5 ms·
When I initially started Go, it felt so easy to pick up. Then I wrote a component in it and it felt overly verbose. Then I had to revisit the component and had
by noisy_boy 4y ago
When I initially started Go, it felt so easy to pick up. Then I wrote a component in it and it felt overly verbose. Then I had to revisit the component and had to do some heavy refactoring/additional testing and realized that the language, to certain extent, didn't stand in the way. After all these iterations, I think Go is leaving an-even-bigger-adoption on the table for the want of following:
1. Functional operators like map/filter/reduce - all of these would be optional but would save SO many lines of code.
2. Add simple conveniences - e.g. "contains" to check if a key is present in a map. Again those who don't want to use these, don't have to.
3. Error handling boilerplate - something to the tune of "?" operator in Rust
- herval 4y ago1 and 2 are now possible to implement, since 1.18 - I'm using this and it does save quite a bit of boilerplate: github.com/life4/genesis I'd love to see less verbose error handling too, but Rust's ? IMHO is not the best way to go - it adds quite a bit of magic and makes debugging difficult, when a question mark at the end of a line "injects" an unexpected return statement.
- leeoniya 4y agoalso https://github.com/samber/lo https://github.com/samber/lo
- svnpenn 4y ago2 has been possible since version 1.0 https://go.dev/doc/effective_go#maps https://go.dev/doc/effective_go#maps
- pjmlp 4y agoWhile it won't win the hearts of Gophers, I would use a utility function that panics if error, at least on throw away code.
- yakubin 4y agoThere are some instances of it in the stdlib, e.g. <https://pkg.go.dev/html/template@go1.18.4#Must https://pkg.go.dev/html/template@go1.18.4#Must> I'd guess with generics we can expect a generic "Must" to replace them.
- deleted 4y ago[deleted]
- na85 4y ago>When I initially started Go, it felt so easy to pick up. Same. It felt freeing to just say "fuck it, I'll use a struct" and have the built-ins required to automagically marshall json on the wire to structs in memory. That was pretty cool. You're spawning threads^H^H^H^H^H^H^Hgoroutines and passing messages and not giving a fuck because the language protects you. Then I wanted to make v2 of my package. Go's packaging (and module) system is just so indescribably, generally, and thoroughly bad that it put me off the language and I won't be back. I spent more time fucking around with dependencies and wondering why `go get` was giving me cryptic and unhelpful errors that were unaddressed by the docs than I did writing my code. Deleting go was the best move I've made.
- konart 4y ago>Add simple conveniences - e.g. "contains" to check if a key is present in a map. Why though? it doesn't even save you much space compared to standard use: if _, ok := m[key]; ok { } vs if contains(m, key) { } I'm not strictly against it, but it can open pandora's box of all kinds of weird sugar flavors.
- giveupitscrazy 4y agoI know zero go, despite having worked with it professionally for a short stint that I try and block out of my memory (not go's fault), anyway that first example looks like gibberish to me while the second is super clear.
- tptacek 4y agoIt is deeply idiomatic in the language.
- IshKebab 4y agoBut only because there's no `contains` function!
- ignoramous 4y agoIf perl has taught us anything... 3 ways to do something is worse than 1.
- peoplefromibiza 4y agowhat `contains` what? you could write this in Go if m[key] { } the comma ok idiom simply lets you distinguish a "zero" value from a missing value.
- ndr 4y agoAgreed that `key in m` or `m.contains(key)` would be clearer, but checking the value rather than the presence is asking for trouble.
- Cthulhu_ 4y ago> 1. Functional operators like map/filter/reduce - all of these would be optional but would save SO many lines of code. But at the cost of performance; Go is not (yet?) optimized for functional programming constructs, and its function syntax adds a LOT of mental overhead to reading the code; http://www.jerf.org/iri/post/2955 http://www.jerf.org/iri/post/2955 was a good post on that. Remember the Go proverb: clear is better than clever. In this case, not only for readability but also performance. I have no objections to your point #2 though, I always found Go's constructs like `len(slice)` or `slice = append(slice, value)` a bit awkward. With generics support, `slice.len()` and `slice.append(value)` should now be possible. Actually I'm not sure why the latter was not possible all along, I'm sure there's a reason somewhere. I know you can implement the latter yourself as well, even before generics. As for #3, I got nothing; I sorta followed along with a Big Discussion about different error handling in Go a few years ago, but it basically ended with "Well... actually how it is now is absolutely fine"; all the offered alternatives added complexity, magic behaviour, or reduced readability to the language. As it is, error handling is obvious. I wouldn't mind some syntactic sugar though; a one-line error handler at the moment is `if err := doSomething(); err != nil {` which is a bit awkward. The other Issue I have is with variable reuse and shadowing, it's a risk that may cause unhandled errors.
- HelloNurse 4y agoThe examples of what map, reduce etc. could look like in "Why Go Getting Generics Will Not Change Idiomatic Go" are very awful, but chiefly because they repeatedly state many types that in most programming languages would be deducted or unneeded. For example the line return Filter(string)(func(s string) bool { return len(s) <= 2 },... should contain no occurrence of 'bool' (it is implicit in the definition of a Filter) and at most one occurrence of 'string' (it is a filter over a string sequence if and only if the input of its defining predicate is a string). Is there any alternative technique for functional style in Go?
- cies 4y agoI dont know why the Go designers put in implicit null and left out proper sum-types and pattern matching. Where they actually trying to copy other's well-known-to-be mistakes?
- Cthulhu_ 4y agoI don't know about null, but wouldn't sum types and pattern matching make the language spefication and the toolchains a lot more complex? Their goal has always been to be simple and have longevity, but I think it's been at the cost of "safety", e.g. being able to just ignore errors, allowing nulls (although that's only for pointer types, value types have sane zero values and should be used as much as possible; some pointer types can handle null values as well), etc. That said, there are other languages with proper sum-types and pattern matching, if that's what you need; I think it's a bad thing that some people advocate for every language to have every feature from every other language. Take Javascript; someone Decided that it should have classes, but the implementation has never been good (e.g. field access levels) and it's always felt bolted on. Take Scala, which borrowed every feature from every other language ever, and now you can't have two people work on one Scala codebase without them having endless discussions about which flavor or pattern to use.
- cies 4y ago> I think it's a bad thing that some people advocate for every language to have every feature from every other language Not what I'm saying. I'm saying when smart people created Go, the forgot that null is a mistake, and sum-types are simply too useful in modelling the world to miss out on (pattern matching makes them a joy to use). This was both well understood in the 20XXies; and I have never seen any reason from the creators of Go as to why... > Scala Scala is a multi-paradigm lang; that sucks on whole different levels. I'm not advocating at all that Go should be multi-paradigm.
- bigbluedots 4y agoOne of the problems with simple things is that everyone wants more features, and then they stop being simple.
- parasense 4y agoI'd really love to see container constants. As of this writing only strings or numbers can be set constant. ``` const map[uint8]string { 0: "thing1", 1: "thing2", } ``` That way tables of data can be made immutable at compile. Folks are left to invent stupid hacks, that don't really work. For example, a function that defines a template and returns: ``` func my_data() map[uint8]string { return map[uint8]string { 0: "thing1", 1: "thing2", } } ``` And then we have folks running silly function calls for the sake of avoiding mutability. Don't get me wrong, I understand why this hasn't been done. We've all read the arguments against adding things to the language, but I accept in part, and reject in part that argument. Complexity always increases, so it's understandable to put the brake on run-away complexity. But GO is slightly pathological when it comes to the avoidance of adding sensible language features. The thing is most folks would rather have a slightly more complex compiler than a limiting programing language.