[HN Gopher] Go's Sweet 16
___________________________________________________________________
Go's Sweet 16
Author : 0xedb
Score : 271 points
Date : 2025-11-14 22:33 UTC (1 days ago)
(HTM) web link (go.dev)
(TXT) w3m dump (go.dev)
| tschellenbach wrote:
| 10 week onboarding program we use here for go backend devs:
| https://www.reddit.com/r/golang/comments/1eiea6q/10_week_pla...
|
| go is amazing. switches from python to go 7 years ago. It's the
| reason our startup did well
| thunderbong wrote:
| Direct link
|
| https://stream-wiki.notion.site/Stream-Go-10-Week-Backend-En...
| zerr wrote:
| 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.
| millerm wrote:
| I haven't been able to find a job anywhere, using any
| language, that didn't require all that stuff these days. I
| wish I could go back to pure development, but now we all get
| this entire infra-crap thrown at us too. Which then means...
| you support the environments, the runtime, and the code. It's
| a 24/7 world and I don't care for it anymore.
| arccy wrote:
| it's alignment of incentives.
|
| nowadays devs are less inclined to pump out crappy code
| that ends up with some ops guy having to wake up in the
| middle of the night
| Xeoncross wrote:
| 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.
| tialaramex wrote:
| > 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.
| klodolph wrote:
| > I don't see it. Can you say what 80% you feel like you're
| getting?
|
| I read it as "80% of the way to Rust levels of reliability
| and performance." That doesn't mean that the type system or
| syntax is at all similar, but that you get some of the same
| benefits.
|
| I might say that, "C gets you 80% of the way to assembly with
| 20% of the effort." From context, you could make a reasonable
| guess that I'm talking about performance.
| Xeoncross wrote:
| Yes, for me I've always pushed the limits of what kinds of
| memory and cpu usage I can get out of languages. NLP, text
| conversion, video encoding, image rendering, etc...
|
| Rust beats Go in performance.. but nothing like how far
| behind Java, C#, or scripting languages (python, ruby,
| typescript, etc..) are from all the work I've done with
| them. I get most of the performance of Rust with very
| little effort a fully contained stdlib/test suite/package
| manger/formatter/etc.. with Go.
| echelon wrote:
| Rust is the most defect free language I have ever had the
| pleasure of working with. It's a language where you can
| almost be certain that if it compiles and if you wrote
| tests, you'll have no runtime bugs.
|
| I can only think of two production bugs I've written in
| Rust this year. Minor bugs. And I write a lot of Rust.
|
| The language has very intentional design around error
| handling: Result<T,E>, Option<T>, match, if let,
| functional predicates, mapping, `?`, etc.
|
| Go, on the other hand, has nil and extremely exhausting
| boilerplate error checking.
|
| Honestly, Go has been one of my worst languages outside
| of Python, Ruby, and JavaScript for error introduction.
| It's a total pain in the ass to handle errors and
| exceptional behavior. And this leads to making mistakes
| and stupid gotchas.
|
| I'm so glad newer languages are picking up on and copying
| Rust's design choices from day one. It's a godsend to be
| done with null and exceptions.
|
| I really want a fast, memory managed, statically typed
| scripting language somewhere between Rust and Go that's
| fast to compile like Go, but designed in a safe way like
| Rust. I need it for my smaller tasks and scripting. Swift
| is kind of nice, but it's too Apple centric and hard to
| use outside of Apple platforms.
|
| I'm honestly totally content to keep using Rust in a wife
| variety of problem domains. It's an S-tier language.
| nine_k wrote:
| > _I really want a fast, memory managed, statically typed
| scripting language somewhere between Rust and Go that 's
| fast to compile_
|
| It could as well be Haskell :) Only partly a joke:
| https://zignar.net/2021/07/09/why-haskell-became-my-
| favorite...
| Xeoncross wrote:
| I agree with a lot of what you said. I'm hoping Rust will
| warm on me as I improve in it. I hate nil/null.
|
| > Go... extremely exhausting boilerplate error checking
|
| This actually isn't correct. That's because Go is the
| only language that makes you think about errors at every
| step. If you just ignored them and passed them up like
| exceptions or maybe you're basically just exchanging
| handling errors for assuming the whole thing pass/fail.
|
| If you you write actual error checking like Go in Rust
| (or Java, or any other language) then Go is often less
| noisy.
|
| It's just two very different approaches to error handling
| that the dev community is split on. Here's a pretty good
| explanation from a rust dev:
| https://www.youtube.com/watch?v=YZhwOWvoR3I
| dontlaugh wrote:
| It's very common in Go to just pass the error on since
| there's no way to handle it in that layer.
|
| Rust forces you to think about errors exactly as much,
| but in the common case of passing it on it's more
| ergonomic.
| gr4vityWall wrote:
| Borgo could be that language for you. It compiles down to
| Go, and uses constructs like Option<T> instead of nil,
| Result<T,E> instead of multiple return values, etc.
| https://github.com/borgo-lang/borgo
| gf000 wrote:
| > I really want a fast, memory managed, statically typed
| scripting language somewhere between Rust and Go that's
| fast to compile like Go, but designed in a safe way like
| Rust
|
| OCaml is pretty much that, with a very direct
| relationship with Rust, so it will even feel familiar.
| vips7L wrote:
| Go is in the same performance profile as Java and C#.
| There are tons of benchmarks that support this.
| Xeoncross wrote:
| 1) for one-off scripts and 2) If you ignore memory.
|
| You can make about anything faster if you provide more
| memory to store data in more optimized formats. That
| doesn't make them faster.
|
| Part of the problem is that Java in the real world
| requires an unreasonable number of classes and 3rd party
| libraries. Even for basic stuff like JSON marshaling. The
| Java stdlib is just not very useful.
|
| Between these two points, all my production Java systems
| easily use 8x more memory and still barely match the
| performance of my Go systems.
| gf000 wrote:
| Memory is the most common tradeoff engineers make for
| better performance. You can trivially do so yourself with
| java, feel free to cut down the heap size and Java's GC
| will happily chug along 10-100 times as often without a
| second thought, they are beasts. The important metric is
| that Java's GC _will_ be able to keep up with most
| workloads, and it won 't needlessly block user threads
| from doing their work. Also, not running the GC as often
| makes Java use surprisingly small amounts of energy.
|
| As for the stdlib, Go's is certainly impressive but come
| on, I wouldn't even say that in general case Java's
| standard library is smaller. It just so happens that Go
| was developed with the web in mind almost exclusively,
| while Java has a wider scope. Nonetheless, the Java
| standard library is certainly among the bests in
| richness.
| vips7L wrote:
| I genuinely can't think of anything the Java standard
| library is missing, apart from a json parser which is
| being added.
|
| It's your preference to prefer one over the other, I
| prefer Java's standard library because atleast it has a
| generic Set data structure in it and C#'s standard
| library does have a JSON parser.
|
| I don't think discussions about what is in the standard
| library really refutes anything about Go being within the
| same performance profile though.
| password4321 wrote:
| Single binary deployment was a big deal when Go was young;
| that might be worth a few percent. Also: automatically
| avoiding entire categories of potential vulnerabilities due
| to language-level design choices and features. Not compile
| times though ;)
| kace91 wrote:
| Wild guess but, with the current JS/python dominance, maybe
| it's just the benefits of a (modern) compiled language.
| NoboruWataya wrote:
| I guess the 80% would be a reasonably performant compiled
| binary with easily managed dependencies? And the extra 20%
| would be the additional performance and peace of mind
| provided by the strictness of the Rust compiler.
| morshu9001 wrote:
| 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.
| ezst wrote:
| I'll be the one to nickpick, but Scala never intended to be a
| nicer Java. It was and still is an academic exercise in
| compiler and language theory. Also, judging by Kotlin's
| decent strides, "little Syntex differences" get you a long
| way on a competent VM/Runtime/stdlib.
| morshu9001 wrote:
| Kotlin's important feature is the cooperative multitasking.
| Java code has been mangled all these years to work around
| not having that. I don't think many would justify the
| switch to Kotlin otherwise.
| roncesvalles wrote:
| 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.
| morshu9001 wrote:
| This is also what I like about JS, except it's even easier
| than Go. Meanwhile Python has a surprising number of random
| features.
| jchw wrote:
| Just so we're on the same page, this is the current JS
| spec:
|
| https://262.ecma-international.org/16.0/index.html
|
| I don't agree. (And frankly don't like using JS without at
| least TypeScript.)
| goranmoomin wrote:
| While I might not think that JS is a good language (for
| some definition of a good language), to me the provided
| spec does feel pretty small, considering that it's a
| language that has to be specified to the dot and that the
| spec contains the standard library as well.
|
| It has some strange or weirdly specified features (ASI?
| HTML-like Comments?) and unusual features (prototype-
| based inheritance? a dynamically-bounded this?), but IMO
| it's a small language.
| jchw wrote:
| Shrugging it off as just being large because it contains
| the "standard library" ignores that many JS language
| features necessarily use native objects like symbols or
| promises, which can't be entirely implemented in just
| JavaScript alone, so they are intrinsic rather than being
| standard library components, akin to Go builtins rather
| than the standard library. In fact, in _actual_
| environments, the browser and /or Node.JS provide the
| _actual_ standard library, including things like fetch,
| sockets, compression codecs, etc. Even ignoring almost
| all of those bits though, the spec is absolutely
| enormous, because JavaScript has:
|
| - Regular expressions - not just in the "standard
| library" but in the _syntax_.
|
| - An entire module system with granular imports and
| exports
|
| - Three different ways to declare variables, two of which
| create temporal dead zones
|
| - Classes with inheritance, including private properties
|
| - Dynamic properties (getters and setters)
|
| - Exception handling
|
| - Two different types of closures/first class functions,
| with different binding rules
|
| - Async/await
|
| - Variable length "bigint" integers
|
| - Template strings
|
| - Tagged template literals
|
| - Sparse arrays
|
| - for in/for of/iterators
|
| - for await/async iterators
|
| - The with statement
|
| - Runtime reflection
|
| - Labeled statements
|
| - A lot of operators, including bitwise operators and two
| sets of equality operators with different semantics
|
| - Runtime code evaluation with eval/Function constructor
|
| And honestly it's only scratching the surface, especially
| of modern ECMAScript.
|
| A language spec is necessarily long. The JS language
| spec, though, is so catastrophically long that it is a
| bit hard to load on a low end machine or a mobile web
| browser. It's on another planet.
| alexjplant wrote:
| ECMAScript is an order of magnitude more complicated than
| Go by virtually every measure - length of language spec,
| ease of parsing, number of context-sensitive keywords and
| operators, etc.
| ttoinou wrote:
| Yeah I'm pretty sure people who say JS is easy don't know
| about its Prototype based OOP
| morshu9001 wrote:
| You don't have to know about it, but if you do, it's
| actually simpler than how other languages do OOP.
| gf000 wrote:
| Not convinced. Especially with property flags.
| liveoneggs wrote:
| strict mode makes it okay
| woodruffw wrote:
| I think JS is notoriously complicated: the phrase "the good
| parts" has broad recognition among programmers.
| ajross wrote:
| The Javascript world hides its complexity outside the core
| language, though. JS itself isn't so weird (though as
| always see the "Wat?" video), but the incantations required
| to type and read the actual code are pretty wild.
|
| By the time you understand all of typescript, your
| templating environment of choice, and especially the
| increasingly arcane build complexity of the npm world,
| you've put in hours comparable to what you'd have spent
| learning C# or Java for sure (probably more). Still easier
| than C++ or Rust though.
| xigoi wrote:
| ...do you know you can just write JavaScript and run it
| in the browser? You don't need TypeScript, NPM or build
| tools.
| throwaway894345 wrote:
| You do if you want more than one file, or if you want to
| use features that a user's target browser may not
| support.
| xigoi wrote:
| > You do if you want more than one file
|
| Modules were added in, like, 2016.
| legends2k wrote:
| Sorry, hard disagree. Try to understand what `this` means
| in JS in its entirety and you'll agree it's by no stretch
| of the imagination a simple language. It's more mind-
| bending and hence _The Good Parts_.
| cratermoon wrote:
| https://jsdate.wtf/
| kermatt wrote:
| > I'm convinced no more than a handful of humans understand
| all of C# or C++
|
| How would the proportion of humans that understand all of
| Rust compare?
| metaltyphoon wrote:
| Rust isn't that complicated if you have some background in
| non GC languages.
| j16sdiz wrote:
| Parent say _all_ of it, not a subset for everyday use.
| estebank wrote:
| There's a different question too, that I think is more
| important (for any language): how much of the language do
| you _need_ to know in order to use it effectively. As
| another poster mentioned, the issue with C++ might not be
| the breath of features, but rather how they interact in
| non-obvious ways.
| Measter wrote:
| For Rust vs C++, I'd say it'll be much easier to have a
| complete understanding of Rust. C++ is an immensely complex
| language, with a lot of feature interactions.
|
| C# is actually fairly complex. I'm not sure if it's quite
| at the same level as Rust, but I wouldn't say it's that far
| behind in difficulty for complete understanding.
| Santosh83 wrote:
| For Rust I'd expect the _implementation_ to be the real
| beast, versus the language itself. But not sure how it
| compares to C++ implementation complexity.
| pclmulqdq wrote:
| I'm pretty convinced that nobody has a full picture of Rust
| in their head. There isn't even a spec to read.
| jrpelkonen wrote:
| There is, in fact, a spec to read[1], as of earlier this
| year.
|
| [1] https://rustfoundation.org/media/ferrous-systems-
| donates-fer...
| kccqzy wrote:
| Rust is very advanced, with things like higher-ranked trait
| bounds (https://doc.rust-lang.org/nomicon/hrtb.html) and
| generic associated types
| (https://www.ncameron.org/rfcs/1598) that are difficult
| because they are essential complexity not accidental
| complexity.
| gf000 wrote:
| Rust managed to learn a lot from C++ and other languages'
| mistakes.
|
| So while it has quite a bit of essential complexity
| (inherent in the design space it operates: zero overhead
| low-level language with memory safety), I believe it fares
| overall better.
|
| Like no matter the design, a language wouldn't need 10
| different kinds of initializer syntaxes, yet C++ has at
| least that many.
| egl2020 wrote:
| I've been writing go professionally for about ten years, and
| with go I regularly find myself saying "this is pretty
| boring", followed by "but that's a good thing" because I'm
| pretty sure that I won't do anything in a go program that
| would cause the other team members much trouble if I were to
| get run over by a bus or die of boredom.
|
| In contrast writing C++ feels like solving an endless series
| of puzzles, and there is a constant temptation to do
| Something Really Clever.
| stackghost wrote:
| Go is okay. I don't hate it but I certainly don't love it.
|
| The packaging story is better than c++ or python but that's
| not saying much, the way it handles private repos is a
| colossal pain, and the fact that originally you had to have
| everything under one particular blessed directory and
| modules were an afterthought sure speaks volumes about the
| critical thinking (or lack thereof) that went into the
| design.
|
| Also I miss being able to use exceptions.
| throwaway894345 wrote:
| When Go was new, having better package management than
| Python and C++ was saying a lot. I'm sure Go wasn't the
| first, but there weren't many mainstream languages that
| didn't make you learn some imperative DSL just to add
| dependencies.
| stackghost wrote:
| Sure, but all those languages didn't have the psychotic
| design that mandated all your code lives under $GOPATH
| for the first several versions.
|
| I'm not saying it's awful, it's just a pretty mid
| language, is all.
| gp wrote:
| The language has changed a lot since then. Give it a
| fresh look sometime.
| treis wrote:
| It's still pretty mid and still missing basic things like
| sets.
|
| But mid is not all that bad and Go has a compelling
| developer experience that's hard to beat. They just made
| some unfortunate choices at the beginning that will
| always hold it back.
| throwaway894345 wrote:
| I picked up Go precisely in 2012 because $GOPATH (as bad
| as it was) was infinitely better than CMake, Gradle,
| Autotools, pip, etc. It was dead simple to do basic
| dependency management and get an executable binary out.
| In any other mainstream language on offer at the time,
| you had to learn an entire programming language just to
| script your meta build system before you could even begin
| writing code, and that build system programming language
| was often more complex than Go.
| tptacek wrote:
| That was a Plan9ism, I think. Java had something like it
| with CLASSPATH too, didn't it?
| klooney wrote:
| I never understood the GOPATH freakout, coming from
| Python it seemed really natural- it's a mandatory
| virtualenv.
| stackghost wrote:
| The fact that virtualenv exists at all should be viewed
| by the python community as a source of profound shame.
|
| The idea that it's natural and accepted that we just have
| python v3.11, 3.12, 3.13 etc all coexisting, each with
| their own incompatible package ecosystems, and in use on
| an ad-hoc, per-directory basis just seems fundamentally
| insane to me.
| zimpenfish wrote:
| > I'm pretty sure that I won't do anything in a go program
| that would cause the other team members much trouble
|
| Alas there are plenty of people who do[0] - for some reason
| Go takes architecture astronaut brain and wacks it up to 11
| and god help you if you have one or more of those on your
| team.
|
| [0] _flashbacks to the interface calling an interface
| calling an interface calling an interface I dealt with last
| year - NONE OF WHICH WERE NEEDED because it was a bloody
| hardcoded value in the end._
| asa400 wrote:
| > The nice thing about Go is that you can learn "all of it"
| in a reasonable amount of time
|
| This always feels like one of those "taste" things that some
| programmers tend to like on a personal level but has almost
| no evidence that it leads to more real-world success vs any
| other language.
|
| Like, people get real work done every day at scale with C#
| and C++. And Java, and Ruby, and Rust, and JavaScript. And
| every other language that programmers castigate as being huge
| and bloated.
|
| I'm not saying it's wrong to have a preference for smaller
| languages, I just haven't seen anything in my career to
| indicate that smaller languages outperform when it comes to
| faster delivery or less bugs.
|
| As an aside, I'd even go so far as to say that the main
| problem with C++ is not that it has so many features in
| number, but that its features interact with each other in
| unpredictable ways. Said another way, it's not the number of
| nodes in the graph, but the number of edges and the manner of
| those edges.
| synthetic-echo wrote:
| Just an anecdote and not necessarily generalizable, but I
| can at least give one example:
|
| I'm in academia doing ML research where, for all intents
| and purposes, we work exclusively in Python. We had a
| massive CSV dataset which required sorting, filtering, and
| other data transformations. Without getting into details,
| we had to rerun the entire process when new data came in
| roughly every week. Even using every trick to speed up the
| Python code, it took around 3 days.
|
| I got so annoyed by it that I decided to rewrite it in a
| compiled language. Since it had been a few years since I've
| written any C/C++, which was only for a single class in
| undergrad and I remember very little of, I decided to give
| Go a try.
|
| I was able to learn enough of the language and write up a
| simple program to do the data processing in less than a few
| hours, which reduced the time it took from 3+ days to less
| than 2 hours.
|
| I unfortunately haven't had a chance or a need to write any
| more Go since then. I'm sure other compiled, GC languages
| (e.g., Nim) would've been just as productive or performant,
| but I know that C/C++ would've taken me much longer to
| figure out and would've been much harder to read/understand
| for the others that work with me who pretty much only know
| Python. I'm fairly certain that if any of them needed to
| add to the program, they'd be able to do so without wasting
| more than a day to do so.
| Denzel wrote:
| Did you try scipy/numpy or any python library with a
| compiled implementation before picking up Go?
| synthetic-echo wrote:
| Of course, but the dataset was mostly strings that needed
| to be cross-referenced with GIS data. Tried every library
| under the sun. The greatest speed up I got was using
| polars to process the mostly-string CSVs, but didn't help
| much. With that said, I think polars was also _just_
| released when we were working with that dataset and I 'm
| sure there's been a lot of performance improvements since
| then.
| kalterdev wrote:
| > I'm not saying it's wrong to have a preference for
| smaller languages, I just haven't seen anything in my
| career to indicate that smaller languages outperform when
| it comes to faster delivery or less bugs.
|
| I can imagine myself grappling with a language feature
| unobvious to me and eventually getting distracted. Sure,
| there is a lot of things unobvious to me but Go is not one
| of them and it influenced the whole environment.
|
| Or, when choosing the right language feature, I could end
| up with weighing up excessively many choices and still
| failing to get it right, from the language correctness
| perspective (to make code scalable, look nice, uniform,
| play well with other features, etc).
|
| An example not related to Go: bash and rc [1].
| Understanding 16 pages of Duff's rc manual was enough for
| me to start writing scripts faster than I did in bash. It
| did push me to ease my concerns about program correctness,
| though, which I welcomed. The whole process became more
| enjoyable without bashisms getting in the way.
|
| Maybe it's hard to measure the exact benefit but it should
| exist.
|
| 1: https://9p.io/sys/doc/rc.html
| 8organicbits wrote:
| I think Go is a great language when hiring. If you're
| hiring for C++, you'll be wary of someone who only knows
| JavaScript as they have a steep learning curve ahead. But
| learning Go is very quick when you already know another
| programming language.
| throwaway894345 wrote:
| I agree that empirical data in programming is difficult,
| but i've used many of those languages personally, so I can
| say for myself at least that I'm far more productive in Go
| than any of those other languages.
|
| > As an aside, I'd even go so far as to say that the main
| problem with C++ is not that it has so many features in
| number, but that its features interact with each other in
| unpredictable ways. Said another way, it's not the number
| of nodes in the graph, but the number of edges and the
| manner of those edges.
|
| I think those problems are related. The more features you
| have, the more difficult it becomes to avoid strange,
| surprising interactions. It's like a pharmacist working
| with a patient who is taking a whole cocktail of
| prescriptions; it becomes a combinatorial problem to avoid
| harmful reactions.
| throwaway894345 wrote:
| I've been using Python since 2008, and I don't feel like I
| understand very much of it at all, but after just a couple of
| years of using Go in a hobby capacity I felt I knew it very
| well.
| treis wrote:
| The tradeoff with that language simplicity is that there's a
| whole lot of gotchas that come with Go. It makes things look
| simpler than they actually are.
| jbreckmckye wrote:
| I learned Go this year, and this assertion just... isn't
| true? There are a bunch of subtleties and footguns,
| _especially_ with concurrency.
|
| C++ is a basket case, it's not really a fair comparison.
| tptacek wrote:
| 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.
| zer00eyz wrote:
| 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...
| cwbriscoe wrote:
| Error handling isn't even a pain to write any more with AI
| autocomplete which gets it right 95%+ of the time in my
| experience.
| zer00eyz wrote:
| You're not wrong but... there is a large contingent of the
| Go community that has a rather strong reaction to AI/ML/LLM
| generated code at any level.
|
| I keep using the analogy, that the tools are just nail guns
| for office workers but some people remain sticks in the
| mud.
| 9rx wrote:
| _> there is a large contingent of the Go community that
| has a rather strong reaction to AI /ML/LLM generated code
| at any level._
|
| This Go community that you speak of isn't bothered by
| writing the boilerplate themselves in the first place,
| though. For everyone else the LLMs provide.
| bccdee wrote:
| Nail guns are great because they're instant and
| consistent. You point, you shoot, and you've
| unimpeachably bonded two bits of wood.
|
| For non-trivial tasks, AI is neither of those. Anything
| you do with AI needs to be carefully reviewed to correct
| hallucinations and incorporate it into your mental model
| of the codebase. You point, you shoot, and that's just
| the first 10-20% of the effort you need to move past this
| piece of code. Some people like this tradeoff, and fair
| enough, but that's nothing like a nailgun.
|
| For trivial tasks, AI is barely worth the effort of
| prompting. If I really hated typing `if err != nil {
| return nil, fmt.Errorf("doing x: %w", err) }` so much,
| I'd make it an editor snippet or macro.
| zer00eyz wrote:
| > Nail guns are great because they're instant and
| consistent. You point, you shoot, and you've
| unimpeachably bonded two bits of wood.
|
| You missed it.
|
| If I give a random person off the street a nail gun,
| circular saw and a stack of wood are they going to do a
| better job building something than a carpenter with a
| hammer and hand saw?
|
| > Anything you do with AI needs to be carefully reviewed
|
| Yes, and so does a JR engineer, so do your peers, so do
| you. Are you not doing code reviews?
| kgwxd wrote:
| You are responsible for the AI code you check in. It's
| your reputation on the line. If people felt the need to
| assume that much responsibility for all code they review,
| they'd insist on writing it themselves instead.
| bccdee wrote:
| > If I give a random person off the street a nail gun,
| circular saw and a stack of wood
|
| If this is meant to be an analogy for AI, it doesn't make
| sense. We've seen what happens when random people off the
| street try to vibe-code applications. They consistently
| get hacked.
|
| > Yes, and so does a JR engineer
|
| Any junior dev who consistently wrote code like an AI
| model and did not improve with feedback would get fired.
| gf000 wrote:
| Error handling is objectively terrible in Go and the
| explicitness of the always repeating pattern just makes
| humans pay less attention to potentially problematic lines
| and otherwise increases the noise to signal ratio.
| throw1111221 wrote:
| 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.
|
| https://go.dev/talks/2012/splash.article#TOC_6.
| pkaye wrote:
| Doesn't Google use mostly C++?
| throw1111221 wrote:
| Just because it was a design goal doesn't mean it succeeded
| ;)
|
| From Russ Cox this time: "Q. What language do you think Go
| is trying to displace? ... One of the surprises for me has
| been the variety of languages that new Go programmers used
| to use. When we launched, we were trying to explain Go to
| C++ programmers, but many of the programmers Go has
| attracted have come from more dynamic languages like Python
| or Ruby."
|
| https://research.swtch.com/gotour
| Measter wrote:
| It's interesting that I've also heard the same from
| people involved in Rust. Expecting more interest from C++
| programmers and being surprised by the numbers of
| Ruby/Python programmers interested.
|
| I wonder if it's that Ruby/Python programmers were
| interested in using these kinds of languages but were
| being pushed away by C/C++.
| estebank wrote:
| The people writing C++ either don't need much convincing
| to switch because they see the value or are unlikely to
| give it up anytime soon because they don't see anything
| Rust does as being useful to them, very little middle
| ground. People from higher level languages on the other
| hand see in Rust a way to break into a space that they
| would otherwise not attempt because it would take too
| long a time to reach proficiency. The hard part of Rust
| is trying to simultaneously have hard to misuse APIs and
| no additional performance penalty (however small). If you
| relax either of those goals (is it really a problem if
| you call that method through a v-table?), then Rust
| becomes much easier to write. I think GC Rust would
| already be a nice language to use that I'd love, like a
| less convoluted Scala, it just wouldn't have fit in a
| free square that ensured a niche for it to exist and
| grow, and would likely have died in the vine.
| dpe82 wrote:
| It really depends on product area.
| allset_ wrote:
| No.
| the_gipsy wrote:
| > This is why unused dependencies are a compile time error.
|
| https://go.dev/doc/faq?utm_source=chatgpt.com#unused_variabl.
| ..
|
| > There are two reasons for having no warnings. First, if
| it's worth complaining about, it's worth fixing in the code.
| (Conversely, if it's not worth fixing, it's not worth
| mentioning.) Second, having the compiler generate warnings
| encourages the implementation to warn about weak cases that
| can make compilation noisy, masking real errors that should
| be fixed.
|
| I believe this was a mistake (one that sadly Zig also
| follows). In practice there are too many things that wouldn't
| make sense being compiler errors, so you need to run a
| linter. When you need to comment out or remove some code
| temporarily, it won't even build, and then you have to remove
| a chain of unused vars/imports until it let's you, it's just
| annoying.
|
| Meanwhile, unlinted go programs are full of little bugs, e.g.
| unchecked errors or bugs in err-var misuse. If there only
| were warnings...
| Mawr wrote:
| Yeah, but just going back to warnings would be a
| regression.
|
| I believe the correct approach is to offer two build modes:
| release and debug.
|
| Debug compiles super fast and allows unused variables etc,
| but the resulting binary runs super slowly, maybe with
| extra safety checks too, like the race detector.
|
| Release is the default, is strict and runs fast.
|
| That way you can mess about in development all you want,
| but need to clean up before releasing. It would also take
| the pressure off having release builds compile fast,
| allowing for more optimisation passes.
| the_gipsy wrote:
| That doesn't make any sense, you'd still need to run the
| linters on release. Why bail out on "unused var" and not
| on actually harmful stuff.
| dmoy wrote:
| > Debug compiles super fast and allows unused variables
| etc, but the resulting binary runs super slowly, maybe
| with extra safety checks too, like the race detector.
|
| At least in the golang / unused-vars at Google case,
| allowing unused vars is explicitly one of the things that
| makes compilation slower.
|
| In that case it's not "faster compilation as in less
| optimization". It's "faster compilation as in don't have
| to chase down and potentially compile more parts of a
| 5,000,000,000 line codebase because an unused var isn't
| bringing in a dependency that gets immediately dropped on
| the floor".
|
| So it's kinda an orthogonal concern.
| Too wrote:
| Accidentally pulling in a unused dependency during
| development is, if not a purely hypothetical scenario, at
| least an extreme edge case. During debug, most of the
| times you already built those 5000000000 lines while
| trying to reproduce a problem on the original version of
| the code. Since that didn't help, you now want to try
| commenting out one function call. Beep! Unused var.
| pa7ch wrote:
| I feel like people always take the designed for juniors thing
| the wrong way by implying that beneficial (to general
| software engineering) features or ideas were left out as a
| trade off to make the language easier to learn at the cost of
| what the language could be to a senior. I don't think the go
| designers see these as opposing trade offs.
|
| Whats good for the junior can be good for the senior. I think
| PL values have leaned a little too hard towards valuing
| complexity and abstract 'purity' while go was a break away
| from that that has proved successful but controversial.
| ErroneousBosh wrote:
| > This is why unused dependencies are a compile time error.
|
| I think my favourite bit of Go opinionatedness is the code
| formatting.
|
| K&R or GTFO.
|
| Oh you don't like your opening bracket on the same line?
| Tough shit, syntax error.
| throwaway894345 wrote:
| 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.
| throw-the-towel wrote:
| Unfortunately, it's the remaining 20% of Rust features that
| provide 80% of its usefulness.
| osigurdson wrote:
| >> 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.
|
| By 20% of the effort, do you mean learning curve or
| productivity?
| Someone wrote:
| > 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."_ )
|
| (Also, browsing golang's spec, I think I spotted an error in
| https://go.dev/ref/spec#Integer_literals. The grammar says:
| decimal_lit = "0" | ( "1" ... "9" ) [ [ "_" ] decimal_digits
| ] .
|
| Given that, how can _0600_ and _0_600_ be valid integer
| literals in the examples?)
| neild wrote:
| 0600 and 0_600 are octal literals:
| octal_lit = "0" [ "o" | "O" ] [ "_" ] octal_digits .
| j-scott wrote:
| Never mind, I was wrong. Here's a playground showing how go
| parses each one: https://go.dev/play/p/hyWPkL_9C5W
| mseepgood wrote:
| > Octals must start with zero and then o/O literals.
|
| No, the o/O is optional (hence in square brackets), only
| the leading zero is required. All of these are valid
| octal literals in Go:
|
| 0600 (zero six zero zero)
|
| 0_600 (zero underscore six zero zero)
|
| 0o600 (zero lower-case-letter-o six zero zero)
|
| 0O600 (zero upper-case-letter-o six zero zero)
| j-scott wrote:
| My bad! I was wrong; added a playground demonstration the
| parsing behavior above.
| j-scott wrote:
| My original comment was incorrect. These are being parsed as
| octals, not decimals: https://go.dev/play/p/hyWPkL_9C5W
| mseepgood wrote:
| You're looking at the wrong production. They are octal
| literals: octal_lit = "0" [ "o" | "O"
| ] [ "_" ] octal_digits .
| Someone wrote:
| Thanks! Never considered that a 21st century language
| designed for "power of two bits per word" hardware would
| keep that feature from the 1970s, so I never looked at that
| production.
|
| Are there other modern languages that still have that?
| baby wrote:
| 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
| Thorrez wrote:
| Go is getting more complex over time though. E.g. generics.
| weakfish wrote:
| 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.
| jsight wrote:
| I've finally gotten around to learning Go this year and I'm
| having a pretty similar experience.
|
| It really feels like a simpler language and ecosystem compared
| to Python. On top of that, it performs much better!
| jryio wrote:
| 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.
|
| 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 wrote:
| 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.
| MichaelNolan wrote:
| 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.
| kellpossible2 wrote:
| 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.
| HL33tibCe7 wrote:
| vlang is pretty much this
| qouteall wrote:
| There is borgo https://github.com/borgo-lang/borgo but it's not
| yet mature and not being actively developed
| tail_exchange wrote:
| 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.
| thegeekpirate wrote:
| > exhaustive checks for sum types
|
| Linters such as https://golangci-lint.run will do this for you.
| trenchpilgrim wrote:
| > better nulability checks
|
| In development: https://github.com/uber-go/nilaway
| srameshc wrote:
| 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.
| sedatk wrote:
| 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!
|
| https://en.wikipedia.org/wiki/Go!_(programming_language)#Con...
| p2detar wrote:
| 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.
| ashishb wrote:
| Contributing to a new Go codebase is easy.
|
| 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.
| stOneskull wrote:
| 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.
| trenchpilgrim wrote:
| 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.
| ashishb wrote:
| > I'm still trying to convince the scientists I work with
| that they should format their code or use linters.
|
| Consider adding a pre-commit hook if you are allowed to.
| trenchpilgrim wrote:
| My group's repos enforce strict rules, theirs does not.
| millerm wrote:
| Yeah, I've been there. I would get passed down horribly
| formatted code from another repo and it showed the data
| scientists writing it barely knew what they were doing.
| It was their repo, we couldn't do anything about it. They
| wouldn't reformat the code, because they were afraid it
| would break. They also passed us a lot of Python, and you
| can see where they got this fear from.
| reppap wrote:
| I like that I can understand a Go file without deciphering 15
| layers of macros.
| threemux wrote:
| 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!
| bobjordan wrote:
| 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.
| kasperset wrote:
| 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.
| rishabhaiover wrote:
| Love Go! It gently introduced me to the systems programming
| world.
| nicodjimenez wrote:
| 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.
| wanderlust123 wrote:
| I think lack of classes is highly desirable. So much enterprise
| code is poorly put together abstractions.
|
| I think go needs some more functional aspects, like iterators
| and result type/pattern matching.
| robryan wrote:
| Go does have iterators: https://pkg.go.dev/iter
| wanderlust123 wrote:
| Thanks! Did not see this until your message, looking
| forward to make use of this
| nicodjimenez wrote:
| The solution to bad abstractions it not to make it very
| difficult to create abstractions at all. For systems code I
| think it's fine but for application code you probably want
| some abstractions or else it's very hard to scale a codebase.
| grey-area wrote:
| 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.
|
| https://www.infoworld.com/article/2160788/why-extends-is-evi...
| ModernMech wrote:
| 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.
|
| _Status changed to Unfortunate_
|
| https://github.com/golang/go/issues/9#issuecomment-66047478
| MagicMoonlight wrote:
| Does anyone use that other language? No!
| ModernMech wrote:
| That's not the point, no one uses 99% of languages, so if
| that's the standard then it's a free-for-all. The PL
| community is small, so norms are important.
|
| PL naming code is:
|
| 1. Whoever uses the name first, has claim to the name. Using
| the name first is measured by: when was the spec published,
| or when is the first repo commit.
|
| 2. A name can be reused IFF the author has abandoned the
| original project. Usually there's a grace period depending on
| how long the project was under development. But if a project
| is abandoned then there's nothing to stop someone from
| picking up the name.
|
| 3. Under no circumstances should a PL dev step on the name of
| a currently active PL project. If that happens, it's up to
| the most recently named project to change their name, not the
| older project even if the newer project has money behind it.
|
| 4. Language names with historical notoriety are essentially
| "retired" despite not being actively developed anymore.
|
| All of this is reasonable, because the PL namespace is still
| largely unsaturated*. There are plenty of one syllable
| English words that are out there for grabs. All sorts of
| animals, verbs, nouns, and human names that are common for
| PLs are there for the taking. There's _no_ reason to step on
| someone else 's work just because there's some tie in with
| your company's branding.
|
| So it's pretty bottom basement behavior for luminaries like
| Ken Thompson and Rob Pike to cosign Google throwing around
| their weight to step on another dev's work, and then say
| essentially "make me" when asked to stop.
|
| * This of course does not apply to the single-letter langs,
| but even still, that namespace doesn't really have 25 langs
| under active development.
| arccy wrote:
| Like how C and C# are different languages, Go and Go! are
| different. There's not name reuse here.
| ModernMech wrote:
| Go and Go! are pronounced the same way, so yes, they're
| the same.
|
| Moreover _the author of Go! personally requested that
| Google not step on his life 's work._ The man had
| dedicated a decade and authored a book and several papers
| on the topic, so it wasn't a close call. Additionally C#
| built on C++ which built on C. Go had no relationship to
| Go! at all. Homage and extension are one thing, but Go
| was not that.
|
| A policy of "do no evil" required Google to acquiesce.
| Instead they told him to pound sand.
| duskwuff wrote:
| Go! wasn't even published as its own project [1] until 2015,
| well after Go(lang) was available. It previously existed as
| an unpublished CVS repository in an obscure Sourceforge
| project [2]; I can't fault the Go developers for ignoring or
| overlooking it. You can find a circa-2002 version of Go! in
| the archived CVS repository of the Sourceforge project, but
| none of the project's release files appear to contain it.
|
| (Ignore the "Last Update: 2013-09-06" on the project page -
| that's the date that SourceForge performed an automatic
| migration. Any real activity on the project seems to have
| petered out around 2002, with one final file released in
| 2003.)
|
| [1]: https://github.com/fgmccabe/go
|
| [2]: https://sourceforge.net/projects/networkagent/
| anal_reactor wrote:
| 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.
| zmj wrote:
| I'm glad Go exists. If nothing else, it cemented that tooling is
| at least as important as the language.
| MagicMoonlight wrote:
| I just can't get over the idiotic syntax.
|
| 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.
| LexiMax wrote:
| 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;
| } }
| mxey wrote:
| > don't know if they've ever told anybody why they went with
| the Pascal style
|
| I don't know if this is the reason but Robert Griesemer, one
| of the three original guys, comes from a Pascal/Modula
| background.
| anal_reactor wrote:
| Golang exists in this weird place where it's similar enough
| to C so that intuition connects it with C, but at the same
| time different enough that you keep tripping over.
| gf000 wrote:
| I have no problem with ident: type. I have problem with
| dropping the colon between them for no good reason, even
| though there used to be 2 quite well-established patterns
| _every_ language adhered to.
| bbkane wrote:
| I prefer this, especially for more complex types like
| functions- https://go.dev/blog/declaration-syntax gives an
| overview of their thought process
| gf000 wrote:
| "x: int p: pointer to int a: array[3] of int These
| declarations are clear, if verbose - you just read them left
| to right. Go takes its cue from here, but in the interests of
| brevity it drops the colon and removes some of the keywords "
|
| And in the process makes it significantly harder for human
| eyes to find the boundary between identifier and type.
| mxey wrote:
| how would that look with type inference?
|
| 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.
| captainkrtek wrote:
| 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.
| Pbhaskal wrote:
| 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
| adamddev1 wrote:
| 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.
| culebron21 wrote:
| 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
|
| * iterators
|
| * result unwrapping shorthands
| alain_gilbert wrote:
| 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!
|
| https://github.com/alaingilbert/agl
| 9rx wrote:
| _> proper enums_
|
| 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...
| culebron21 wrote:
| > It has proper enums.
|
| Well, then they look awkward and have give a feel like it's a
| syntax abuse.
|
| > Its arrays and slices are exactly the same as how you would
| do it in C. So while it is true that trips up 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.
|
| In Rust, I see exactly what I work with -- a proper vector,
| material thing, or a slice, which is a view into a vector.
| Also, a slice in Rust is always contiguous, it starts from
| element a and finishes at element b. I can remove an
| arbitrary element from a middle of a vector, but slice is
| read-only, and I simply can't. I can push (append) only to a
| vector. I can insert in the middle of a vector -- and the doc
| warns me that it'll need to shift every element after it
| forward. There's just zero magic.
|
| In Go instead, how do I insert an element in the middle of an
| array? I see suggestions like `myarray[:123] +
| []MyType{my_element} + myarray[123:]`. (Removing is like
| myarray[:123] + myarray[124:]`.)
|
| What do I deal in this code with, and what do I get
| afterwards? Is this a sophisticated slice that keeps 3 views,
| 2 to myarray and 1 to the anonymous one?
|
| The docs on the internet suggest that slices in go are
| exactly like in Rust, a contiguous sequence of array's
| elements. If so, in my example of inserting (as well as when
| deleting), there must be a lot happening under the hood.
| 9rx wrote:
| _> Well, then they look awkward and have give a feel like
| it 's a syntax abuse._
|
| So nothing to worry about?
|
| _> how do I insert an element in the middle of an array?_
|
| Same as in C. If the array allocation is large enough, you
| can move the right hand side to the next memory location,
| and then replace the middle value.
|
| Something like: replaceWith := 3
| replaceAt := 2 array := [5]int{1, 2, 4, 5}
| size := 4 for i := size; i > replaceAt; i-- {
| array[i] = array[i-1] } array[replaceAt] =
| replaceWith fmt.Println(array) // Output: [1 2 3 4
| 5]
|
| If the array is not large enough, well, you are out of
| luck. Just like C, arrays must be allocated with a fixed
| size defined at compile time.
|
| _> The docs on the internet suggest that slices in go are
| exactly like in Rust, a contiguous sequence of array 's
| elements._
|
| They're exactly like how you'd implement a slice in C:
| struct slice { void *ptr; size_t
| len; size_t cap; };
|
| The only thing Go really adds, aside from making slice a
| built-in type, that you wouldn't find in C is the [:]
| syntax.
|
| Which isn't exactly the same as Rust. Technically, a Rust
| slice looks something like: struct slice
| { void *ptr; size_t len; };
|
| There is some obvious overlap, of course. It still has to
| run on the same computer at the end of the day. But there
| is enough magic in Rust to hide the details that I think
| that you lose the nuance in that description. Go, on the
| other hand, picks up the exact same patterns one uses in C.
| So if you understand how you'd do it in C, you understand
| how you'd do it in Go.
|
| Of course, that does mean operating a bit lower level than
| some developers are used to. Go favours making expensive
| operations obvious so that is a tradeoff it is willing to
| make, but regardless if it were to make it more familiar to
| developers coming from the land of magic it stands that it
| would require more magic, not less.
| culebron21 wrote:
| Ok, so mostly we agree. And I was right that you can't
| just concatenate different slices (e.g. to remove one
| item from the middle), hence Go has to do a lot of work
| under the hood to do that. I count this as magic.
| zimpenfish wrote:
| I may have misunderstood "you can't just concatenate
| different slices (e.g. to remove one item from the
| middle" but does [0] not do what you're talking about?
|
| (with the caveat that anything else sharing `a` will be
| mangled, obvs.)
|
| [0] https://go.dev/play/p/uQdoa3mUF00
| 9rx wrote:
| _> Ok, so mostly we agree._
|
| I don't follow. Information isn't agreeable or
| disagreeable, it just is.
|
| _> And I was right that you can 't just concatenate
| different slices_
|
| That's right. You would have to physically move the
| capacitors in your RAM around (while remaining powered!)
| in order to do that. Given the limits of our current
| understanding of science, that's impossible.
|
| _> hence Go has to do a lot of work under the hood to do
| that._
|
| Do what? You can't actually do that. It cannot be done at
| the hardware level. There is nothing a programming
| language can do to enable it.
|
| All a programming language can do is what we earlier
| demonstrated for arrays, or as slices allow dynamic
| allocation, if the original slice is not large enough you
| can also copy smaller slices into a new slice using a
| similar technique to the for loop above.
|
| Go does offer a copy function and an append function that
| do the same kind of thing as the for loop above so you do
| not have to write the loop yourself every time. I guess
| that's what you think is magic? If you are suggesting
| that calling a function is magic, well, uh... You're not
| going to like this whole modern programming thing. Even
| Rust has functions, I'm afraid.
|
| The Go standard library also provides a function for
| inserting into the middle of a slice, but, again, that's
| just a plain old boring function that adds some
| conditional logic around the use of the append and copy
| functions. It is really no different to how you'd write
| the code yourself. So, unless function are still deemed
| magic...
| pekim wrote:
| Inserting elements in to a slice can be done quite easily
| since the introduction of the slices package to the
| standard library.
|
| https://pkg.go.dev/slices#Insert
| callc wrote:
| You shouldn't need a library to do this simple operation.
|
| I'm guessing the go language design went too far into
| "simplicity" at the expense of reasonableness.
|
| For example, we can make a "simpler" language by not
| supporting multiplication, just use addition and write
| your own!
| 9rx wrote:
| The operation is simple in concept, but can be costly
| from a compute standpoint when _n_ is large.
| Multiplication has predicable performance. Insert does
| not. It being a function indicates that it is doing a lot
| of things and thus offers pause to make sure that the
| operation is acceptably within your operational bounds.
|
| It could have been a builtin function, I suppose, but why
| not place it in the standard library? It's not a
| foundational operation. If you look at the
| implementation, you'll notice it simply rolls up several
| foundation operations into one function. That is exactly
| the kind of thing you'd expect to find in a standard
| library.
| tptacek wrote:
| I wish Go had sum types too. But I like being able to write a
| mutable tree structure without first having to read a whole
| book on the subject and inventing a new system of pointers.
| Every language is tradeoffs.
| zerr wrote:
| As a C++ dev, such comments reinforce my hesitation to pick
| up either Go or Rust seriously :) It seems I already have
| the golden middle after all.
| EnergyAmy wrote:
| I like the language saying "it's not as easy as you think"
| when I'm about to do something ill-advised like roll my own
| mutable tree structure.
| bobbylarrybobby wrote:
| I mean, it is as easy as you think in a GC language
| tptacek wrote:
| You understand that tree structures aren't just lookup
| tables, right? I wouldn't roll my own red-black tree
| (Jesus how tedious would that be). That's not what I'm
| talking about.
| dilyevsky wrote:
| It is in fact not that hard when your memory is
| automatically managed
| Zababa wrote:
| 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.
|
| That is not a problem with Go.
| Mawr wrote:
| > it lacks iterators -- every time you must write a big cycle
| instead
|
| 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
| culebron21 wrote:
| > `value, keyExists := myMap[someKey]`
|
| If I don't need the value, I have to do awkward tricks with
| this construct. like `if _, key_exists := my_may[key];
| key_exists { ... }`.
|
| Also, you can do `value := myMap[someKey]`, and it will just
| return a value or nil.
|
| Also, if the map has arrays as elements, it will magically
| create one, like Python's defaultdict.
|
| This construct (assigning from map subscript) is pure magic,
| despite all the claims, that there's none in Golang.
|
| ...And also: I guess the idea was to make the language
| minimal and easy to learn, hence primitives have no methods
| on them. But... after all OOP in limited form is there in
| Golang, exactly like in Rust. And I don't see the point why
| custom structs do have methods, and it's easier to use, but
| basic ones don't, and you have to go import packages.
|
| Not that it's wrong. But it's not easier at all, and learning
| curve just moves to another place.
| lenkite wrote:
| > Also, if the map has arrays as elements, it will
| magically create one, like Python's defaultdict.
|
| Err, no Go doesn't do that. No insertion happens unless you
| explicitly assign to the key.
| culebron21 wrote:
| You're right. But it will return something:
| https://go.dev/play/p/Cz6aeGpURgo my_map
| := make(map[int32][]int64) val := my_map[123]
| val = append(val, 456) my_map[123] = val
| fmt.Println(my_map)
|
| prints `map[123:[456]]`
|
| I guess it's convenient compared to Rust's strict
| approach with entry API. But also, what I found is that
| golang's subscript returns nil in one case: if the value
| type is a nested map. my_map :=
| make(map[int32]map[int32]int64) val := my_map[123]
| val[456] = 789 my_map[123] = val
| fmt.Println(my_map)
|
| output: panic: assignment to entry in nil
| map
| HL33tibCe7 wrote:
| It returns the zero value for all types, including arrays
| (which is nil).
|
| nil is equivalent to the empty array, which is why the
| rest of the code works as it does.
| tiltowait wrote:
| You can test for existence: val, ok :=
| my_map[123] if ok { ... }
|
| https://go.dev/blog/maps#working-with-maps
| HL33tibCe7 wrote:
| > But it's not easier at all, and learning curve just moves
| to another place.
|
| Hard disagree. Go has its sharp corners, but they don't
| even approach the complexity of the borrow checker of Rust
| alone, let alone all of the other complexity of the Rust
| ecosystem.
| zimpenfish wrote:
| > Also, you can do `value := myMap[someKey]`, and it will
| just return a value or nil.
|
| It might if your map is a `map[typeA]*typeB` but it
| definitely won't return a `nil` if your map is anything
| like `map[typeA]typeC` (where `typeC` is non-nillable; i.e.
| int, float, string, bool, rune, byte, time.Time, etc.) -
| you'll get a compile error: "mismatched types typeC and
| untyped nil".
| lenkite wrote:
| > This makes you split functions in many pieces, turning your
| code into enterprise Java.
|
| Umm..in Java you won't have to split functions here. Maybe you
| should study some modern Java ?
| jiehong wrote:
| 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).
| tapirl wrote:
| > Go stands by its compatibility promise--the old way will
| continue to work in perpetuity ...
|
| 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
| gf000 wrote:
| It's especially funny considering that this issue has been
| known from lisps for 50+ years..
| pjmlp wrote:
| And still so many programming language design history lessons to
| learn from.
|
| Maybe by 18, or 21, the maturity finally settles in.
| rollulus wrote:
| 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.
| tmoertel wrote:
| 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.
|
| [1] https://abseil.io/resources/swe-book/html/ch22.html
| liampulles wrote:
| 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.
| linhns wrote:
| Agreed. This use case is not mentioned enough.
| liveoneggs wrote:
| I don't understand how this isn't also true for practically
| every other language?
| vlovich123 wrote:
| It's not true of C/C++ which need changes to the build
| system. Also true for rust workspaces which is how I'd
| recommend structuring monorepos although it is generally easy
| (you just need to add a small cargo.toml file) or you can not
| use a workspace but you still need to declare the binary if I
| recall correctly.
| o11c wrote:
| It's true for any C/C++ project which bothers to write 10
| lines of GNU `make` code.
|
| The problem is that many projects still pander to inferior
| 1980s-era `make` implementations, and as such rely heavily
| on the abominations that are autotools and cmake.
| duskwuff wrote:
| C/C++ library dependencies are a thing, and there's no
| universal solution to acquiring and installing them.
| bayindirh wrote:
| The most universal thing in C/C++ is vendoring, IMHO.
|
| If you are distributing source, you distribute
| everything. Then, it only needs a compiler and libc. That
| vendored package is tested, and it works on your
| platform, so there's no guesswork.
| LexiMax wrote:
| Autotools is far too pessimistic, but there are still
| considerable differences between different compiling
| environments. Tooling like CMake will always be necessary
| unless you are only targeting unix and your dependency
| graph isn't terribly deep.
|
| Even in that specific niche I find using a
| programmatically generated ninja file to be a far
| superior experience to GNU make.
| wredcoll wrote:
| The distinction, I believe, is between "possible" and "easy".
| Go makes a lot of very specific things easy via some of its
| design choices with language and tooling.
|
| As a counter example, it seems like e.g. c++ is mostly
| concerned about making things possible and rarely about easy.
| Zardoz84 wrote:
| I tough that would be about SWEET16
| insurancesucks wrote:
| Every Go thread on this site is the same.
|
| "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
| disintegrator wrote:
| 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.
| mikewarot wrote:
| And here I was anticipating a release of Go for the Apple ][
| computer[16]
|
| [16] https://en.wikipedia.org/wiki/SWEET16
| duskwuff wrote:
| It might be possible. TinyGo exists, and can target some
| devices with even less memory than the Apple II, like the
| ATmega328 microcontroller.
| submeta wrote:
| 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.
___________________________________________________________________
(page generated 2025-11-15 23:01 UTC)