I know they say that your programming language isn't the bottleneck, but I remember sitting there being frustrated as a young dev that I couldn't parse faster in the languages I was using when I learned about Go.
It took a few more years before I actually got around to learning it and I have to say I've never picked up a language so quickly. (Which makes sense, it's got the smallest language spec of any of them)
I'm sure there are plenty of reasons this is wrong, but it feels like Go gets me 80% of the way to Rust with 20% of the effort.
The nice thing about Go is that you can learn "all of it" in a reasonable amount of time: gotchas, concurrency stuff, everything. There is something very comforting about knowing the entire spec of a language.
I'm convinced no more than a handful of humans understand all of C# or C++, and inevitably you'll come across some obscure thing and have to context switch out of reading code to learn whatever the fuck a "partial method" or "generic delegate" means, and then keep reading that codebase if you still have momentum left.
Well that's good, since Go was specifically designed for juniors.
From Rob Pike himself: "It must be familiar, roughly C-like. Programmers working at Google are early in their careers and are most familiar with procedural languages, particularly from the C family. The need to get programmers productive quickly in a new language means that the language cannot be too radical."
However, the main design goal was to reduce build times at Google. This is why unused dependencies are a compile time error.
I write a lot of Go, a bit of Rust, and Zig is slowly creeping in.
To add to the above comment, a lot of what Go does encourages readability... Yes it feels pedantic at moments (error handling), but those cultural, and stylistic elements that seem painful to write make reading better.
Portable binaries are a blessing, fast compile times, and the choices made around 3rd party libraries and vendoring are all just icing on the cake.
That 80 percent feeling is more than just the language, as written, its all the things that come along with it...
> Which makes sense, it's got the smallest language spec of any of them
I think go is fairly small, too, but “size of spec” is not always a good measure for that. Some specs are very tight, others fairly loose, and tightness makes specs larger (example: Swift’s language reference doesn’t even claim to define the full language. https://docs.swift.org/swift-book/documentation/the-swift-pr...: “The grammar described here is intended to help you understand the language in more detail, rather than to allow you to directly implement a parser or compiler.”)
I don't understand the framing you have here, of Rust being an asymptote of language capability. It isn't. It's its own set of tradeoffs. In 2025, it would not make much sense to write a browser in Go. But there are a lot of network services it doesn't really make sense to write in Rust: you give up a lot (colored functions, the borrow checker) to avoid GC and goroutines.
Rust is great. One of the stupidest things in modern programming practice is the slapfight between these two language communities.
Language can be bottleneck if there's something huge missing from it that you need, like how many of them didn't have first class support for cooperative multitasking, or maybe you need it to be compiled, or not compiled, or GC vs no GC. Go started out with solid greenthreading, while afaik no major lang/runtime had something comparable at the time (Java now does supposedly).
The thing people tend to overvalue is the little syntax differences, like how Scala wanted to be a nicer Java, or even ObjC vs Swift before the latter got async/await.
Similar story for me. I was looking for a language that just got out of the way. That didn’t require me to learn a full imparable DSL just to add a few dependencies and which could easily produce some artifact that I could share around without needing to make sure the target machine had all the right dependencies installed.
It really is a lovely language and ecosystem of tools, I think it does show its limitations fairly quickly when you want to build something a bit complex though. Really wish they would have added sumtypes
Funny thing is that also makes it easier on LLM / AI... Tried a project a while ago both creating the same thing in Rust and Go. Go's worked from the start, while Rust's version needed a lot of LLM interventions and fixes to get it to compile.
We shall not talk about compile time / resource usage differences ;)
I mean, Rust is nice, but compared to when i learned it like 10 years ago, it really looks a lot more these days, like it took too much of a que from C++.
While Go syntax is still the same as it was 10 years ago with barely anything new. What may anger people but even so...
The only thing i love to see is reduce executable sizes because pushing large executables on a dinky upload line, to remove testing is not fun.
> I'm sure there are plenty of reasons this is wrong, but it feels like Go gets me 80% of the way to Rust with 20% of the effort.
I don't see it. Can you say what 80% you feel like you're getting?
The type system doesn't feel anything alike, I guess the syntax is alike in the sense that Go is a semi-colon language and Rust though actually basically an ML deliberately dresses as a semi-colon language but otherwise not really. They're both relatively modern, so you get decent tooling out of the box.
But this feels a bit like if somebody told me that this new pizza restaurant does a cheese pizza that's 80% similar to the Duck Ho Fun from that little place near the extremely tacky student bar. Duck Ho Fun doesn't have nothing in common with cheese pizza, they're both best (in my opinion) if cooked very quickly with high heat - but there's not a lot of commonality.
I love Go. One thing I haven't seen noted here is how great it is for use in monorepos. Adding a new application is just a matter of making a folder and putting a main packaged go file with a main() func. Running go install at the root ./.. takes care of compiling everything quickly and easily.
This combined with the ease of building CLI programs has been an absolute godsend in the past when I've had to quickly spin up CLI tools which use business logic code to fix things.
The Go codebases look all alike.
Not only the language has really few primitives but also the code conventions enforced by standard library, gofmt, and golangci-lint implies that the structure of code bases are very similar.
Many language communities can't even agree on the build tooling.
I'm still trying to convince the scientists I work with that they should format their code or use linters. Making them mandatory in Go was a good decision.
i've just started learning Go and i really like this aspect. one way to do things, one way to format.. the % operator is a bit confusing for a negative number - that took me down a little rabbit-hole, learning about how a remainder can be different to how i normally think about it.
One thing I don't like when it comes to Golang jobs - it is rare to see pure software engineering positions. For some reason, most Go jobs requirements include AWS, Kubernetes/Docker, CI/CD setup, etc... DevOps stuff, which is not the case for positions in other stacks.
The introduction of automatic code modernizers to keep legacy code up to date with modern Go idioms is interesting:
> With gopls v0.18.0, we began exploring automatic code modernizers. As Go evolves, every release brings new capabilities and new idioms; new and better ways to do things that Go programmers have been finding other ways to do. Go stands by its compatibility promise—the old way will continue to work in perpetuity—but nevertheless this creates a bifurcation between old idioms and new idioms. Modernizers are static analysis tools that recognize old idioms and suggest faster, more readable, more secure, more modern replacements, and do so with push-button reliability. What gofmt did for stylistic consistency, we hope modernizers can do for idiomatic consistency.
Modernizers seem like a way make Large-Scale Changes (LSCs) more available to the masses. Google has internal tooling to support them [1], but now Go users get a limited form of opt-in LSC support whenever modernizers make a suggestion.
I was very skeptical of Go when I started learning it, but it quickly became my favourite language. I like how simple but powerful it is.
If I had a magic wand, the only things I would add is better nulability checks, add stack traces by default for errors, and exhaustive checks for sum types. Other than that, it does everything I want.
I like Go. Coming from Python, I appreciate having most things be explicit in nature vs. magical, and having concurrency not feel like a bolted on nightmare.
Writing microservices at $DAYJOB feels far easier and less guess-work, even if it requires more upfront code, because it’s clear what each piece does and why.
Go would probably be my favorite language if it just had a few more features around functional programming. Specifically around immutability and nullness, and maybe exhaustive switch statements. Then it just might be perfect.
At work we use Uber’s NillAway, so that helps bit. https://github.com/uber-go/nilaway Though actually having the type system handle it would be nicer.
Go with Sum types and no nil pointers would be fantastic! Is it too much to dream of?
It feels like Gleam gets pretty close but it flies off in a bunch of other directions.
Go is my favorite programming language. I remember when I first found Go and it was because I was using Java back then and learnign Akka framework for concurrent programming . I realized Go was so much less code compared to Java and I could understand it effortlessly. Since then I have been using it very regularly but still I don't feel I am good at this language. But it helps me get the work done. Cheers to the 16th anniversary of Go.
I use Go every day at work and it's still the first thing I reach for when completing personal projects. It gets better every year. Keep up the good work Go team!
I tried to use go in a project 6-7 years ago and was kind of shocked by needing to fetch packages directly from source control with a real absence of built in versioning. That turned me off and I went back to python. I gather that now there’s a new system with go modules. I should probably revisit it.
I love Go. It makes that I get shit done. I picked up Go more than ten years ago, because it was HN’s darling and when I didn’t know about hype cycles. No regrets.
To me, Go is like Rust oversimplified beyond reason. It edits your code when you don't ask, removing things you just started; it lacks iterators -- every time you must write a big cycle instead. It lacks simple things like check if a key exists in a map.
Proponents say it has nothing under the hood. I see under-the-hood-magic happen every time.
1) The arrays append is one example. Try removing an element from an array - you must rely on some magic and awkward syntax, and there's no clear explanation what actually happens under the hood (all docs just show you that a slice is a pointer to a piece of vector).
2) enums creation is just nonsense
3) To make matters worse, at work we have a linter that forbids merging a branch if you a) don't do if err != nil for every case b) have >20 for & if/else clauses. This makes you split functions in many pieces, turning your code into enterprise Java.
It feels like, to implement same things, Go is 2x slower than in Rust.
On the positive side,
* interfaces are simpler, without some stricter Rust's limitations; the only problem with them is that in the using code, you can't tell one from a struct
* it's really fast to pick up, I needed just couple of days to see examples and start coding stuff.
I think Go would have been great with
* proper enums (I'll be fine if they have no wrapped data)
* sensible arrays & slices, without any magic and awkward syntax
One thing Go took from C that I dislike: overly short variable names (like in interface names when implementing function are usually 1 or 2 letters, but also chan!).
Other random things I hate:
- first element in a struct, if unnamed, acts like extending a struct;
- private/public fields of method based on capitalisation (it makes json mapping to a struct have so much boilerplate);
- default json lib being so inept with collections: an empty slice is serialised as null/absent (empty list is not absence of a list, WTF, but the new json lib promises to fix that json crap);
- error type being special, and not working well with chanels;
- lambda syntax is verbose;
- panics (especially the ones in libs);
- using internal proxy in companies for packages download is very fiddly, and sucks.
But, the tooling is pretty good and fast, I won’t lie. The language won’t win beauty contests for sure, but it mostly does the job. Still weak at building http servers (limited http server libs with good default headers, very limited openapi spec support).
I worked on a toy programming language (that compile down to golang), which is a fork of the go lexer/parser, but it changes how functions can only return one value allowing the use of Result[T]/Option[T] and error propagation operators `!` and `?`.
It has enums (sum type), tuple, built-in Set[T], and good Iterator methods. It has very nice type inferred lambda function (heavily inspired by the swift syntax)... lots of good stuff!
Go has iterators, had them for a while now. To delete an element from a slice you can use `slices.Delete`.
>3) To make matters worse, at work we have a linter that forbids merging a branch if you a) don't do if err != nil for every case b) have >20 for & if/else clauses. This makes you split functions in many pieces, turning your code into enterprise Java.
> It lacks simple things like check if a key exists in a map.
What? `value, keyExists := myMap[someKey]`
> Try removing an element from an array - you must rely on some magic and awkward syntax, and there's no clear explanation what actually happens under the hood (all docs just show you that a slice is a pointer to a piece of vector).
First of all, if you're removing elements from the middle of an array, you're using the wrong data structure 99% of the time. If you're doing that in a loop, you're hitting degenerate performance.
I used to do Go in production for several years, along with Java and TypeScript event-loop backends. It was a breeze of fresh air, especially for new projects, where the Java conventions could be put to rest. But in such an environment, with mostly Java legacy, people did tend to bend Go to the Java idioms rendering the PR reviews very cumbersome.
From what I’ve experienced, if you need any fine-grained control over your data or allocations, precision on the type level, expressing nontrivial algorithms, Go is just too clumsy.
The more I read about how people use Go today and what issues people still have, the more I’m happy I picked Rust for almost everything. I even find it much more productive to write scripts in Rust than in Python or shell script. You just get it right very quickly and you don’t need to care about the idiosyncrasies of ancient tech debt that would otherwise creep into your new projects. And of course the outcome is way more maintainable.
Not saying that Rust hadn’t had its own warts, but most of them are made explicit. This is perhaps what I appreciate the most.
Intuitively, however, I still notice myself creating a new Python or shell script file when I need something quick, but then something doesn’t really work well the moment the logic gets a bit more complex, and I need to backtrack and refactor. With Rust, this hasn’t been an issue in my experience.
And intuitively, I still tend to think in Java terms when designing. It’s funny how it sticks for so long. And when writing some Java, I miss Go’s use-site interfaces and TypeScript’s structural typing, while I miss nominal typing in TypeScript. It’s just maybe that you get used to workarounds and idiosyncrasies in some system and then carry them over to another paradigms.
I do like Go’s value propositions, and lots of its warts have been sorted out, but I’m just not as productive in it for my use cases as I am with Rust. It just checks way more boxes with me.
It has proper enums. Granted, it lacks an enum keyword, which seems to trip up many.
Perhaps what you are actually looking for is sum types? Given that you mentioned Rust, which weirdly[1] uses the enum keyword for sum types, this seems likely. Go does indeed lack that. Sum types are not enums, though.
> sensible arrays & slices, without any magic and awkward syntax
Its arrays and slices are exactly the same as how you would find it in C. So it is true that confuses many coming from languages that wrap them in incredible amounts of magic, but the issue you point to here is actually a lack of magic. Any improvements to help those who are accustomed to magic would require adding magic, not taking it away.
> iterators
Is there something about them that you find lacking? They don't seem really any different than iterators in other languages that I can see, although I'll grant you that the anonymous function pattern is a bit unconventional. It is fine, though.
> result unwrapping shorthands
Go wants to add this, and has been trying to for years, but nobody has explained how to do it sensibly. There are all kinds of surface solutions that get 50% of the way there, but nobody wants to tackle the other 50%. You can't force someone to roll up their sleeves, I guess.
[1] Rust uses enums to generate the sum type tag as an implementation detail, so its not quite as weird as it originally seems, but still rather strange that it would name it based on an effectively hidden implementation detail instead of naming it by what the user is actually trying to accomplish. Most likely it started with proper enums and then realized that sum types would be better instead and never thought to change the keyword to go along with that change.
But then again Swift did the same thing, so who knows? To be fair, its "enums" can degrade to proper enums in order to be compatible with Objective-C, so while not a very good reason, at least you can maybe find some kind of understanding in their thinking in that case. Rust, though...
Glad to see that the bowling development team is focusing on deterministic tooling like language server protocol in gopls and using static analysis for automatically restoring code with go fix.
Recently I made the same assertions as to Go's advantage for LLM/AI orchestration.
It would not surprise me that Google (being the massive services company that it is) would have sent an internal memo instructing teams not to use the Python tool chain to produce production agents or tooling and use Golang.
Even 15 years ago or so when Guido was still there I recall being told "we aren't supposed to write any new services in Python. It starts easy, then things get messy and end up needing to be rewritten." I recall it mostly being perf and tooling support, but also lack of typing, which has changed since then, so maybe they've gotten more accepting.
When you turn on exhaustive, exhaustruct and wrapcheck linters in golangci-lint. You get such a massive safety boost and it makes you fly through writing Go.
Been writing Python code for over twenty years, and using it for personal and work projects, not mainly, but to suppport my work. Recently I ported some of my code to Go and was blown away: Cross compiler, creating binaries, concurrency done right, super fast code. I come very late to the party, and writing software is not my main job, but Go is such a nice complement for my toolbelt. Python for prototyping or writing small services with fastapi, go for network realted stuff, serving lots of users. Super happy with this.
And I am wondering if Rust would be a good addition. Or rather go with Typescript to complement Python and Go.
I recently finished my first ever side gig in Go - a web platform that organizes business processes between multiple actors. Got paid and more feature requests are coming in. Fronted with Caddy, the whole thing runs flawlessly on a $5 VPS. I love Go.
It has been my go to language since 2020. I was given a task to complete in a week and my lead told just go through Go playground and write the code (it was some snmp receiver/transmit stuff). To my surprise it was so easy to learn, write and more importantly test. Only recent thing i have not learned is generics, hopefully will get their sooner. Coming from java background the things Go did felt so clever and just too good to believe
"Man I love Go, it's so simple, plenty fast, really easy to pick up, read, and write. I really love that it doesn't have dozens of esoteric features for my colleagues to big brain into the codebase"
"Oh yeah? Well Go sucks, it doesn't have dozens of esoteric features for me to big brain into the codebase"
I'm thankful for Go because it was an easy first introduction to static typing.
I remember making a little web app and seeing the type errors pop up magically in all he right places where I missed things in my structs. It was a life-changing experience.
I am not really familiar with Go but I wonder where it would be without Google's support and maintenance. I have no doubt it is a solid language with some really smart people in programming language design behind it.
It is so much easy to release programming language but so much difficult to maintain and curate it over time.
Been happily working in Go since 2014. My career has spanned C, Python, C#, Ruby, and a smattering of other languages, but am always quite fond and preferential towards Go.
I remember when Go was born, then, it turned out there was already another programming language called "Go!", but nobody cared, and everybody forgot about that other Go!. So, happy birthday, Go, and rest in peace, Go!
Which obscures the type, making it harder to read the code. The only justification is that 16 years ago, some guy thought he was being clever. For 99.99% of code, it’s a worse syntax. Nobody does eight levels of pointer redirection in typical everyday code.
16 years is a bit of an under-estimate. I think the first popular language with this form of declaration was Pascal.
var
foo: char;
Go was developed by many of the minds behind C, and inertia would have led them to C-style declaration. I don't know if they've ever told anybody why they went with the Pascal style, but I would bet money on the fact that Pascal-style declarations are simply easier and faster for computers to parse. And it doesn't just help with compile speed, it also makes syntax highlighting far more reliable and speeds up tooling.
Sure, it's initially kind of annoying if you're used to the C style of type before identifier, but it's something you can quickly get to grips with. And as time has gone on, it seems like a style that a lot of modern languages have adopted. Off the top of my head, I think this style is in TypeScript, Python type hints, Go, Rust, Nim, Zig, and Odin. I asked Claude for a few more examples and apparently it's also used by Kotlin, Swift, and various flavors of ML and Haskell.
But hey, if you're still a fan of type before variable, PHP has your back.
class User {
public int $id;
public ?string $name;
public function __construct(int $id, ?string $name) {
$this->id = $id;
$this->name = $name;
}
}
Golang to me is a great runtime and very poor language. I could maybe get used to the C pointer-like syntax and to half of my code checking if err != nil, but the lack of classes is a step too far. The Golang idiomatic approach is to have a sprawling set of microservices talking to each other over the network, to manage complexity instead of having classes. This makes sense for things like systems agents (eg K8) but doesn't make sense for most applications because it complicates the development experience unnecessarily and monoliths are also easier to debug.
I would not use Golang for a big codebase with lots of business logic. Golang has not made a dent in Java usage at big companies, no large company is going to try replacing their Java codebases with Golang because there's no benefit, Java is almost as fast as Golang and has classes and actually has a richer set of concurrency primitives.
Microservices are entirely unrelated to classes and in no way endemic to go.
Go’s lack of inheritance is one of its bolder decisions and I think has been proven entirely correct in use.
Instead of the incidental complexity encouraged by pointless inheritance hierarchies we go back to structure which bundle data and behaviour and can compose them instead.
Favouring composition over inheritance is not a new idea nor did it come from the authors of Go.
Also the author of Java (Gosling) disagrees with you.
Oh wow, so it's already been 16 years since Google steamrolled the Go! language, which had existed a decade before Go and had every right to the name. This was when they were still pretending "do no evil" was their brand.
There may be no honor amongst thieves but there is honor amongst langdevs, and when they did Go! dirty, Google made clear which one they are.
Go! was clearly a toy language created only for the purpose of writing papers. It has no applications outside academia. Meanwhile Google's golang exists mostly in the sphere of practical use.
Xeoncross|3 months ago
It took a few more years before I actually got around to learning it and I have to say I've never picked up a language so quickly. (Which makes sense, it's got the smallest language spec of any of them)
I'm sure there are plenty of reasons this is wrong, but it feels like Go gets me 80% of the way to Rust with 20% of the effort.
roncesvalles|3 months ago
I'm convinced no more than a handful of humans understand all of C# or C++, and inevitably you'll come across some obscure thing and have to context switch out of reading code to learn whatever the fuck a "partial method" or "generic delegate" means, and then keep reading that codebase if you still have momentum left.
throw1111221|3 months ago
From Rob Pike himself: "It must be familiar, roughly C-like. Programmers working at Google are early in their careers and are most familiar with procedural languages, particularly from the C family. The need to get programmers productive quickly in a new language means that the language cannot be too radical."
However, the main design goal was to reduce build times at Google. This is why unused dependencies are a compile time error.
https://go.dev/talks/2012/splash.article#TOC_6.
zer00eyz|3 months ago
To add to the above comment, a lot of what Go does encourages readability... Yes it feels pedantic at moments (error handling), but those cultural, and stylistic elements that seem painful to write make reading better.
Portable binaries are a blessing, fast compile times, and the choices made around 3rd party libraries and vendoring are all just icing on the cake.
That 80 percent feeling is more than just the language, as written, its all the things that come along with it...
Someone|3 months ago
I think go is fairly small, too, but “size of spec” is not always a good measure for that. Some specs are very tight, others fairly loose, and tightness makes specs larger (example: Swift’s language reference doesn’t even claim to define the full language. https://docs.swift.org/swift-book/documentation/the-swift-pr...: “The grammar described here is intended to help you understand the language in more detail, rather than to allow you to directly implement a parser or compiler.”)
(Also, browsing golang’s spec, I think I spotted an error in https://go.dev/ref/spec#Integer_literals. The grammar says:
Given that, how can 0600 and 0_600 be valid integer literals in the examples?)tptacek|3 months ago
Rust is great. One of the stupidest things in modern programming practice is the slapfight between these two language communities.
throw-the-towel|3 months ago
morshu9001|3 months ago
The thing people tend to overvalue is the little syntax differences, like how Scala wanted to be a nicer Java, or even ObjC vs Swift before the latter got async/await.
throwaway894345|3 months ago
baby|3 months ago
Thorrez|3 months ago
osigurdson|3 months ago
By 20% of the effort, do you mean learning curve or productivity?
benjiro|3 months ago
We shall not talk about compile time / resource usage differences ;)
I mean, Rust is nice, but compared to when i learned it like 10 years ago, it really looks a lot more these days, like it took too much of a que from C++.
While Go syntax is still the same as it was 10 years ago with barely anything new. What may anger people but even so...
The only thing i love to see is reduce executable sizes because pushing large executables on a dinky upload line, to remove testing is not fun.
tialaramex|3 months ago
I don't see it. Can you say what 80% you feel like you're getting?
The type system doesn't feel anything alike, I guess the syntax is alike in the sense that Go is a semi-colon language and Rust though actually basically an ML deliberately dresses as a semi-colon language but otherwise not really. They're both relatively modern, so you get decent tooling out of the box.
But this feels a bit like if somebody told me that this new pizza restaurant does a cheese pizza that's 80% similar to the Duck Ho Fun from that little place near the extremely tacky student bar. Duck Ho Fun doesn't have nothing in common with cheese pizza, they're both best (in my opinion) if cooked very quickly with high heat - but there's not a lot of commonality.
liampulles|3 months ago
This combined with the ease of building CLI programs has been an absolute godsend in the past when I've had to quickly spin up CLI tools which use business logic code to fix things.
liveoneggs|3 months ago
linhns|3 months ago
ashishb|3 months ago
The Go codebases look all alike. Not only the language has really few primitives but also the code conventions enforced by standard library, gofmt, and golangci-lint implies that the structure of code bases are very similar.
Many language communities can't even agree on the build tooling.
trenchpilgrim|3 months ago
reppap|3 months ago
stOneskull|3 months ago
tschellenbach|3 months ago
go is amazing. switches from python to go 7 years ago. It's the reason our startup did well
thunderbong|3 months ago
https://stream-wiki.notion.site/Stream-Go-10-Week-Backend-En...
zerr|3 months ago
tmoertel|3 months ago
> With gopls v0.18.0, we began exploring automatic code modernizers. As Go evolves, every release brings new capabilities and new idioms; new and better ways to do things that Go programmers have been finding other ways to do. Go stands by its compatibility promise—the old way will continue to work in perpetuity—but nevertheless this creates a bifurcation between old idioms and new idioms. Modernizers are static analysis tools that recognize old idioms and suggest faster, more readable, more secure, more modern replacements, and do so with push-button reliability. What gofmt did for stylistic consistency, we hope modernizers can do for idiomatic consistency.
Modernizers seem like a way make Large-Scale Changes (LSCs) more available to the masses. Google has internal tooling to support them [1], but now Go users get a limited form of opt-in LSC support whenever modernizers make a suggestion.
[1] https://abseil.io/resources/swe-book/html/ch22.html
tail_exchange|3 months ago
If I had a magic wand, the only things I would add is better nulability checks, add stack traces by default for errors, and exhaustive checks for sum types. Other than that, it does everything I want.
thegeekpirate|3 months ago
Linters such as https://golangci-lint.run will do this for you.
trenchpilgrim|3 months ago
In development: https://github.com/uber-go/nilaway
unknown|3 months ago
[deleted]
weakfish|3 months ago
Writing microservices at $DAYJOB feels far easier and less guess-work, even if it requires more upfront code, because it’s clear what each piece does and why.
_ea1k|3 months ago
It really feels like a simpler language and ecosystem compared to Python. On top of that, it performs much better!
MichaelNolan|3 months ago
At work we use Uber’s NillAway, so that helps bit. https://github.com/uber-go/nilaway Though actually having the type system handle it would be nicer.
kellpossible2|3 months ago
qouteall|3 months ago
srameshc|3 months ago
threemux|3 months ago
bobjordan|3 months ago
rollulus|3 months ago
zmj|3 months ago
tapirl|3 months ago
It is so weird that they still claim this after they have made the the semantic change for 3-clause for-loop in Go 1.22.
When a Go module is upgraded from 1.21- to 1.22+, there are some potential breaking cases which are hard to detect in time. https://go101.org/blog/2024-03-01-for-loop-semantic-changes-...
Go toolchain 1.22 broke compatibility for sure. Even the core team admit it. https://go101.org/bugs/go-build-directive-not-work.html
0x696C6961|3 months ago
gf000|3 months ago
culebron21|3 months ago
Proponents say it has nothing under the hood. I see under-the-hood-magic happen every time.
1) The arrays append is one example. Try removing an element from an array - you must rely on some magic and awkward syntax, and there's no clear explanation what actually happens under the hood (all docs just show you that a slice is a pointer to a piece of vector).
2) enums creation is just nonsense
3) To make matters worse, at work we have a linter that forbids merging a branch if you a) don't do if err != nil for every case b) have >20 for & if/else clauses. This makes you split functions in many pieces, turning your code into enterprise Java.
It feels like, to implement same things, Go is 2x slower than in Rust.
On the positive side,
* interfaces are simpler, without some stricter Rust's limitations; the only problem with them is that in the using code, you can't tell one from a struct
* it's really fast to pick up, I needed just couple of days to see examples and start coding stuff.
I think Go would have been great with
* proper enums (I'll be fine if they have no wrapped data)
* sensible arrays & slices, without any magic and awkward syntax
* iterators
* result unwrapping shorthands
jiehong|3 months ago
Other random things I hate:
- first element in a struct, if unnamed, acts like extending a struct;
- private/public fields of method based on capitalisation (it makes json mapping to a struct have so much boilerplate);
- default json lib being so inept with collections: an empty slice is serialised as null/absent (empty list is not absence of a list, WTF, but the new json lib promises to fix that json crap);
- error type being special, and not working well with chanels;
- lambda syntax is verbose;
- panics (especially the ones in libs);
- using internal proxy in companies for packages download is very fiddly, and sucks.
But, the tooling is pretty good and fast, I won’t lie. The language won’t win beauty contests for sure, but it mostly does the job. Still weak at building http servers (limited http server libs with good default headers, very limited openapi spec support).
alain_gilbert|3 months ago
It has enums (sum type), tuple, built-in Set[T], and good Iterator methods. It has very nice type inferred lambda function (heavily inspired by the swift syntax)... lots of good stuff!
https://github.com/alaingilbert/agl
Zababa|3 months ago
>3) To make matters worse, at work we have a linter that forbids merging a branch if you a) don't do if err != nil for every case b) have >20 for & if/else clauses. This makes you split functions in many pieces, turning your code into enterprise Java.
That is not a problem with Go.
Mawr|3 months ago
It has iterators - https://pkg.go.dev/iter.
> It lacks simple things like check if a key exists in a map.
What? `value, keyExists := myMap[someKey]`
> Try removing an element from an array - you must rely on some magic and awkward syntax, and there's no clear explanation what actually happens under the hood (all docs just show you that a slice is a pointer to a piece of vector).
First of all, if you're removing elements from the middle of an array, you're using the wrong data structure 99% of the time. If you're doing that in a loop, you're hitting degenerate performance.
Second, https://pkg.go.dev/slices#Delete
jmaker|3 months ago
From what I’ve experienced, if you need any fine-grained control over your data or allocations, precision on the type level, expressing nontrivial algorithms, Go is just too clumsy.
The more I read about how people use Go today and what issues people still have, the more I’m happy I picked Rust for almost everything. I even find it much more productive to write scripts in Rust than in Python or shell script. You just get it right very quickly and you don’t need to care about the idiosyncrasies of ancient tech debt that would otherwise creep into your new projects. And of course the outcome is way more maintainable.
Not saying that Rust hadn’t had its own warts, but most of them are made explicit. This is perhaps what I appreciate the most.
Intuitively, however, I still notice myself creating a new Python or shell script file when I need something quick, but then something doesn’t really work well the moment the logic gets a bit more complex, and I need to backtrack and refactor. With Rust, this hasn’t been an issue in my experience.
And intuitively, I still tend to think in Java terms when designing. It’s funny how it sticks for so long. And when writing some Java, I miss Go’s use-site interfaces and TypeScript’s structural typing, while I miss nominal typing in TypeScript. It’s just maybe that you get used to workarounds and idiosyncrasies in some system and then carry them over to another paradigms.
I do like Go’s value propositions, and lots of its warts have been sorted out, but I’m just not as productive in it for my use cases as I am with Rust. It just checks way more boxes with me.
unknown|3 months ago
[deleted]
lenkite|3 months ago
Umm..in Java you won't have to split functions here. Maybe you should study some modern Java ?
9rx|3 months ago
It has proper enums. Granted, it lacks an enum keyword, which seems to trip up many.
Perhaps what you are actually looking for is sum types? Given that you mentioned Rust, which weirdly[1] uses the enum keyword for sum types, this seems likely. Go does indeed lack that. Sum types are not enums, though.
> sensible arrays & slices, without any magic and awkward syntax
Its arrays and slices are exactly the same as how you would find it in C. So it is true that confuses many coming from languages that wrap them in incredible amounts of magic, but the issue you point to here is actually a lack of magic. Any improvements to help those who are accustomed to magic would require adding magic, not taking it away.
> iterators
Is there something about them that you find lacking? They don't seem really any different than iterators in other languages that I can see, although I'll grant you that the anonymous function pattern is a bit unconventional. It is fine, though.
> result unwrapping shorthands
Go wants to add this, and has been trying to for years, but nobody has explained how to do it sensibly. There are all kinds of surface solutions that get 50% of the way there, but nobody wants to tackle the other 50%. You can't force someone to roll up their sleeves, I guess.
[1] Rust uses enums to generate the sum type tag as an implementation detail, so its not quite as weird as it originally seems, but still rather strange that it would name it based on an effectively hidden implementation detail instead of naming it by what the user is actually trying to accomplish. Most likely it started with proper enums and then realized that sum types would be better instead and never thought to change the keyword to go along with that change.
But then again Swift did the same thing, so who knows? To be fair, its "enums" can degrade to proper enums in order to be compatible with Objective-C, so while not a very good reason, at least you can maybe find some kind of understanding in their thinking in that case. Rust, though...
jryio|3 months ago
Recently I made the same assertions as to Go's advantage for LLM/AI orchestration.
https://news.ycombinator.com/item?id=45895897
It would not surprise me that Google (being the massive services company that it is) would have sent an internal memo instructing teams not to use the Python tool chain to produce production agents or tooling and use Golang.
somekyle2|3 months ago
disintegrator|3 months ago
submeta|3 months ago
And I am wondering if Rust would be a good addition. Or rather go with Typescript to complement Python and Go.
p2detar|3 months ago
Pbhaskal|3 months ago
insurancesucks|3 months ago
"Man I love Go, it's so simple, plenty fast, really easy to pick up, read, and write. I really love that it doesn't have dozens of esoteric features for my colleagues to big brain into the codebase"
"Oh yeah? Well Go sucks, it doesn't have dozens of esoteric features for me to big brain into the codebase"
Repeat
dlock17|3 months ago
adamddev1|3 months ago
I remember making a little web app and seeing the type errors pop up magically in all he right places where I missed things in my structs. It was a life-changing experience.
rishabhaiover|3 months ago
kasperset|3 months ago
mikewarot|3 months ago
[16] https://en.wikipedia.org/wiki/SWEET16
duskwuff|3 months ago
captainkrtek|3 months ago
sedatk|3 months ago
https://en.wikipedia.org/wiki/Go!_(programming_language)#Con...
iainctduncan|3 months ago
Zardoz84|3 months ago
MagicMoonlight|3 months ago
Instead of “int x”
You have “var x int”
Which obscures the type, making it harder to read the code. The only justification is that 16 years ago, some guy thought he was being clever. For 99.99% of code, it’s a worse syntax. Nobody does eight levels of pointer redirection in typical everyday code.
bbkane|3 months ago
LexiMax|3 months ago
Sure, it's initially kind of annoying if you're used to the C style of type before identifier, but it's something you can quickly get to grips with. And as time has gone on, it seems like a style that a lot of modern languages have adopted. Off the top of my head, I think this style is in TypeScript, Python type hints, Go, Rust, Nim, Zig, and Odin. I asked Claude for a few more examples and apparently it's also used by Kotlin, Swift, and various flavors of ML and Haskell.
But hey, if you're still a fan of type before variable, PHP has your back.
mxey|3 months ago
You can write
var x = 5
how would that work if the type had to be first? Languages that added inference later tend to have “auto” as the type which looks terrible.
pjmlp|3 months ago
Maybe by 18, or 21, the maturity finally settles in.
nicodjimenez|3 months ago
I would not use Golang for a big codebase with lots of business logic. Golang has not made a dent in Java usage at big companies, no large company is going to try replacing their Java codebases with Golang because there's no benefit, Java is almost as fast as Golang and has classes and actually has a richer set of concurrency primitives.
wanderlust123|3 months ago
I think go needs some more functional aspects, like iterators and result type/pattern matching.
grey-area|3 months ago
Go’s lack of inheritance is one of its bolder decisions and I think has been proven entirely correct in use.
Instead of the incidental complexity encouraged by pointless inheritance hierarchies we go back to structure which bundle data and behaviour and can compose them instead.
Favouring composition over inheritance is not a new idea nor did it come from the authors of Go.
Also the author of Java (Gosling) disagrees with you.
https://www.infoworld.com/article/2160788/why-extends-is-evi...
ModernMech|3 months ago
There may be no honor amongst thieves but there is honor amongst langdevs, and when they did Go! dirty, Google made clear which one they are.
Status changed to Unfortunate
https://github.com/golang/go/issues/9#issuecomment-66047478
anal_reactor|3 months ago
MagicMoonlight|3 months ago