Skip to content

Commit

Permalink
README/rss: update
Browse files Browse the repository at this point in the history
  • Loading branch information
thiagokokada authored and github-actions[bot] committed Jul 30, 2024
1 parent 6294e60 commit 47717e2
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion rss.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<item>
<title>Go, a reasonable good language</title>
<link>https://github.com/thiagokokada/blog/blob/main/2024-07-29/02-go-a-reasonable-good-language.md</link>
<description>&lt;p&gt;Go was one of the languages that I always was interested to learn, but never&#xA;got the hang of it. I first got interested in the language when I was in my&#xA;first job, between 2016-2018. At the time the language was a completely&#xA;different beast: no modules, no generics, no easy way to error wrap yet, etc.&lt;/p&gt;&#xA;&lt;p&gt;Go forward 2023 (no pun indented), I wrote my &lt;a href=&#34;https://github.com/thiagokokada/twenty-twenty-twenty/&#34;&gt;first project in&#xA;Go&lt;/a&gt;, wrote some scripts&#xA;at &lt;code&gt;$CURRENT_JOB&lt;/code&gt; in the language, and now wrote &lt;a href=&#34;https://github.com/thiagokokada/hyprland-go/&#34;&gt;my first&#xA;library&lt;/a&gt;. I am also writing more&#xA;&lt;a href=&#34;https://github.com/thiagokokada/nix-configs/blob/8c559527ed12e1d4f57a3fc5c72630b956f4c290/home-manager/desktop/wayland/hyprland/hyprtabs/hyprtabs.go&#34;&gt;scripts&lt;/a&gt;&#xA;in the language, where I would prefer to use Bash or Python before. Heck, even&#xA;this blog is automatically published with a &lt;a href=&#34;https://github.com/thiagokokada/blog/blob/main/2024-07-29/01-quick-bits-why-you-should-automate-everything.md&#34;&gt;Go&#xA;script&lt;/a&gt;, that&#xA;used to be a &lt;a href=&#34;https://github.com/thiagokokada/blog/blob/main/2024-07-26/02-using-github-as-a-bad-blog-platform.md&#34;&gt;Python&#xA;one&lt;/a&gt; before. I can say&#xA;that nowadays it is another language in my toolbox, and while it is still a&#xA;love and hate relationship, recently it is more about love and less about hate.&lt;/p&gt;&#xA;&lt;p&gt;The points that I love about Go is probably obvious for some, but still&#xA;interesting to talk about anyway. The fact that the language generates static&#xA;binaries by default and have fast compilation times is something that I&#xA;apreciate since I first heard about the language, and now that I am using the&#xA;language frequently are points I appreciate even more. Something about getting&#xA;almost instant feedback after changing a line of code and running &lt;code&gt;go run&lt;/code&gt;&#xA;(even with its quirks) are great for the developer experience. This is the main&#xA;reason why I am using the language more frequently for scripts.&lt;/p&gt;&#xA;&lt;p&gt;Then we have the fast startup times. I am kind of sensitive to latency,&#xA;especially of command line utilities that need to answer fast when I expect&#xA;them to be fast (e.g.: &lt;code&gt;foo --help&lt;/code&gt;). This is one part where I could have&#xA;issues in Python, especially for more complex programs, but in Go it is rarely&#xA;an issue.&lt;/p&gt;&#xA;&lt;p&gt;Modules are also fantastic. It is not without its weirdness (like everything in&#xA;Go ecossystem), but the fact that it is so easy to add and manage dependencies&#xA;in a project using only the &lt;code&gt;go&lt;/code&gt; CLI is great. I also like that it generates a&#xA;hash of every dependency, make it reproducible (well, probably not at Nix&#xA;level, but still reproducible).&lt;/p&gt;&#xA;&lt;p&gt;Since I started to talk about &lt;code&gt;go&lt;/code&gt; CLI, what a great tool! The fact that you&#xA;can manage dependencies, generate documentation, format code, lint, run tests,&#xA;etc., all with just the &amp;quot;compiler&amp;quot; for the language is excelent. Still probably&#xA;one of the best developer experiences I know in any programming language (maybe&#xA;only rivaled by &lt;a href=&#34;https://ziglang.org/&#34;&gt;Zig&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;p&gt;I will not even talk about the things that everyone talks about Go, like&#xA;&lt;a href=&#34;https://go.dev/doc/effective_go#goroutines&#34;&gt;goroutines&lt;/a&gt;, because I just don&#39;t&#xA;think I can add anything interesting to the topic.&lt;/p&gt;&#xA;&lt;p&gt;Now for the parts that I like less, the test part still quirks me that it is&#xA;not based in assertions, but thankfully it is easy to write assertions with&#xA;generics nowadays:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func Equal[T comparable](t *testing.T, got, want T) {&#xA;&#x9;t.Helper()&#xA;&#x9;if got != want {&#xA;&#x9;&#x9;t.Errorf(&amp;quot;got: %#v, want: %#v&amp;quot;, got, want)&#xA;&#x9;}&#xA;}&#xA;&#xA;func GreaterOrEqual[T cmp.Ordered](t *testing.T, actual, expected T) {&#xA;&#x9;t.Helper()&#xA;&#x9;if actual &amp;lt; expected {&#xA;&#x9;&#x9;t.Errorf(&amp;quot;got: %v; want: &amp;gt;=%v&amp;quot;, actual, expected)&#xA;&#x9;}&#xA;}&#xA;&#xA;// etc...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Just one of those things that I end up re-writing in every project. Yes, I know&#xA;about &lt;a href=&#34;https://github.com/stretchr/testify&#34;&gt;testify&lt;/a&gt; and other assertion&#xA;libraries, but quoting &lt;a href=&#34;https://www.youtube.com/watch?v=PAAkCSZUG1c&amp;amp;t=568s&#34;&gt;Rob&#xA;Pike&lt;/a&gt; here, &amp;quot;a little&#xA;copying is better than a little dependency&amp;quot;. As long the code you write is&#xA;trivial, it is better to duplicate the code than try to import a dependency.&lt;/p&gt;&#xA;&lt;p&gt;About another piece of code that generics allows me to write and I always end&#xA;up re-writing in every project is the &lt;code&gt;must*&lt;/code&gt; family of functions:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func must(err error) {&#xA;&#x9;if err != nil {&#xA;&#x9;&#x9;panic(err)&#xA;&#x9;}&#xA;}&#xA;&#xA;func must1[T any](v T, err error) T {&#xA;&#x9;must(err)&#xA;&#x9;return v&#xA;}&#xA;&#xA;func must2[T1 any, T2 any](v1 T1, v2 T2, err error) T {&#xA;&#x9;must(err)&#xA;&#x9;return v1, v2&#xA;}&#xA;&#xA;// must3, must4, etc...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Those functions are so useful, especially for scripts where I generally don&#39;t&#xA;want to handle each error: if I have an error, I want the program to halt and&#xA;print a stack trace (exactly as I would have with a language with exceptions).&#xA;It basically allow me to convert code from:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;contents, err := os.ReadFile(&amp;quot;file&amp;quot;)&#xA;if err != nil {&#xA; panic(err)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;To:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;contents := must1(os.ReadFile(&amp;quot;file&amp;quot;))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;This brings Go closer to Python to me, and I think for scripts this is&#xA;something great.&lt;/p&gt;&#xA;&lt;p&gt;Finally, for the things that I hate, well the biggest one currently is the lack&#xA;of nullability (or in Go terms,&#xA;&lt;a href=&#34;https://github.com/golang/go/issues/49202&#34;&gt;nillability&lt;/a&gt;). After using&#xA;languages that has it, like Kotlin, or even something like&#xA;&lt;a href=&#34;https://www.mypy-lang.org/&#34;&gt;mypy&lt;/a&gt;, this is one of those things that completely&#xA;changes the developer experience. I also still don&#39;t like the error handling&#xA;(but &lt;code&gt;must*&lt;/code&gt; goes far by improving the situation, when it is possible to use&#xA;it), especially because it is easy to lose context on it:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;// bad&#xA;func readFileContents(file) ([]byte, error) {&#xA; contents, err := os.ReadFile(file)&#xA; if err != nil {&#xA; return nil, err&#xA; }&#xA; return contents, nil&#xA;}&#xA;&#xA;// good&#xA;func readFileContents(file) ([]byte, error) {&#xA; contents, err := os.ReadFile(file)&#xA; if err != nil {&#xA; return nil, fmt.Errorf(&amp;quot;readFileContents: error while reading a file: %w&amp;quot;, err)&#xA; }&#xA; return contents, nil&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I also have some grips about the mutate everything approach of the language. I&#xA;prefer immutability by default, but I find that in general as long as you split&#xA;your functions at a reasonable size it is generally fine.&lt;/p&gt;&#xA;&lt;p&gt;And for a language that is supposed to be straightforward, it is strange on how&#xA;much magic the language relies on, in the form of things like &lt;a href=&#34;https://go.dev/doc/modules/layout&#34;&gt;&lt;code&gt;internal&lt;/code&gt; and&#xA;&lt;code&gt;main&lt;/code&gt;&lt;/a&gt; packages, name capitalisation to&#xA;indicate visibility (&lt;code&gt;private&lt;/code&gt; vs &lt;code&gt;Public&lt;/code&gt;), conditional compiling by filenames&#xA;(e.g.: &lt;code&gt;foo_amd64.go&lt;/code&gt;, &lt;code&gt;bar_linux.go&lt;/code&gt;), magic comments (e.g.: &lt;code&gt;//go:build&lt;/code&gt;),&#xA;etc.&lt;/p&gt;&#xA;&lt;p&gt;I expect to write more Go code going forward. Not because it is the perfect&#xA;language or whatever, but just because it a is language that has some really&#xA;good qualities that makes the language attractive even with the issues that I&#xA;have. That makes it a reasonable good language, and at least for me this is&#xA;good enough.&lt;/p&gt;&#xA;</description>
<description>&lt;p&gt;Go was one of the languages that I always was interested to learn, but never&#xA;got the hang of it. I first got interested in the language when I was in my&#xA;first job, between 2016-2018. At the time the language was a completely&#xA;different beast: no modules, no generics, no easy way to error wrap yet, etc.&lt;/p&gt;&#xA;&lt;p&gt;Go forward 2023 (no pun indented), I wrote my &lt;a href=&#34;https://github.com/thiagokokada/twenty-twenty-twenty/&#34;&gt;first project in&#xA;Go&lt;/a&gt;, wrote some scripts&#xA;at &lt;code&gt;$CURRENT_JOB&lt;/code&gt; in the language, and now wrote &lt;a href=&#34;https://github.com/thiagokokada/hyprland-go/&#34;&gt;my first&#xA;library&lt;/a&gt;. I am also writing more&#xA;&lt;a href=&#34;https://github.com/thiagokokada/nix-configs/blob/8c559527ed12e1d4f57a3fc5c72630b956f4c290/home-manager/desktop/wayland/hyprland/hyprtabs/hyprtabs.go&#34;&gt;scripts&lt;/a&gt;&#xA;in the language, where I would prefer to use Bash or Python before. Heck, even&#xA;this blog is automatically published with a &lt;a href=&#34;https://github.com/thiagokokada/blog/blob/main/2024-07-29/01-quick-bits-why-you-should-automate-everything.md&#34;&gt;Go&#xA;script&lt;/a&gt;, that&#xA;used to be a &lt;a href=&#34;https://github.com/thiagokokada/blog/blob/main/2024-07-26/02-using-github-as-a-bad-blog-platform.md&#34;&gt;Python&#xA;one&lt;/a&gt; before. I can say&#xA;that nowadays it is another language in my toolbox, and while it is still a&#xA;love and hate relationship, recently it is more about love and less about hate.&lt;/p&gt;&#xA;&lt;p&gt;The points that I love about Go is probably obvious for some, but still&#xA;interesting to talk about anyway. The fact that the language generates static&#xA;binaries by default and have fast compilation times is something that I&#xA;apreciate since I first heard about the language, and now that I am using the&#xA;language frequently are points I appreciate even more. Something about getting&#xA;almost instant feedback after changing a line of code and running &lt;code&gt;go run&lt;/code&gt;&#xA;(even with its quirks) are great for the developer experience. This is the main&#xA;reason why I am using the language more frequently for scripts.&lt;/p&gt;&#xA;&lt;p&gt;Then we have the fast startup times. I am kind of sensitive to latency,&#xA;especially of command line utilities that need to answer fast when I expect&#xA;them to be fast (e.g.: &lt;code&gt;foo --help&lt;/code&gt;). This is one part where I could have&#xA;issues in Python, especially for more complex programs, but in Go it is rarely&#xA;an issue.&lt;/p&gt;&#xA;&lt;p&gt;Modules are also fantastic. It is not without its weirdness (like everything in&#xA;Go ecossystem), but the fact that it is so easy to add and manage dependencies&#xA;in a project using only the &lt;code&gt;go&lt;/code&gt; CLI is great. I also like that it generates a&#xA;hash of every dependency, make it reproducible (well, probably not at Nix&#xA;level, but still reproducible).&lt;/p&gt;&#xA;&lt;p&gt;Since I started to talk about &lt;code&gt;go&lt;/code&gt; CLI, what a great tool! The fact that you&#xA;can manage dependencies, generate documentation, format code, lint, run&#xA;tests/&lt;a href=&#34;https://blog.logrocket.com/benchmarking-golang-improve-function-performance/&#34;&gt;benchmarks&lt;/a&gt;/&lt;a href=&#34;https://go.dev/doc/security/fuzz/&#34;&gt;fuzzing&lt;/a&gt;,&#xA;check code for &lt;a href=&#34;https://go.dev/doc/articles/race_detector&#34;&gt;races&lt;/a&gt; etc., all&#xA;with just the &amp;quot;compiler&amp;quot; for the language is excelent. Still probably one of&#xA;the best developer experiences I know in any programming language (maybe only&#xA;rivaled by &lt;a href=&#34;https://ziglang.org/&#34;&gt;Zig&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;p&gt;I will not even talk about the things that everyone talks about Go, like&#xA;&lt;a href=&#34;https://go.dev/doc/effective_go#goroutines&#34;&gt;goroutines&lt;/a&gt;, because I just don&#39;t&#xA;think I can add anything interesting to the topic.&lt;/p&gt;&#xA;&lt;p&gt;Now for the parts that I like less, the test part still quirks me that it is&#xA;not based in assertions, but thankfully it is easy to write assertions with&#xA;generics nowadays:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func Equal[T comparable](t *testing.T, got, want T) {&#xA;&#x9;t.Helper()&#xA;&#x9;if got != want {&#xA;&#x9;&#x9;t.Errorf(&amp;quot;got: %#v, want: %#v&amp;quot;, got, want)&#xA;&#x9;}&#xA;}&#xA;&#xA;func GreaterOrEqual[T cmp.Ordered](t *testing.T, actual, expected T) {&#xA;&#x9;t.Helper()&#xA;&#x9;if actual &amp;lt; expected {&#xA;&#x9;&#x9;t.Errorf(&amp;quot;got: %v; want: &amp;gt;=%v&amp;quot;, actual, expected)&#xA;&#x9;}&#xA;}&#xA;&#xA;// etc...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Just one of those things that I end up re-writing in every project. Yes, I know&#xA;about &lt;a href=&#34;https://github.com/stretchr/testify&#34;&gt;testify&lt;/a&gt; and other assertion&#xA;libraries, but quoting &lt;a href=&#34;https://www.youtube.com/watch?v=PAAkCSZUG1c&amp;amp;t=568s&#34;&gt;Rob&#xA;Pike&lt;/a&gt; here, &amp;quot;a little&#xA;copying is better than a little dependency&amp;quot;. As long the code you write is&#xA;trivial, it is better to duplicate the code than try to import a dependency.&lt;/p&gt;&#xA;&lt;p&gt;About another piece of code that generics allows me to write and I always end&#xA;up re-writing in every project is the &lt;code&gt;must*&lt;/code&gt; family of functions:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;func must(err error) {&#xA;&#x9;if err != nil {&#xA;&#x9;&#x9;panic(err)&#xA;&#x9;}&#xA;}&#xA;&#xA;func must1[T any](v T, err error) T {&#xA;&#x9;must(err)&#xA;&#x9;return v&#xA;}&#xA;&#xA;func must2[T1 any, T2 any](v1 T1, v2 T2, err error) T {&#xA;&#x9;must(err)&#xA;&#x9;return v1, v2&#xA;}&#xA;&#xA;// must3, must4, etc...&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Those functions are so useful, especially for scripts where I generally don&#39;t&#xA;want to handle each error: if I have an error, I want the program to halt and&#xA;print a stack trace (exactly as I would have with a language with exceptions).&#xA;It basically allow me to convert code from:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;contents, err := os.ReadFile(&amp;quot;file&amp;quot;)&#xA;if err != nil {&#xA; panic(err)&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;To:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;contents := must1(os.ReadFile(&amp;quot;file&amp;quot;))&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;This brings Go closer to Python to me, and I think for scripts this is&#xA;something great.&lt;/p&gt;&#xA;&lt;p&gt;Finally, for the things that I hate, well the biggest one currently is the lack&#xA;of nullability (or in Go terms,&#xA;&lt;a href=&#34;https://github.com/golang/go/issues/49202&#34;&gt;nillability&lt;/a&gt;). After using&#xA;languages that has it, like Kotlin, or even something like&#xA;&lt;a href=&#34;https://www.mypy-lang.org/&#34;&gt;mypy&lt;/a&gt;, this is one of those things that completely&#xA;changes the developer experience. I also still don&#39;t like the error handling&#xA;(but &lt;code&gt;must*&lt;/code&gt; goes far by improving the situation, when it is possible to use&#xA;it), especially because it is easy to lose context on it:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-go&#34;&gt;// bad&#xA;func readFileContents(file) ([]byte, error) {&#xA; contents, err := os.ReadFile(file)&#xA; if err != nil {&#xA; return nil, err&#xA; }&#xA; return contents, nil&#xA;}&#xA;&#xA;// good&#xA;func readFileContents(file) ([]byte, error) {&#xA; contents, err := os.ReadFile(file)&#xA; if err != nil {&#xA; return nil, fmt.Errorf(&amp;quot;readFileContents: error while reading a file: %w&amp;quot;, err)&#xA; }&#xA; return contents, nil&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;I also have some grips about the mutate everything approach of the language. I&#xA;prefer immutability by default, but I find that in general as long as you split&#xA;your functions at a reasonable size it is generally fine.&lt;/p&gt;&#xA;&lt;p&gt;And for a language that is supposed to be straightforward, it is strange on how&#xA;much magic the language relies on, in the form of things like &lt;a href=&#34;https://go.dev/doc/modules/layout&#34;&gt;&lt;code&gt;internal&lt;/code&gt; and&#xA;&lt;code&gt;main&lt;/code&gt;&lt;/a&gt; packages, name capitalisation to&#xA;indicate visibility (&lt;code&gt;private&lt;/code&gt; vs &lt;code&gt;Public&lt;/code&gt;), conditional compiling by filenames&#xA;(e.g.: &lt;code&gt;foo_amd64.go&lt;/code&gt;, &lt;code&gt;bar_linux.go&lt;/code&gt;), magic comments (e.g.: &lt;code&gt;//go:build&lt;/code&gt;),&#xA;etc.&lt;/p&gt;&#xA;&lt;p&gt;I expect to write more Go code going forward. Not because it is the perfect&#xA;language or whatever, but just because it a is language that has some really&#xA;good qualities that makes the language attractive even with the issues that I&#xA;have. That makes it a reasonable good language, and at least for me this is&#xA;good enough.&lt;/p&gt;&#xA;</description>
<guid>https://github.com/thiagokokada/blog/blob/main/2024-07-29/02-go-a-reasonable-good-language.md</guid>
<pubDate>Mon, 29 Jul 2024 00:00:00 +0000</pubDate>
</item>
Expand Down

0 comments on commit 47717e2

Please sign in to comment.