17 ms·
Why I Don't Like Golang (2016)
- Mathnerd314 4y ago2016. Generics have been added.
- deleted 4y ago[deleted]
- nemothekid 4y ago>There’s no ternary (?:) operator. Every C-like language has had this, and I miss it every day that I program in Go. The language is removing functional idioms right when everyone is agreeing that these are useful. And everyone agreed so hard that it was removed from almost every modern C replacement (Rust, Nim, Zig, Elixir, Kotlin).
- edflsafoiewq 4y agoAll those languages have if-expressions, which is all ?: is.
- kbd 4y agoTotally. In fact, if expressions are the very first example of “if” in the Zig manual https://ziglang.org/documentation/master/#if https://ziglang.org/documentation/master/#if Also, Zig is so into expressions over statements that they plan to remove “function definition as statement”, which I think is awesome. In other words, conceptually function definition is a compile-time expression that creates the function. Edit: here’s that Zig rfc: https://github.com/ziglang/zig/issues/1717# https://github.com/ziglang/zig/issues/1717#
- dragonwriter 4y agoRust has if/else (ternary) and match (N-ary) expressions, so it doesn't need a separate ternary operator. All of the other “C replacements” listed (which are a weird list for that description, especially Elixir, but whatever) have at least if/else-expressions, which, again, are ternaries.
- the_only_law 4y agoYeah if I can have decent pattern matching I can live without some other syntax sugars.
- ungamedplayer 4y agoHave you met my friend.. erlang ?
- the_only_law 4y agoIndeed, big fan, though it's rare I get to use it.
- V-2 4y agoTrue. In Kotlin you can go val foo = if (bar) "this" else "that" and you don't need two separate assignments.
- thegeekpirate 4y agoFor comparison, in Go it would be: foo := func() string { if bar { return "this" } return "that" }()
- Beltalowda 4y agoBit of an odd use of an anonymous function IMO. Normally I'd write that as: foo := "that" if bar { foo = "that" } Unless the assignment of "foo" is expensive, then you'd assign it in an else. If you really want to, you can do it in a single line too: foo := map[bool]string{true: "this", false: "that"}[bar]
- V-2 4y agoThese are rather nasty workarounds, to be honest. Instantiating a map out of the blue is clever, but not very readable (not to mention potential performance concerns eg. if it's code executing in a large loop), and something I'd definitely call out in code review. Note that computing "this" and "that" could by itself be costly, and one of these values is guaranteeed to get discarded.
- mikebenfield 4y ago> And everyone agreed so hard that it was removed from almost every modern C replacement They removed it because they made the regular "if" statement into an expression, so the separate "ternary" operator expression is superfluous. Rust et al made the "if" situation better than C; Go made it worse.
- Hasu 4y agoThis is entirely off topic, but how are Elixir or Kotlin "modern C replacements"? Elixir is built off of Erlang and has influences from Ruby and Clojure, and Kotlin is a replacement for Java. Rust, Nim, Zig, and Go are all fair game in that list, as far as I know being a C replacement is in the mission statement for the creation of all those languages.
- kaba0 4y agoI literally don’t understand why so many people believe Go is a C replacement. Like it is by all means in the first camp of managed languages with a huge runtime.
- yencabulator 4y agoReplacement for C in many areas it is used for != replacement for C in all areas it is used for
- kaba0 4y agoSure, as long as Node, C#, Java, Haskell are all C replacements as well. Which I am okay with claiming, as GC has no considerable overhead for most use cases, but go is not unique in any way or shape.
- yencabulator 4y agoGo is much closer to C than Node, Java, or Haskell. (I won't make claims about C#, I don't know it well enough -- but I doubt it's as similar to C as Go is.)
- bobbylarrybobby 4y agoTernary syntax was statement-oriented languages' compromise to get one bit of nontrivial expression syntax into the language. In Rust everything is already an expression, including if-else, so additional syntax isn't necessary.
- tobyhinloopen 4y agoElixir has the if-else being an expression. foo = if x, do: 1, else: 2
- deleted 4y ago[deleted]
- implying 4y agoThey've fixed the import / modules situation to a point where it's usable and much improved, and generics have been added. However, the issue this brings up about structs / types not explicitly declaring which interfaces they implement is a real and unaddressed problem, especially in large codebases. The only tool that I'm aware of that finds implementations is GoLand, at steep JetBrains prices. Figuring out what type an API is asking for should not require reading every line of code in the package, and slows down every developer of large Go projects
- saturn_vk 4y agoDoesn't the official language server have support for this?
- voidfunc 4y agoWhen developers who usually make 6 figures of money complain about $90/yr IDE price I just cannot help laugh. Actually it's even better... the price elevators down from $90 -> year2 90 - 20% -> year3 90 - 40%. Over three years that's like $150-$200 total and it will save you so many headaches. But that's a steep price? Are you kidding? Why do developers hate tools that cost money when they save them time and allow them to do more?
- xigoi 4y agoProfessional developers in the USA usually make 6 figures.
- sriram_malhar 4y agoMusicians and carpenters make far less than programmers, but they still buy their tools. Software people are too entitled. Even if you are not professional, you can still afford 54c a day ($200 a year). Even a programmer in India can.
- 5e92cb50239222b 4y agoMany junior developers in my city make around $300 a month. After spending $200 on rent and most of the rest on food, you're not left with much. I understand nobody really cares about crap-holes like mine when they're making most of their money in Western Europe and North America, so just throwing it out there.
- jjtheblunt 4y agoTitle needs 2016
- deleted 4y ago[deleted]
- xigoi 4y ago> if I name my source file i_love_linux.go, it won’t get compiled on my Mac What the fuck?
- tanduv 4y agoExplanation from a previous discussion - https://news.ycombinator.com/item?id=16414435 https://news.ycombinator.com/item?id=16414435 ...seriously wtf
- justanorherhack 4y agoIn 5 years of writing to code this has never prevented me from naming a file what I wanted to name it. I enforced conventions are nice, when I need to look at what’s different between platforms I can very quickly do so in any large repo.
- tandr 4y agoThere some file name conventions in place in Go [1]. Files ending in *_test.go are going to be run dufing `go test ` invocation, but not compiled during production build run. In general, last parts of file name reflect "tags", or a platform that this file should be built for. So, in the case of *_linux.go file will only be compiled when it targeted linux platform. Allows to have a file say file_windows_amd64.go and file_linux.go that have functions with same signature, but only one will be picked up for a target platform. Sort of like #ifdef , but at file-name level. There is a way to specify what file is actually targeting inside the file, through //go: "pragmas" too [1] https://stackoverflow.com/questions/25161774/what-are-conventions-for-filenames-in-go https://stackoverflow.com/questions/25161774/what-are-conven...
- quickthrower2 4y agoSearching around a few blogs mention _linux.go files are only compiled on Linux. But I see nothing in the official documentation, will at least in my quick searches. It will catch someone out who uses BSD as an acronym for something in their domain model (Bulk Sales Discount?) then xyz_bsd.go doesn't compile.
- benhoyt 4y agoMy thoughts on his points, from someone who really likes Go and has used it heavily on small and large projects (1M LoC): 1. Probably a matter of taste, but I love this feature, just because of the lack of noisy public/private keywords everywhere that you see in Java et al. It also means you can tell from a usage (not just the definition) that something is exported, which is often useful. As far as renaming goes, either rename the definition and see where the compiler complains, or get your IDE to do it (I use GoLand, but good things are said about gopls). As for his example, the idiomatic way to write that is either just call it `usr` or `adminUser`, or use `user := &user{}` which is valid (if a little confusing). 2. This is a feature: it allows you to define interfaces only where you need them (on the consumer side), and you define the interface with only the methods you actually need. This means that when you add a bunch of new methods on the implementation, you don't need to change all the consumers. Go interfaces are amazing. The downside he discusses almost never happens: it's surprising, but even in large projects I've never had structs accidentally implementing interfaces or a IsAdmin method being implemented with reversed polarity by accident. 3. Definitely has its downsides. Tooling helps find unchecked errors. Though I've found the biggest downside to explicit errors is the verbosity. You do get used to it, and the explicitness is at least clear. 4. There are a couple of "magical" things like this, but they're well known and documented, and simple to fix if you run into them. I love the fact I can just name a file foo_test.go and add TestFoo methods, and "go test" finds them automatically. 5. I have not found this to be the case, and in the rare cases it does happen, the compiler tells you loudly and it's easy to fix. 6. Yeah, this is a slight pain, but the semi-official "imports" package (golang.org/x/tools/imports) fixes it up, so you just run generated code through that (and it auto-formats the code as well). It's a couple of lines of code. See: https://github.com/benhoyt/prig/blob/2df1b65a2bdf34c10bb5e57ecc99d1775bc9d196/prig.go#L134 https://github.com/benhoyt/prig/blob/2df1b65a2bdf34c10bb5e57... 7. Yeah, I wouldn't mind a ternary operator. Easily misused, which is why they didn't add it, but it would be really nice used judiciously, rather than the 4-line if-else block. 8. Fixed by sort.Slice, which avoids the need for Len and Swap (and even more so by the new generics "slices" package, coming soon). I guess this was added after the article was written? 9. Fixed by "Go modules", which is really well designed and works well (though opinions differ). 10. Fixed with generics being added in Go 1.18. And generic helpers like "slices" and "maps" packages coming soon. 11. Yeah, slightly annoying for newbies, though as he mentioned, tooling tells you. I do like the control you (can) get over allocation and memory management with Go slices. As far as his summary goes (eg: the type system getting in your way for large programs), I have definitely not found that to be the case. The author doesn't like Go, and that's okay! I don't like Java. :-)
- weatherlite 4y agoAs a new Go user I seriously don't get the hype. It feels like C with some (not many) niceties thrown on top, that's not what we expect from high level languages. I am still waiting for the tada moment, hope it comes.
- throwawaylala1 4y agoWhat are you using it for?
- weatherlite 4y agoCrud APIs...
- justanorherhack 4y agoIMO it’ll be slower to write crud apis and there are some missing batteries you have to look for, it’s fairly verbose but I think some of that will change with generics and hopefully more pattern matching. On the flip side when you deploy it, it will like just work and run smoothly. Also very easy to add full integration tests as you can create a mock http server at runtime, paired with some db tools (go migrate) it’s very easy spin up a whole env and test it. It’s also very easy to get at lower level things like headers and cookies without it getting in the way. Also much of the web middleware is interchangeable or a few lines away from an adapter as there is a common interface in the std lib.
- weatherlite 4y agoOK thanks for this, the easily mock thing is indeed very nice to have. And maybe Generics will improve things. I don't get why there isn't a function to remove element from a slice (there's some append[:i],[i+1] trick instead) why wouldn't this be wrapped in a stdlib function? call it delete or something. I keep hearing good things about the stdlib - what am I missing? It's that do it yourself mentality I really don't like, and taking huge compromises on readability to preserve low language keyword count (like the lack of private keyword / capitalization the article discussed and the consequences) and then calling this whole setup "simple". There's nothing major but many many small things I think that make it a subpar experience. I don't care that much about performance and concurrency though which I think are Go's strong suits.
- LVB 4y ago>The tried and true approach of providing a compare method works great and has none of these drawbacks. Agreed! https://pkg.go.dev/sort#Slice https://pkg.go.dev/sort#Slice is wonderful. (Added a bit after this article was written, I think.)
- srer 4y agoLets see what the Go doc example looks like: sort.Slice(people, func(i, j int) bool { return people[i].Name < people[j].Name }) In Python one might write: people.sort(key=lambda person: person.name) Or in Rust: people.sort_by_key(|person| person.name); // sort_by is also an option... I think it's worth calling out exactly what is happening in the Go example: - We create a closure that captures the people slice - We pass the people slice and the closure to the Slice function - The Slice function mutates the people slice, and because the closure captured the slice it sees these mutations too I get why the Go team wrote sort.Slice like that, and it was perhaps the best they could have done with the language features...But I think we're going to have to agree to disagree on how wonderful it is compared to other languages ;).
- LVB 4y agoNo disagreement, having used Python a lot and finding it much nicer for this case. My compliments to Go on this were relative to the just how tedious the “implement this sort interface” method was that TFA was describing. sort.Slice is definitely still pretty rote (I think I write the same Less() function 90% of the time?), but it’s at least fewer characters of rote! I’m looking forward to generics improving this too. (e.g. https://github.com/golang/go/issues/47619#issuecomment-915428658 https://github.com/golang/go/issues/47619#issuecomment-91542...)
- IshKebab 4y agoGo's method is like that because it didn't have generics, but it does have the advantage of allowing you to sort more complicated things, e.g. indexes into other data structures, or computed values. Sorting by key is a special case (admittedly the most common special case).
- 4y ago
- x3n0ph3n3 4y agoI'm still baffled by their decision around date formatting. https://www.godateformat.com/ https://www.godateformat.com/
- Beltalowda 4y agoI find 15:04:05 on Monday Jan 2nd 2006 a lot easier to remember than all those strftime %-verbs. I certainly don't see how "%B %e, %Y" is any better than "January _2, 2006". %B for what? Bonth name? And %e for "d for day plus one so %e".
- erik_seaberg 4y ago1999-12-31T23:59:60 would make it easier to remember what the constants are.
- Beltalowda 4y agoThe way I remember it is that it counts from 1 to 7: 2006-01-02T15:04:05Z-0700 It's unfortunate that the year is 2006 and sandwiched between the minute and TZ offset, but this keeps the day at Monday (1st day of the week, for many anyway) so that's nice.
- thegeekpirate 4y agoI wrote https://golangti.me https://golangti.me because I never remember _any_ of the formatting types (besides Excel (which isn't as extensive)—d, dd, ddd, dddd, m, mm, mmm, mmmm, mmmmm...).
- philliphaydon 4y agoThis makes no sense to me. First time I’ve been confused about date formatting.
- ngalaiko 4y agoanother person who can’t get over his java stockholm syndrome in three (!) years one particular thing that tells that is the attitude to interfaces: while in java (and most languages) interfaces are used to tell which contracts a class implements, in go it’s reversed. you must declare interfaces to _require_ certain contracts, for arguments in your functions for example: type interface Operator { Operate(int, int) int } func IntOparation(a, b int, op Operator) int { return op.Operate(a, b) } this is a major difference highlighting the ownership boundaries: * when I write a package and rely on a 3rd party contract, instead of referencing it and adhering to it, I will copy-paste parts that I need to my package and be independent
- deleted 4y ago[deleted]
- yashap 4y agoAgreed with the article, though obviously it’s a bit dated (especially around generics and package management). My take is that Go is basically the new Java, with fewer abstractions and faster compilation. Although, the pre-Java 8 Java, before Java started to get a bit functional. Like Java it’s a practical, imperative, statically typed, garbage collected language with very good performance. Also like (pre-Java 8) Java, it’s very verbose, doesn’t allow for much “elegance”, and many find it not very fun to write. But it is a pretty decent language for getting shit done. Overall, I don’t really enjoying writing Go, but it’s not the worst either. I’d code in it if necessary, but wouldn’t chose it for a personal project. I just have more fun and am more productive writing code in concise, mixed OOP/FP languages like TypeScript or Scala, even if they don’t compile as fast.
- vippy 4y agoThe Scala ecosystem is super cool, once you're able to groc all of the neat stuff happening, sort the good tools from the bad, etc. Love http4s, scala-js, scalajs-react, doobie, cats, etc.
- digianarchist 4y agoSurprised you compare it to pre-Java 8 considering functions have first class support in go.
- yashap 4y agoFirst class functions are a lot less interesting without functional data structures, with methods like map, filter, reduce, etc. These were added in Java 8, but Go has always been against them. This may change with generics, people can certainly write their own now, but I’m on the fence about whether they’ll catch on. I think they still won’t be overly nice to use in Go because: - Go’s lambdas are extremely verbose. “Concise but clear” is a big part of what people live about functional data structures, Go won’t have the concise part - Go will still have almost no support for immutability, which works beautifully with functional data structures Code like this is nice to write: users.map((user) => user.id) While code like this isn’t: users.map(func (user User) string { return user.id })
- deleted 4y ago[deleted]
- crowdyriver 4y ago> Go doesn’t have exceptions. It uses multiple return values to return errors. It’s far too easy to forget to check errors... Yes, because it is easy and predictable to track exceptions in nested try catches and hidden control flow.
- deleted 4y ago[deleted]
- pvg 4y agoPreviously: 2019, 296 comments - https://news.ycombinator.com/item?id=20166806 https://news.ycombinator.com/item?id=20166806 2018, 148 comments - https://news.ycombinator.com/item?id=16414098 https://news.ycombinator.com/item?id=16414098 2016, 47 comments - https://news.ycombinator.com/item?id=12356823 https://news.ycombinator.com/item?id=12356823
- thefaust 4y agoWhy isn't Go good for large projects? Kubernetes is an example of a huge project built in Go
- ihateolives 4y agoThis is stock example. Anything else?
- thegeekpirate 4y agoExcluding any lines that aren't Go code, and from projects that I can recall off the top of my head: Kubernetes = 3.87 million, Go = 1.75 million, CockroachDB = 1.65 million, TiDB = 725k, Consul = 375k, Nomad = 375k, InfluxDB = 375k, Mattermost = 370k, Vault = 345k, rkt = 320k, Terraform = 275k, Grafana = 265k, Ethereum = 245k, Gitea = 225k, Dgraph = 205k, MinIO = 200k, Rclone = 200k, etcd = 185k, Hugo = 120k, Prometheus = 120k, Syncthing = 110k, Traefik = 110k, Juju = 105k, Perkeep = 100k.
- ihateolives 4y agoOk, fair enough. Love Syncthing, didn't know it was written in Go. Though I wonder why they wrote MacOS client in Objective-C instead?
- gorgoiler 4y agoI’d like to get into go but in the past I’ve always been burned by not being able to quickly refactor my code. If I want to change the contract of get_kittens so that it returns a set instead of a list, I found it quite tiresome to then go to all the call sites of get_kittens and change their types to match. What was I doing wrong?* Perhaps there’s a cleverer tool out there that can infer and implement these type changes for me, automatically? * using vim? [joke]
- taki_mekhalfa 4y agoThis is true for all typed languages though..
- Zababa 4y agoNo, type inference avoids this issue.
- yencabulator 4y agoWhich Go has. https://go.dev/ref/spec#Type_inference https://go.dev/ref/spec#Type_inference (Not to a level something like Typescript has it, but I'll argue that's a win. Typescript inferred typing can be hard to follow.)
- kstenerud 4y agoAlthough go has many deficiencies, this is not one of them. When you use "var" or "val", it works like "auto" does in C++.
- sudo_chmod777 4y agoI also use Vim. 1. Use `:=` whenever you can, so types are inferred by the assignments/allocations 2. Alternatively query all references from `gopls` and put the results into quick fix list, then `:cdo`
- ridof 4y agoI just leave this here: https://github.com/golang/go/issues/49383 https://github.com/golang/go/issues/49383 After such public disregard to the communnity and contributors as a whole, the talk about good or bad has no meaning until they learn the basics. For example how to work with community, and the fact that you have to provide your phone number in order to fix urgent bug or implement some feature is a plain stupid(or rather malicious). Just imagine you've spent your free time working on the fix or feature, and instead of getting appreciation or sometimes bounty or just nothing, you're being "charged" to contribute. Yeah, they really think it's normal that contributors have to give up PI to the advertisement company that were accused of violating privacy many times before. They basically treat contributors, tech-savvy users who provide free labor, like their usual consumers. Just think about it for a second, this is insane.
- deleted 4y ago[deleted]
- shantnutiwari 4y agoWhy does Go get so much hate here? Almost all front page articles are about how Go suCkS mAn I know Go isnt great or perfect, but still, why so much hate? I seriously want to know
- morelisp 4y agoFor many years Go has been displacing C/Python/PHP/Ruby/backend JS in situations where it's a clear win or at least the tradeoffs in tooling, speed, type systems, distribution etc. can be expressed in terms of agreed-upon technical priorities. Now there's a lot of Go code in the wild, projects people want to use or extend and programmers who will choose it by default, and it's starting to displace C#, Java, and C++ where the comparisons become a lot more preferential and vague. Do you want a faster GC or deterministic allocation? Nominal or structural interfaces? People fear change, especially in a field where change is only loosely correlated with improvement.
- mayormcheeseman 4y agoDo you think Go is really starting to displace C#, and Java though? I rule out C++ because I really think rust is the one aiming for that spot. But Go for C# and Java? Hard to say until we see Go start to take over more of the business domain applications within enterprise IMO.
- morelisp 4y agoI mean, for Kubernetes, Go literally displaced the prototype in Java. And the surrounding tools that are all now in Go, would likely have been in Java instead. You could say it's been successful in part because it's not Java and therefore Go "grew the market" instead of displacing anything, but I think that's pretty weak - some kind of DIY cluster management was coming, and the state of things is that Go snatched it from Java. I think Go is quietly taking over some business domain applications, reminiscent of Python ca. 2003 a lot of companies I see are using it for a few key components that benefit heavily from memory savings of value types and/or easier naive concurrency, but they're relatively quiet about it. There's also a small but significant cohort of junior devs today who learned to program by making games on fantasy consoles or homebrew hardware projects, want to keep working with those data-oriented patterns they learned C and C++, and Go supports that style a lot more idiomatically than Java. As much as I sometimes rant about "kids today", more of the current generation know the true value of a MB or a ms better than that of 10 years ago (Rust is helping a lot here, too).