12 ms·
An Honest Review of Go (2025)
- auggierose 9mo agoSafari doesn't show the t's. Why?? Chrome does.
- jacknews 9mo agoexactly wtf is up with this website, firefox doesn't show t's, random f's, d's - it's a complete mess.
- b40d-48b2-979e 9mo agofirefox doesn't show I'm using the Firefox Developer version on Windows and everything renders correctly for me. I tested Firefox on Android and everything is present there as well.
- prophesi 9mo agoNo issues here on Firefox 146 Fedora/GNOME. Also imagine it's not uncommon for a personal site to not test for Safari if they're not in the Apple ecosystem.
- nullpoint420 9mo agoAs a fellow Fedora/GNOME user, fun fact: GNOME Web uses the same web engine as Safari! They both use Webkit, so it's not out of reach.
- michaelcampbell 9mo agoFF working as expected for me on Ubuntu
- benrazdev 9mo agoMy best guess is that the font I am using (WOFF2 variable font) might be tripping up the browser.
- auggierose 9mo agoThat's probably it. I am getting these problems with Safari 17.6, with a newer one, Safari 26.0.1, there is no problem.
- tombert 9mo agoI commend Go for popularizing the channel-based concurrency, since I do think that that is a very elegant way of structuring stuff (especially compared to mutexes), but I have to admit that I don’t have a lot of fun writing Go. I agree with a lot of the sentiment of this post; the weirdness with “tuples”, the weirdness of the error types, and etc. It’s not a “bad” language, just one that I don’t enjoy using. Historically to get something similar to Go-style concurrency I would use Clojure with core.async, but more recently I have started using Rust and Tokio.
- OkayPhysicist 9mo agoIMO, this is because Go succeeded at its intended to goal: to create a language that people with very little Computer Science (but some C/C++ programming) experience can be productive in. It eschews basically all abstractions that take more than 30s to explain to someone, which leaves a lot of really useful ones on the cutting room floor.
- tombert 9mo agoThat’s fair. I came into Go relatively late and from a more Functional Programming background, so the language ends up being kind of annoying to me but that is probably not the case for others.
- OkayPhysicist 9mo agoDon't get me wrong, I don't think it was a good goal. But that goal is the original sin of Go as a language, and most of the bad decisions that have been made in Go's design are in pursuit of it.
- benrazdev 9mo agoI agree with your point in general, but I would challenge the idea that tuples aren't something that is intuitive to explain (even in less than 30 seconds). Perhaps it's difficult to explain why tuples and not lists, but that's also relatively simple (homogeneous vs heterogeneous)
- 9mo ago
- eximius 9mo agoLack of enums are the main point for me. The error story is not ideal but less bad than that most of the time, as you can downcast to access extra error data. Still, harder than it needs to be. Overall, I've grown to like using the language even despite its warts.
- MobiusHorizons 9mo agoIt doesn’t have the enum keyword, but there is an idiomatic way to make enums in the language. They just end up being typed constants.
- weitendorf 9mo agoThe problem is that this makes enums non-enumerable. They need to be represented as a range or union type to do that. I am pretty sure I know why/how Go ended up like this because it’s inherited behavior from proto, wrote a large comment later down the thread explaining why.
- estebank 9mo agoWhen people say they want sum types, they generally mean they want both sum types and exhaustive pattern matching. Either of these features on isolation are nice to have, but both together are incredibly powerful to the point where having just one is almost not worth it.
- MobiusHorizons 9mo agoIs this what people mean by Enums? I must not have used languages where Enums have those powers. I have often been very confused by statements people make about Enums so that would make some sense. How do sum types address the problem that the underlying type (int or string or whatever) is totally capable of describing values other than those your code was compiled with? I'm mostly thinking of version skew with something like a dynamic library or plugin, although casting would probably also have the same effect.
- 9mo ago
- dewey 9mo agofyi your about page doesn't work: https://benraz.dev/about.html https://benraz.dev/about.html
- lagniappe 9mo agoGo is a pleasure to use. The stdlib is one of the most complete, while keeping the keyword count low. LLMs understand it very well, project size stays low, line count stays low (if err nil included), doesn't need a bunch of scaffolded boilerplate in the project directory, and it compiles very quickly for a ton of OS and architectures. Very seldom do I ever need to go outside of the stdlib. Is it perfect for everything? no. Is it the fastest compiled language out there? no. But, it'll do most things very well, and for me that's good enough. I choose go because when I need to make something, it steps aside and lets me build, and for that I have great respect and appreciation for it. I will be defering all detractors and negative comments ;)
- themicahshell 9mo agoYou defer at the beginning, not at the end in Go. /jk
- lagniappe 9mo agoHey you caught that! I was hoping someone would notice the joke :)
- nh23423fefe 9mo ago> The stdlib is one of the most complete what does this mean? Go lib seems tiny compared to JDK. anytime i review some Go code from adjacent team i'm turned off by weird stuff like append and slices everywhere, as well as a bunch of strange string packages When I think of a massive stdlib I think of a language like groovy
- embedding-shape 9mo agoThen ask a JS web developer what "big standard library" would mean, and Go probably would fit somehow with that definition :) It seems to be very relative depending on where you come from.
- MobiusHorizons 9mo agoThe api surface is relatively small, but the capabilities you get from it (http serving, json parsing, crypto, in addition to table stakes like io, args, flags etc) are very high. Having a small api surface is why you need to use primatives so often, but the upside benefit to that is there is less domain specific knowledge, since you end up using familiar types and libraries in more of your code.
- rcarmo 9mo agoAs someone who's been back into Go a couple of times (oscillating between Python, "C-ish" languages and the like), the ONE thing I hate about Go is error handling. The rest I can live with just fine.
- Xeoncross 9mo agoOne of the things I wish more people talked about isn't just the language or the syntax, but the ecosystem. Programming isn't just typing, it's dealing with dependencies and trying to wire everything up so you can have tests, benchmarks, code-generation and build scripts all working together well. When I use modern languages like Go or Rust I don't have to deal with all the stuff added to other languages over the past 20 years like unicode, unit testing, linting, or concurrency. I use Go where the team knows Java, Ruby or TypeScript but needs performance with low memory overhead. All the normal stuff is right there in the stdlib like JSON parsing, ECC / RSA encryption, or Image generation. You can write a working REST API with zero dependencies. Not to mention so far all Go programs I've ever seen still compile fine unlike those Python or Ruby projects where everything is broken because it's been 8mo. However, I'd pick Rust when the team isn't scared of learning to program for real.
- anttiharju 9mo agoI like Rust. I don't like that for fairly basic things one has to quickly reach for crates. I suppose it allows the best implementation to emerge and not be concerned with a breaking change to the language itself. I also don't like how difficult it is to cross-compile from Linux to macOS. zig cc exists, but quickly runs into a situation where a linker flag is unsupported. The rust-lang/libc also (apparently?) insists on adding a flag related to iconv for macOS even though it's apparently not even used? But writing Rust is fun. You kind of don't need to worry so much about trivialities because the compiler is so strict and can focus on the interesting stuff.
- Xeoncross 9mo agoYeah, I've never seen an all-in-one language like Go before. Not just a huge stdlib where you don't have to vet the authors on github to see if you'll be okay using their package, but also a huge amount of utility built in like benchmarking, testing, multiple platforms, profiling, formatting, and race-detection to name a few. I'm sad they still allow null, but they got a lot right when it comes to the tools. Everything is literally built-in. It's the perfect scripting language replacement with the fast compile time and tiny language spec (Java 900 pages vs Go 130 pages) making it easy to fully train C-family devs into it within a couple weeks.
- tschellenbach 9mo ago10 years ago we started out with Python. We switched to Go probably 8 years back. I think my little startup would have utterly failed without Go. Thx google :) But yes Enums are so much nicer in Kotlin vs Go. That's true, it doesn't impact productivity much, but he has a point.
- sethammons 9mo agoI think some pythonistas maybe got their feeling hurt by your comment causing it to grey out. Over the last 25 years in the SaaS world, I have never seen python evolve into a system that is easy to reason about and debug. It lets you do too many things. In over 30 cases, I have seen teams deliver better software faster in Go after replacing their Python.
- deleted 9mo ago[deleted]
- jerf 9mo agoAuthor is still early in their exploration and has some definite mistakes in here. Probably the biggest one is around the error handling, thinking that the only way to interact with an error is through the error interface itself. That is intended as a baseline interaction, a fallback for when nothing else is appropriate, such as just slamming an error into a log. If you want to interact with specific errors, you should use the various functions in the errors package [1] to check for specific types, and then use those specific types in whatever they support. Go error support is quite good; you can return an error object that says "The user was not found, the file the user was supposed to be found in was not found, and while trying to log this the log failed to accept the write" as various error types composed together, and any consumer of the error using the errors package can pick out the various bits of the error they understand using those tools without having to understand the error binding them together or the components it doesn't care about . You should never use string manipulation to check errors unless you have no choice, and whatever library left you with no choice should have an issue filed against it. It doesn't come up often, but it does sometimes come up; most recently I had the AWS SDK emitting an error I could only use string functions on, but I think they've since fixed it. I don't like the term "enums" because of the overloading between simple integers that indicate something (the older, more traditional meaning) and using them to mean "sum types" when we have the perfectly sensible term "sum type" already, that doesn't conflict with the older meaning. If you want sum types, a better approach is to combine the sort of code structure defined here: https://appliedgo.net/spotlight/sum-types-in-go/ https://appliedgo.net/spotlight/sum-types-in-go/ with a linter to enforce it https://github.com/alecthomas/go-check-sumtype https://github.com/alecthomas/go-check-sumtype , which is even better used as a component of golangci-lint: https://golangci-lint.run/ https://golangci-lint.run/ I'd also add my own warnings about reaching for sum types when they aren't necessary, in a language where they are not first class citizens: https://jerf.org/iri/post/2960/ https://jerf.org/iri/post/2960/ but at the same time I'd also underline that I do use them when appropriate in my Go code, so it's not a warning to never use them. It's more a warning that sum types are not somehow Platonically ideal. They're tools, subject to cost/benefit analysis just like anything else. [1]: https://pkg.go.dev/errors https://pkg.go.dev/errors
- dkarl 9mo ago> I don't like the term "enums" because of the overloading between simple integers that indicate something (the older, more traditional meaning) I disagree with this. I'm old as hell, and I learned programming in a context where enums were always ints, but I remember being introduced to int enums as "we're going to use ints to represent the values of our enum," not "enums are when you use ints to represent a set of values." From the very beginning of my acquaintance with enums, long before I encountered a language that offered any other implementation of them, it was clear that enums were a concept independent of ints, and ints just happened to be an efficient way of representing them.
- ajross 9mo agoI don't buy that example about errors at the end at all. The problem the author is trying to solve is to write code that calls a foreign/fixed-API function that is known to return a particular subtype of Error, and wants to extract structured information from it. But you can't, because the type returned is just the outer Error type that only has a string. Obviously, though, the only way this happens is if you know a priori what actually failed, because otherwise it might be some other error type. And you don't, obviously, because it's an error! If your behavior is deterministic then just return whatever you want in your own API. If it's not, you need to parse/extract/inspect the error. Basically it's entirely contrived. This never happens, and to the extent it does it's a terrible bug where you have code making assumptions about runtime error state without fully inspecting that state. The second failure is that Go does in fact have runtime type inspection facilities ("type assertions" is the particular jargon) and if you want you can absolutely "cast" that error into a derived type to get the data out. So it's not even a problem in the language as it exists.
- iamcalledrob 9mo agoI'd encourage the author to spend more time learning Go. They've come to incorrect conclusions -- especially regarding errors. Read more of the stdlib to see how powerful they can be, e.g. net.OpError: https://cs.opensource.google/go/go/+/refs/tags/go1.25.5:src/net/net.go;l=472 https://cs.opensource.google/go/go/+/refs/tags/go1.25.5:src/... > The user now has an interface value error that the only thing > they can do is access the string representation of ... The only > resort the consumer of this library has is to parse the string > value of this error for useful information. This shows a lack of understanding about the `error` interface, `errors.Is`, `errors.As`, error wrapping etc. Personally, I think Go errors are fantastic, just the right sprinkling of structure on top of values. And panic/recover for truly exceptional circumstances.
- bccdee 9mo agoYou're right, but I still think they have a point. What I miss from `error.Is/As` is exhaustive matching. I'd love a way to statically guarantee I haven't missed an important error type. It really comes back to the absence of sum types.
- packetlost 9mo agoYeah, the lack of sum types of any kind in Go is the only thing that I really miss when coming back from Rust. It's, I think, a big part of the reason that Gleam has seen a lot of growth. It has many of the syntactic benefits of Go with the compiler guarantees of Rust (though it's weird in some other ways, like dramatically favoring continuation-passing-style in programmer facing syntax).
- deleted 9mo ago[deleted]
- 9rx 9mo ago> I'd love a way to statically guarantee I haven't missed an important error type. It wouldn't be hard — rather easy, even — to write a static analyzer for that if you constrained your expectations to cases where sum types could practically be used. No reason to not do it right now! But sum types don't really solve for a lot of cases. Even in Go you can add additional constraints to errors to get something approaching sum types. You don't have to use a naked `error`. But you are bound to start feeling pain down the road if you try. There is good reason why even the languages that support defined error sets have trended back to using open-ended constructs. It does sound great in theory, no doubt, but reality is not so kind.
- ddoolin 9mo agoI've only written a handful of production projects in Go so my experience isn't very deep, but I find the syntax to be the ugliest of any PL. The mixed capitalizing based on function privacy, to me, is awful (among other things, i.e. personally I loathe curly brace initialization/definition). I'm sure you get used to it? It doesn't help that it just feels very hacked together, from the wonky generics, the lack of useful types like tuples and enums, the bolted on module system, to the annoying error handling, to say the least. That said, compile times are great, the concurrency is dead simple, it's performant, and it's still easy to be really productive in it so it's not like I'd never consider it. Many other languages have many of the same issues, anyway.
- usrbinbash 9mo ago> The mixed capitalizing based on function privacy, to me, is awful Awful compared to ... what? `private` and `public` keywords? Ugly hacks like pythons `_` and `__`? > it just feels very hacked together > the wonky generics What exactly about the generics is "wonky"? "Wonky" is not a term defined in any programming textbook I ever read. And languages are not designed on feelings, especially when the design goal is to be as pragmatic as possible, as is the case in Go. > the lack of useful types like tuples and enums, Need a tuple? Use an array and don't change it. - [2]string: string 2-tuple - [5]int: int 5-tuple - [1]any: empty-interface 1-tuple And btw. 99% of the time tuples are used, it's as a stand-in for multiple-returns. E.g. Python does that. Go simply has...multiple returns. > and enums, Outside of language-enthusiasm with matching and whatnot (which more often than not is used because it looks cool rather than being useful), the most common (and again, 99%) use of enums, is to give names to magic values. Go has that covered: type Color string const ( RED Color = iota GREEN BLUE ) > the bolted on module system Pray tell what exactly is "bolted on" about modules? They are simply an extension of the import system, nothing more, nothing less. > the annoying error handling The "annoying" thing about it is that it's explicit and forced. Both of which are positives as far as I'm concerned, because I AM FREKKIN DONE with shitty 10-mile stacktraces because some joksters library threw an "exception" 400 layers down in some sub-sub-sub-sub transient dependency lib.
- 9mo ago
- lenkite 9mo agoHis example criticizing errors in `rootInfo` func is silly. There is utterly no need to do a `strings.HasSuffix(err.Error(), "not a directory")`.
- shirogane86x 9mo agobut how would you do that otherwise? Genuinely curious cause I looked up both the go docs and source (disclaimer: not a go dev), and there doesn't seem a way to handle that specific kind of error through stuff like `errors.Is`, at least from what I can tell, at least in the os and fs packages
- benrazdev 9mo agoFrom what the comments are saying I think you downcast with `errors.As` and then work on the underlying error type. But I don't know for sure.
- deleted 9mo ago[deleted]
- lenkite 9mo agoHe can do a test using `errors.Is(err, syscall.ENOTDIR)` func rootInfo(root, p string) (has bool, isDir bool, err error) { p = path.Clean(p) info, err := os.Stat(root + "/" + p) if info != nil { has, isDir = true, info.IsDir() return } if errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) { err = nil } return }
- divan 9mo ago> difficulty of writing if err != nil Literally the simplest way to deal with errors (cognitively and character wise). Since AI autocomplete entered the scene, typing this repetitive (for a reason) pattern became not a problem at all (I'm not even talking about post Claude Code era) > The only resort the consumer of this library has is to parse the string value of this error for useful information. Well, no. See for wrap/unwrap functionality https://go.dev/blog/go1.13-errors https://go.dev/blog/go1.13-errors > In Go, errors are values. They just aren’t particularly useful values. In his example author could easily use his `progError` type instead. Gosh, why it's so tempting to write a post about bad language instead of just reading docs or article about idiomatic usage?
- stouset 9mo ago> typing this repetitive (for a reason) pattern became not a problem at all Code is read 10x more than it is written. The noise this pattern introduces inhibits reading and rapid comprehension. Things are getting marginally better now that go has errors.Is and errors.As, and also now that go is starting to get some functional iterators. But go is one of the least quickly-understandable of the modern languages currently in use.
- divan 9mo ago> The noise this pattern introduces Here is the thing... it's NOT a 'noise'. Untill you see handling 'error path' as noise, you will be trapped in searching magic bullet language solution to hide it. We've all been there.
- dematz 9mo agoCorrect me if I'm wrong, but the Error interface means you can display the error as a string, but you don't have to? Like the err.Error() is idiomatic if you just want to display something, but you could also use the error itself https://pkg.go.dev/errors#As https://pkg.go.dev/errors#As here's an example that uses a field from your blog example error type: https://go.dev/play/p/SoVrnfXfzZy https://go.dev/play/p/SoVrnfXfzZy Also "In Go, errors are values. They just aren’t particularly useful values" ...sometimes user mistakes are due to the language being too complicated, maybe for no benefit, but I don't think that's the case here. It's a very good thing that you can just slap .Error() on any error to print it quickly, and not too crazy complex to say an error can be any normal type that you can use, as long as it also can print Error()
- MobiusHorizons 9mo agoMy guess is that the author hasn’t fully frocked how go interfaces work yet. Go errors implement the error interface, but that just makes them interoperable, it doesn’t mean that’s all they are.
- benrazdev 9mo agoCorrect me if I am wrong, but does it not mean that they are type-erased though? The whole point of returning an interface is to perform type-erasure. If I have struct S { X int } func (s *S) Error() string { ... } but I return it as an error: func DoStuff() error Then all the caller gets is an error interface. Without downcasting (`.(T)`/`errors.As`), you can only compare it to other instances (if the library author provided them) or see the string representation.
- MobiusHorizons 9mo agoYes, that's correct. The interface limits what guarantees the caller has about the type without runtime introspection. I don't think that really makes it any harder to handle expected error conditions though, since type assertions return a boolean. eg: if myErr, ok := err.(MyError); ok { // handle MyError case } ... But you should always expect that there could be errors you don't expect to exhaustively handle with special logic.
- witnessme 9mo agoCracked at "I need to contribute my own beating so this horse is really dead"
- weitendorf 9mo agoI think I know why Go ended up without good enum support. (Disclaimer, formerly worked at Google and used proto/grpc/go there and now in my own startup in github.com/accretional/collector which tries to address this problem with a type registry and fully reflective API. Not privy to the full history, just reasoning.) Proto is designed so that messages can be deserialized into older/previous proto definitions by clients even if the server is responding with messages of a more recent version. Field numbers Re what let you to start serializing new fields (add a new field with an unused/the next number) or safely stop setting fields in proto responses (reserve a field) without risking older clients misinterpreting the data as belonging to some existing field they know about. This requires you to encode the field numbers alongside the field data in the proto wire format. Two major problems: nothing in proto itself enforces that field numbers are assigned sequentially, because there is no single source of truth for the proto schema (you can still have one of your own, but it’s not a “thing” in proto). Also, the whole point of field numbers is that they can be selectively missing/reserved/ignored and allow you to deserialize messages without special handling for version changes in your code at runtime. So, field numbers aren’t a dense, easily enumerable range of numbers, they’re basically tags that can be any number between 1 and 536,870,911 except for the reserved 19,000-19,999. This smells like serious tech debt/ a design flaw that completely closes the door for even fixing this at Google or anywhere else, because it’s arbitrarily in the middle of the range of field numbers and a leaked implementation detail from the internals. You couldn’t build your own dense field number management/sequential enforcement system on top of proto without ripping that part out, but your existing proto usage relies on that part and changing it would break existing clients because you’re removing field numbers, which is the whole fucking point of proto, and makes it difficult to roll out even if you did fix it yourself. So, representing union/enumerable types in proto is impossible. For proto enums to have forward compatibility, they have to handle adding new enum values over time, or need to remove and reserve old ones. So, proto enums end up being basically just field numbers. That’s exactly what you see in Golang enums and I don’t think it’s a coincidence: Google has no good way to serialize/deserialize/operate on enumerable enums or union types anywhere they use proto/grpc. Golang inherits this “enums” implementation from protobuf because it’s the context in which it was created.
- AnimalMuppet 9mo ago
- tensility 9mo agoOne of the few languages I've known that didn't provide any standard features for libraries (until the sixth major revision), Scheme, has been the worse for it.
- gen2brain 9mo agoError handling in Go is actually very nice. You do not have unhandled errors, not possible unless you really want to not handle the error. Now I even use it similar in Python, amazing how many errors I did not handle at all. But what got me into using Go is that there is no libc dependency, just system calls, static binary, that is just amazing. I can compile Go compiler in like few minutes. Rust I cannot even compile after 24h, I use rust-bin in Gentoo,luckily that exists.
- estebank 9mo ago> Rust I cannot even compile after 24h Could I ask what hardware this is on? Even when building LLVM from scratch too as part of building the toolchain (which hasn't been the default for a while now, but could see Gentoo doing so), it never took that long on any hardware I own. (Granted, I never tried on the EEE PC I've got on some drawer, and its 2G of RAM would likely kill the whole thing before it got started.)
- estebank 9mo agoOn a Lenovo T460 (mid-range laptop from 2016), with a fresh clone of https://github.com/rust-lang/rust/ https://github.com/rust-lang/rust/ and the default config: $ time ./x.py build ... snip ... Build completed successfully in 0:21:24 real 21m24.736s user 67m48.195s sys 1m54.906s Subsequent builds during development are faster (as 1. it doesn't build the same compiler multiple times, you can use the stage 1 build as normal, stage 2 is not strictly necessary and 2. if you modify one of the constituent crates of the compiler, the ones that are lower in the dep tree don't get recompiled). I've used this laptop on and off for rustc development for the last 10 years. Nowadays I spent more time using a cloud desktop that has much faster IO, but still use it during travels sometimes. From the sound of it, I suspect that your issue might be that you don't have enough RAM and your build is swapping a lot.
- gen2brain 9mo agoThis is an older thinkpad I am using, 4 cores, 16G of ram. LLVM is now dependency you cannot get rid of. That is painfull, but in the morning, after several hours it is usually done. Rust is LLVM plus I am not sure what, really painfull. And Gentoo also forces many different arches and flags for some reason, use flags are masked, you cannot easily disable them.
- rednafi 9mo agoAnother tired error-handling take. It ain't pretty but it works.
- jdefr89 9mo agoIt is pretty and it can do pretty much exactly what Rust enums do if they learned basic idiomatic Go.. Rust is a cult at this point honestly.
- deleted 9mo ago[deleted]
- travisgriggs 9mo agoAnother languages that just “gets” concurrent right (imo) is erlang/elixir. I’ve done elixir for the last 3 years off and on. Can someone with experience in both Go and Elixir compare the two? I’m sure I can have GPT whip up a comparison and see the syntax diffeeences, but I’m curious what the real experience “in the trench” is like.
- sethammons 9mo agoI've used both professionally. I think elixir has some amazing ideas. I love pattern matching. However! Just like all other interpreted languages, in elixir, I have to go to the call sites of the function that I am editing to understand what it is that is actually available and to understand what I can edit. I don't know what has been passed into my function. The lack of types is not fixed by having a type spec and dialyzer. Pattern matching helps. I wish Go had it. But when it comes to a growing organization, more and more of the codebase cannot fit in your head, and I find that teams and organizations are indeed faster in Go. I recall hearing that Jose was making progress on types. Not sure where that landed.
- travisgriggs 9mo agoI was curious in particular about the concurrency story between the two, but thanks for the higher level feedback.
- yomismoaqui 9mo agoAnother comment already mentioned that the OP don't understand how to work with errors in Go. As with any language, Go has its own philosophy and you have to first understand why it was created and what it brings to the table. To summarize it in one phrase "Less is more" I think this post should be a mandatory reading for everybody learning Go. If this resonates with you it's possible you're gonna like the language: https://commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html https://commandcenter.blogspot.com/2012/06/less-is-exponenti...
- jimbokun 9mo agoI believe I read this when it was first published but it still holds up very well today.
- jimmytucson 9mo agoNot shilling for Go here but there are a few misconceptions in this blog post. In addition to the others mentioned: > All of these examples involve assigning to a constant a value known at compile time but none of them will work Maps are not known at compile time. Hash functions are randomized based on a seed only known at execution time. The hashed value of "HELLO" is actually different each time the program runs. Even if the hash function weren't random, the runtime has to allocate buckets for map values on the heap, which involves calling the OS to get memory addresses for those buckets, etc. In Go, `const` means "the compiler can completely evaluate this expression and store the final bytes in the executable," which has the effect of making them non-reassignable, but protection from reassignment is not an actual feature of the language the way it is in Java and C++ (goes back to the maintainers wanting to keep it simple).
- j_w 9mo agoDoesn't protection from reassignment not exist in most languages anyways? In C++ you should be able to cast away the const. Realistically you probably can achieve this in any language with reflection. Unless a const is literally a compile time constant inserted through the program, it's likely able to be changed somehow in most languages.
- jimmytucson 9mo agoYou can definitely protect from reassignment in those languages (e.g. `final` in Java) but they don't completely prevent you from changing the underlying data. Rust would be one that comes to mind that has true immutability. I guess the Go maintainers just didn't want to go down that road, which I get.
- j_w 9mo agoSorry, I guess I read "protect from reassignment" as "protect the underlying data" then. I would argue that if you CAN change the underlying data, then the understanding of const by 99% of people is made incorrect. Therefore it's not really a good feature (in my opinion).
- irjoe 9mo agoI always felt like go channels were more of a clever solution than a good one. Goroutines are a pleasure to work with though.
- all2 9mo agoI'm curious what the alternative would be? Python's threads/sub-processing almost requires IO queues to function well, and are nearly the same semantically as channels... I'm not saying these are "good", just wondering what alternatives look like?
- hackingonempty 9mo agoOne alternative is STM, software transactional memory which is modular and composable. I think Haskell was first to implement it but its also in Clojure and some Scala libs. This is what ZIO's type safe version looks like https://zio.dev/reference/stm/ https://zio.dev/reference/stm/ Scala's for-comprehension is syntactic sugar for calls to flatMap, map, and withFilter, similar to Haskell's do-notation.
- benrazdev 9mo agoThanks for all of the comments! I want to clarify that I think very highly of Go as a language. I think it gets most things right. It's hard to introduce an abstraction into a language while still making sure that it's not abused. Rust's trait and type system, while powerful have been abused to create some absolutely incomprehensible and long types. Go, on the other hand, doesn't suffer from this issue. If I was too harsh against Go, that was certainly a mistake. I think that the criticisms of my section on error handling are, for the most part, spot on. My impression was that type erasure for errors was the idiomatic solution, which is patently untrue. When writing the blog post, I was unaware of the functions in the `errors` module as well as the syntactic sugar and general acceptance of downcasting errors. While I would still maintain that Rust errors are more convenient to work with, I must admit that there really isn't any good excuse for my ignorance on this. When it comes to enums, I stand by my statements on them. I still believe that it is useful to restrict the values a type might have. And no, I am not using the term enum to mean a rust-style "enum" (tagged union). I am talking about classical enums, more or less as they appear in C. As an aside, I am not terribly surprised that my website doesn't work well on some browsers. I hacked together the website including the HTML and CSS a couple of years ago and some of the hacks I used I ought to be ashamed of.
- amarant 9mo agoMan this post is a rollercoaster. First half of the post I was absolutely starstruck by how amazing go is(I haven't had time to play with it myself yet), and was making mental note after mental note to try it out asap! Then I got to the second half of the post, with the things he didn't like about go. No enums? Wtf? Not having sum types is a lesser evil imo, it places you in the mediocre, but mediocre is mostly ok so that's kinda fine. But no enums? We're stuck with magic numbers? Hell naw, we banished that demon in the nineties, I ain't signing up to bring it back!
- benrazdev 9mo ago>No enums? [...] We're stuck with magic numbers? In go you don't strictly need magic numbers because you can define constants: type Status int const ( IoProblem Status = iota // we start at zero and go down from there JsonParse ... ) The problem is that there is no exhaustiveness with these constant groups. The type Number is not a closed set of just IoProblem and JsonParse like an enum in C. It is just an int.
- jdefr89 9mo agoThey don't seem to understand Go much at all. Comparisons to Rust are somewhat misplaced but that's a different topic... Back to errors. Errors are interface values. They are simple yet powerful. You can create sentinel errors that can be wrapped or just passed to be checked then discarded. Go has all the functionality it needs to provide what ever it is Rust cult members believe makes Rust error handling so great. You can use the primitive constructs Go provides to do nearly the same damn things Rust can do and it won't look like a pile of hieroglyphs your local crackhead would draw. Best of all... Its simple and the syntax of Go (veering off topic) doesn't make me want to jump off a bridge. Stop gaslighting yourselves into thinking Rust syntax is reasonable and that its some perfectly proven language with all edge cases put to rest..
- osigurdson 9mo agoThe way I do this is decide which language I like (just by gut feel) and then come up with reasons why it is good / better than others. I think almost everyone does the same thing, really.
- jimbokun 9mo agoBut you can learn about yourself and others by writing down specifically the things you like and don’t like, and reading other people doing the same. With the possibility of liking different things for different reasons in the future. Or just better understanding how to best use the tools you like.
- osigurdson 9mo agoAlso, if you only really know one language well, don't let your brain tell you it is the best one without a bit more investigation.
- dacapoday 9mo agotoo young too simple, sometimes naive.
- benrazsuck123 9mo agoI hate u! U Suck!!!
- benrazsuck123 9mo agoU suck! I hate u!
- benrazsuck123 9mo agohi
- benrazsuck123 9mo agoxxx