concurrency? great stuff. otherwise the language is not ergonomic, the type system alone leaves a lot to be desired. no exception handling, no nil safety, no built in functional programming support over collections
struct tagging, also a terrible design choice. putting a string into an optional field that gets parsed at runtime, when it could have just been inferred and dispatched via it's type (but go doesn't support this)
What’s worse is that the struct tag field doesn’t even have a formal grammar! It’s just parsed by whichever library needs it separately, like json, gorm, etc. and they have to be unique so there’s this informal “well known” tags post in the wiki… https://go.dev/wiki/Well-known-struct-tags
I like the implicit interfaces, I really like the struct system (embedding, etc). I reluctantly like the use of casing for access control. The standard library is nice. I love the backwards compatibility promise, and the “reach for stdlib first” approach
no, I find that its tendency to pretend important details don't exist to be a major source of bugs, so much that we rewrote our primary service that was in Go about a year ago
Do you feel the same about python? For me, both are side-project languages, and for that reason I like the hidden details: no important infrastructure is hung off my weekend doodles.
I think Amos covered this better than I can in a post, but in short:
computers & software are complex, not simple, and go wants to pretend they're simple instead of giving you better tools to manage complexity (2020, so slightly outdated but still basically true)
This is one of the best posts about to ever. People on my teams that have never used go before ask my why I vote against it. And this post just perfectly sums up my experience.
Supposedly things have improved but there are some fundamental issues imo
as for our service, we had crash issues mostly resulting from nil values being dereferenced.
perhaps I should have done a better job reviewing the code, but that's not what I want to spend my time on. I prefer a compiler which does not allow this. I also found error handling to be confusing
You can also deadlock channels easier in Go in ways that “look fine” under normal review and even pass single message tests. Nicely done rust will crash instead
If I could sum it up in one word - simplicity - Go is highly opinionated with very few keywords and lack of variety to achieve the same thing, especially if you are coming from the JS/TS ecosystem.
When I left a Python project to join a Go project (with zero experience, learning as I went), I was in "WTF" mode every day. After a year with Go, I switched back to Python, and the "WTF" moments hit even harder. Now, I really miss Go! 😆
I didn’t write Go for almost a whole year (sabbatical) and I was able to jump straight back in like no time had passed.
By setting guidelines early on (even if not everyone agrees with them), the authors ensured that the language spec remains simple and a Go codebase is always predictable.
I don't write much Go anymore, but back when I was (1.8 - 1.12), it had very few keywords/identifiers, which made it very easy to pick up and hit the ground running with. I also liked that everything compiled into a single binary, a big departure from the C#/.NET work I had been doing at the time.
The fact that they recommend tabs instead of spaces, because tabs are the objectively superior indentation style, and people who use spaces are doin' it wrong.
Once learned the basics, the development speed with it. And the high performance output binary. Also works great for my job, offensive security, reeeeealy well 😎
It's a split between dev experience(overall simple, easy cross platform building, genius package manager) and the concurrency features... oh god the concurrency features. When you get a bunch of chans recv by a select... obscenely satisfying
Its simple, has very few magic sigils and weird syntax, and has an amazing standard library that does pretty much everything i need.
Also the 'go' keyword beats the pants off any other languages concurrency systems
Not strictly about the language, but the 2 best things about go are compilation speed and gofmt (and popularizing auto formatting across the industry).
I love its directness and readability. Can go back to uncommented code I wrote 5 years ago and immediately see what the code does. Also, as someone who learned C in the 90s, it was very easy to learn.
- has no much OO BS
- structs are simple yet useful
- quite easy to learn
- tooling is fast and has great DX
- great support in most editors
- preemptive concurrency
- the lang itself is very small 🙏
Definitely agree with this. But also think this is the reason iterators in 1.23 are catching so much flak. Using them is fine enough. Creating them not so much…
- Errors as values, no obfuscation of control flow.
- Robust standard library.
- Excellent concurrency primitives with channels, goroutines, and the sync package.
- Limited keywords. There is typically only one way to gut a fish, which helps readability.
I didn’t really like it tbh. Overly verbose error handling, weird implicit interface conformance, not enough opinion on code layout for larger projects.
I guess if your other options are the C family or Rust, maybe Go is the easiest to be productive in.
It has an event loop like JavaScript so you don’t have to open a separate thread for network calls and has go routines for multithreading along with being one of the fastest modern programming languages only behind c c++ and (maybe) rust
what's funny is that rumor has it, internally at google the engineers are begging pike et. al to add some of these features but he's held out for the better part of a decade. even generics took an absolutely massive effort internally to get him to accept the proposal
Rob Pike isn't part of the core team anymore, and hasn't been for over a year. He's basically retired. He still has a bunch of clout, but he's stepped away to allow others to lead.
Like most things, adding option types to Go is a nuanced subject looking for an elegant solution.
Simplicity - this is the best.
The language gives a small set of tools, but all of them are useful.
Standard library - little blocks, but I can build from them anything I need.
Also love their gopher and used to have the original version of it on the WFMU T-shirt. I also have a Renee French signed print that my wife thinks is creepy.
- https://golangci-lint.run/
- goimports
- using exceptions (panics) only for exceptional situation (looking at you python, grrrrrr.)
- multiple return types with err and linter that enforces checking it.
- goroutines and channels!
- interfaces
- easy to onboard new colleagues
- rock solid
- cross compile
it’s easy to understand most code written in Go even though I’m not really a Go programmer. Granted with enough experience this is true of many things. But it helps that Go doesn’t give you enough rope to hang yourself. Contrast Java classpath/annotation/reflection madness.
Which is both a blessing and a curse. Java is a relatively restrictive language which gives you a lot of clunky workarounds to make up for it. Go is a relatively restrictive language which doesn’t.
I have not yet coded in Go. But I've worked on projects that implement it, and it looks very clean, approachable, and relatively easy to read. Def in my list of languages to learn.
Coming from Java, Go is easy to pick up, maintain, and cheaper to operate. Small footprint and great performance means lower cloud costs. Standard lib means little to no dependencies.
break
case
chan
const
continue
default
defer
else
fallthrough
for
func
go
goto
if
import
interface
map
package
range
return
select
struct
switch
type
var
Its culture of explicitness. Go taught me that writing things twice (or n times) isn't always a bad thing. It's okay if your request handler has boilerplate for request validation, because it makes the code more obvious to the next person reading the code.
Explicitness is a good thing. Go enforces this by allowing only few means of abstraction into the language. Linguistic austerity is not to everyone's taste – I know I prefer a richer, less paternalistic language.
I like that it feels as a dev like a happy medium between C# and Python. I like that it’s statically typed. I find the way its packages are laid out easy to parse and figure out what another engineer intended. I think the official go documentation is well done
Every choice they made in coming up with this language oozes the Google attitude of "we know better than you and we think you'll like this slop, so eat it up"
The fact that senior devs with 20+ years of experience in coding are excited about it. I envy that and I wanna learn it and see if I can get also excited about it 😅
Unironically the reason I start learning go. Dabble in JS land for too long, want to pick something out just see the go mascot and immediately learn it lmao
True but that comes at a cost of learning a new and more complicated language, if you're an existing js developer moving to bun or deno v2 would be more ideal they're much faster than node as well
I do miss having Rust (or even Java) style enum/sum types though. And I also prefer returning a `Result` type over a multiple returns with the second one being an optional error type.
Dynamic-ish containers - maps (dicts), slices (vectors, resizable arrays) - in a statically typed AOT lang. 90% of what you need for many tasks and feels like Python (ish! don’t want to overstate it)
I feel like the way it's structured encourages consistent patterns between devs, and I like a lot of the code coverage and right click -> generate test DX built into it. I'd use it over python for lighter ingress/egress type services personally.
The dev tool chain. Previously, I would have said something like how simple the syntax is, but I’ve found the real win is the tooling. The stdlib is powerful and growing; the compiler is super fast; built in linting and formatting.
Recently, I’ve come to wish it had a lil more expressiveness.
Came here out of curiosity since I have not worked with Go before, but these arguments in favor of Go are really selling it to me. I can see what it is quite popular
Most of all, how easy it is to onboard people to it. Collaborating with all kinds of people in Go has been the easiest in my experience, especially for open source. It has great defaults, there's no arguing about formatting, the language is relatively small and forgiving, compiles fast, etc.
More nuanced, but I find the language to be more "proportional" than most other languages, and the kind of boilerplate it has is "the good kind". I argue it more thoroughly here: https://shazow.net/posts/code-boilerplate-is-it-always-bad/
I have zero knowledge of systems programming and languages such as C or C++, but I can write a little Go and make a nice little utility. That's pretty sweet. I could never do that in C/C++ and probably not Rust.
Onboarding new devs is super easy for a litany of reasons. It’s just so easy to pick up the language. Once you get the basics, folding in the complex parts like concurrency and channels is also straightforward.
It’s simple to program and pretty much as fast as you can get without manual memory management. Also has a good std lib and sensible built-in toolchain (go fmt, go test)
Simplicity, maintainability, performance, and I'm yet to see another language make concurrency as straight-forward as Go. Also, the type safety is really good, if it compiles, it most likely does exactly what you expect it to do. It's an amazing language for big refactors. OH, also the toolchain.
The language itself is fairly small and can be learned easily, although some concepts like goroutines, channels, and pointers can be confusing if you’ve never encountered those before
I'm also going to say simplicity, but I mean it in a very information theoretic, Bayesian sense. It seems to promote code having lower entropy and better fit to domain complexity than other languages, maybe because of its Bell Labs roots where info theory came from. https://benoitessiambre.com/entropy.html
I like Go packages and would love to see more language adopt traits like no cyclic dependencies between packages, easy organization of private/public/test code in the same directory, and how link/compile performance grows with package size (not codebase size).
I like JavaScript but never managed to catch up with typescript. With go I experienced the value of strong typing and all the tooling that come with it
There's sensible defaults and generally one way to do things- code linting, parameterized tests, for loops amongst others. Opinions feel reasonable- casing for exports, sets as boolean value maps, implement method signature to extend interface. Errors as first class citizen of course.
I definitely missed a few things like structured concurrency, cross compilation support that just work out of the box due to the character limit, but in general, it's a very pleasant experience IME.
After years of wrestling with JS dependencies, I like that I can come back to a Go project that I wrote years ago, the code is still readable and it will compile with little to no issues
Yeah! I still work with JS/TS daily, but it hurts to maintain projects that break whenever you give them downtime.
I think _how_ we code JS/TS stuff changes a lot more frequently too. A lot more reinvention. For example, if I look at Redux now I struggle to pick it apart despite using it for years
Go and Rust have the luxury of native compilation and the long tradition of backward compatibility that it brings, compared to Javascript, which is dependent on browser APIs that may be removed or added at any time. Maybe this has led to a culture of API churn?
Very true. But, like modern JS is still predicated & dominated by build tools & the types of thjngs that will be drastically different even a couple years from now.
It's funny this is my biggest complaint with go, but I started a lot of projects before packages and modules were fully fleshed out so this might be something newer projects never see. I don't love the syntax but I love the opinionated built in tools like go fmt that mean I don't have to care.
I think it is important to distinguish between the language itself and its dependencies. I think JS code itself almost does not rot at all (given that even old websites continue to work). What breaks everything is dependencies, and in addition to that they are heavily overused.
I love the verbosity of logging and error messages, compile size, it's flexibility, want to modify files at a binary level, we got you, want to do http? Also done.
Object-oriented programming (OO) is not entirely an anti-pattern. I completed an OO-based application and implemented the Factory Method pattern. It defines an interface for creating an object but allows subclasses to alter the type of objects that will be created.
so easy to get started. I made a useful program that solved a few system issues in a couple hours. Last time I needed to make a Python project that I wanted to keep I had to learn yet another venv and package management solution (changes every 2 yrs)… 2d6 psychic dmg every time with python
Comments
Its design lends itself well to be very quickly compiled.
bit annoying the go std library recommends patterns which by default allocate to the heap
I even like the error handling pattern that is all over the Go code. I find it so much easier to reason about than js.
computers & software are complex, not simple, and go wants to pretend they're simple instead of giving you better tools to manage complexity (2020, so slightly outdated but still basically true)
Supposedly things have improved but there are some fundamental issues imo
perhaps I should have done a better job reviewing the code, but that's not what I want to spend my time on. I prefer a compiler which does not allow this. I also found error handling to be confusing
go is very elegant but very pragmatic. that good. corporatly good.
I'll see myself out😉
If you want more specifics, I like the design of the concurrency and how interfaces work. More languages should do interfaces like Go does.
By setting guidelines early on (even if not everyone agrees with them), the authors ensured that the language spec remains simple and a Go codebase is always predictable.
:=
p := fmt.Println
p(“Hello World!”)
Also the 'go' keyword beats the pants off any other languages concurrency systems
simple
100% replacement for python
The compile time
🤡
- has no much OO BS
- structs are simple yet useful
- quite easy to learn
- tooling is fast and has great DX
- great support in most editors
- preemptive concurrency
- the lang itself is very small 🙏
2. I only have to remember about four concepts to be productive: if, for, struct and func.
It knew what it wanted to be and stayed strictly in that lane.
- Errors as values, no obfuscation of control flow.
- Robust standard library.
- Excellent concurrency primitives with channels, goroutines, and the sync package.
- Limited keywords. There is typically only one way to gut a fish, which helps readability.
I guess if your other options are the C family or Rust, maybe Go is the easiest to be productive in.
Being able to drill into the stdlib and read the implementation is also pretty neat
It's weird that its error handling pattern is ideal for this but they stay clear of it. It's embarrasing to have nil pointer deference in 2024 😭
Like most things, adding option types to Go is a nuanced subject looking for an elegant solution.
this sometimes bites new colleagues who come from python,
and have no experience with c.
Easy to avoid with a little discipline, but still, non-nullability in the style of dart would have been nice.
The language gives a small set of tools, but all of them are useful.
Standard library - little blocks, but I can build from them anything I need.
- goimports
- using exceptions (panics) only for exceptional situation (looking at you python, grrrrrr.)
- multiple return types with err and linter that enforces checking it.
- goroutines and channels!
- interfaces
- easy to onboard new colleagues
- rock solid
- cross compile
It would be even cooler if it could jump right into the Go Assembly sources and handled platform–dependent sources, but these are relative edge cases.
That being said, Go channels were pretty revolutionary at the time. Also: duck typing in a compiled language.
break
case
chan
const
continue
default
defer
else
fallthrough
for
func
go
goto
if
import
interface
map
package
range
return
select
struct
switch
type
var
Contrast C++, where it might take me a week of study.
And the sane default of the standard library.
Syntax… who cares.
And the mascot
pretty easy to do large refactors with the type system
Being able to update language and libraries version without pain is amazing
Creators and community focus is to make things easy to understand instead of creating never-ending hype with new features.
I love the fact that my servers are now tiny, like 7MB, compared to Node.js and Ruby on Rails.
I’ve seen the language prioritize backwards compatibility while adding features. This ethos is also in the packages.
This enabled our very large code base and many microservices to stay on the latest Go version and stay evergreen.
Recently, I’ve come to wish it had a lil more expressiveness.
- I like that it makes you think about error handling upfront and handling error values.
- It has a very comprehensive standard library that’s ideal for web.
- Cross compilation is op.
- Built in testing and benchmarking.
- Gophers.
Usage of Go is usually practical. It's not frivolously thrown everywhere just because.
Which for the longest time was the main reason why I avoided it. Now it's the main reason why I love it.
*if you avoid `cgo`
And the tooling is top notch. Not everyone agrees with go fmt's output but everyone agrees that go fmt is a good thing, for example.
i can see why people longer in the tooth with the language might dislike it
I also really like cross-compilation -- makes Go my favorite tool for building quick little CLI utils.
Shipping zero-dependency binaries is fun.
But my favorite part has to be its excellent standard library. You can go incredibly far without having to pull in other modules.
It is a credo.
JS is entirely another story…
I never really thought about it, but now that I did… yeah, getting old JS code to run is often hell.
I think _how_ we code JS/TS stuff changes a lot more frequently too. A lot more reinvention. For example, if I look at Redux now I struggle to pick it apart despite using it for years
If you wrote JS that directly runs in a browser with no transformation (and no vendor specific APIs) it will run going forwards without issues.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Deprecated_and_obsolete_features#obsolete_features
The language itself is meh
…or PLM or Coral66!
structs with methods,
single responsibility principle.
BUT, C++ style classes are in between golang packages and golang structs, e.g. for public private.
Also, polymorphism with interfaces. Composition not inheritance. You will love it
- No "magic"
- Low barrier of entry (kind of the result of the first two)
- Small binaries (and footprint in general)
Imo it's a really good compromise between performance and simplicity.