Live data from Hacker News

Eight years of Go

blog.golang.org

101–110 of 291 posts

Re: Eight years of Go

#101
post #35

Earlier quoted context omitted.

Are the complaints about lack of generics really a minority thing? Writing separate functions to sort different types just strikes me as ridiculous. EDIT: My original tone was a bit nasty in retrospect. Did a little research and while I still am on the generics side, the current situation seems at least workable for a good number of use cases.

My concern is less about writing a bunch of separate functions, but rather the way this hampers the abstractions that are available to you everywhere in the language. You don't have map or fold! And that's only the very tip of the iceberg.

Yeah, I wish go had more functional stuff, like .map(), .filter(), etc.

On the other hand I enjoy that when I pickup a package someone wrote there is not a bunch of different meta-programming using templates.

Generics sometimes lead people (including myself) to over-engineer solutions... usually because we want as much compile safety as possible. But at what cost in complexity.

Re: Eight years of Go

#102
post #70
post #25

Earlier quoted context omitted.

I'm not sure why the next thing you'd consider is bind. It seems like plenty of languages with ADTs and generics still either don't have it available in their libraries, or use it extremely lightly, in spite of being able to implement it.

I'm referring specifically to the error-handling situation. If you replace the two-value assignment with an `Either`, it feels very natural to also eschew the constant `if (err != nil) return err` lines, and adopt a continuation-passing style, the way you do with Futures in JavaScript. You could even consider some syntactic sugar around it, like the `?` operator of C# and Kotlin, or a full-on Haskell-like do-notation…

Again, it doesn't seem like this is something that many communities do, in spite of having languages that support it. The '?' operators in the languages you cited, as far as I recall, are specific to null, and don't work on generic option types.

Re: Eight years of Go

#103
post #22

Earlier quoted context omitted.

But you don't need to do that. It's a bit clunkier than generics, but it's usable: https://golang.org/pkg/sort/

You're still writing separate functions (implementations of sort.Interface) to sort different types.

But this is something you often need to do for any non-trivial type, even with generics. There's a reason that C++ std::sort takes a comparator, or why Rust requires you to implement the 'Ord' interface.

Again, it's a little clunkier in Go, but not unusably so.

Re: Eight years of Go

#104
post #2

Things I love about go: 1. Probably the best ecosystem out there. 2. Go routines 3. (Enabled by (2) actually) `defer` 4. That I can add interfaces implementations to structs I don’t own 5. No exceptions. Actually (5) is one of the few things I don’t like about Haskell. If Go had ADTs and generics it would easily be my favorite language. Edit: and of course the channels. Edit2: yeah, i have no idea why i connected (2)…

What's the connection between `defer` and goroutines?

Yeah, none. I wrote this while still in bed. No idea what I was thinking at the time :D

Re: Eight years of Go

#105
post #96

Earlier quoted context omitted.

It would be nice to add at least the options to explicitly state that type X should implement interface I, and have the compiler barf / emit an error if X does not implement Y. Like I said before, this has not been enough of a problem to really bother me, but I would be quite happy if Go fixed this.

can't you simply do this (from [1]) somewhere in your code to enforce? type T struct{} var _ I = T{} // Verify that T implements I. var _ I = (*T)(nil) // Verify that *T implements I. [1] https://golang.org/doc/faq#guarantee_satisfies_interface

Yes you could, but then you'd have to have both the declaration and the implementation of the interface in the same package. That would mean that if either of them is in a separate file, you'd have to import it. That in return, could easily call hellish compiler errors due to circular dependencies. In Go any circular dependency is an immediate compile error.

Looking at the link, the second advice is that you could require users to implement special functions such as ImplementsFooer() to explicitly declare which interface they're implementing. This could help, but this practice is not present in the codebases I've seen including the Go standard library (to the best of my knowledge).

Re: Eight years of Go

#106

Earlier quoted context omitted.

can't you simply do this (from [1]) somewhere in your code to enforce? type T struct{} var _ I = T{} // Verify that T implements I. var _ I = (*T)(nil) // Verify that *T implements I. [1] https://golang.org/doc/faq#guarantee_satisfies_interface

Yes you could, but then you'd have to have both the declaration and the implementation of the interface in the same package. That would mean that if either of them is in a separate file, you'd have to import it. That in return, could easily call hellish compiler errors due to circular dependencies. In Go any circular dependency is an immediate compile error. Looking at the link, the second advice is that you could re…

A possible solution is to have a separate (otherwise unused) package in your codebase with just a test in it:

  //compile_test.go
  func TestThatThisModuleCompiles(t* testing.T) {}

  //list of "type implements interface" tests
  var _ mymodule.MyInterface = myothermodule.MyStruct{}
  ...
Then you just ensure that `go test` is run, e.g. by the CI.

Re: Eight years of Go

#107
post #22

Earlier quoted context omitted.

But you don't need to do that. It's a bit clunkier than generics, but it's usable: https://golang.org/pkg/sort/

You're still writing separate functions (implementations of sort.Interface) to sort different types.

For sorting slices you only have to pass one function:

  sort.Slice(s, func(i, j int) bool { return s[i].X 

Re: Eight years of Go

#108
post #62

Go's biggest issues still seems to be the lack of a standard mature dependency management system.

this is being addressed in dep, it's obviously not fully ready yet but works pretty well in my experience https://github.com/golang/dep

Which is why I added the 'mature' qualifier.

Re: Eight years of Go

#109
post #10

Earlier quoted context omitted.

Some of those things are true and annoying, while others are exaggerations, and the rest are just wrong. That thread is poor taste.

Yeah, they are (and the author admits as much) but I found > Fact #38: go is supposedly a garbage collected language, but it has not once deleted itself nor any of my code. pretty hilarious.

Yeah actually that's really funny.

Re: Eight years of Go

#110
Go is woefully missing some really key features, which you encounter when tuning it for high performance. My list of grievances:

- Dep handling was never considered. Makes sense given Google's monorepo but thats not how the world works.

- Stdlib just loosely wraps posix features with many C flags copied verbatim. These APIs are old and could use a refresh but Go never bothered.

- No easy way to construct arenas/pools. Once you go down this route you have a great headache of releasing in the right places. The GC doesn't cut it, you need pools sometimes

- Debugging basically doesn't work on some OSes. No easy way to attach gdb and see what's happening. Doubly so if you use Cgo

- Similarly, Go doesnt bother to hide the differences of different OSes. Up to you as the programmer. Again not surprising for Google's all Linux world. If everything is Linux then OS difference doesnt matter. But even Python does a better job here.

- Logging is poorly thought out as evidenced by multitude of third-party log packages. Anemic compiler means you can't get verbose logging without paying a performance penalty.

- No RAII. Defers are a lazy attempt at this, but they're not even close to being as good as RAII. This is probably the biggest point where you realize Go can't dethrone C++

- Tricky Close() semantics force you to architect entire program around who will close() things at end of their lifetime. Lots of terrible hacks ensue when people build something that works but realize close ownership is ambiguous and rightfully don't want to rebuild it all

- Channels don't have a good way to deal with errors. You're forced to come up with an ad hoc solution to deal with your graph of goroutines/channels when one node errors

- No supervision tree. Erlang existed far before Go but they didn't learn from this key feature. But it would greatly enhance Go to have it

- Hacky reflection semantics that cause subtle runtime bugs when a JSON struct field's name starts with a lowercase letter. And of course, there are no generics, the larger issue here.

I was hopeful that Go would fix some of these things before it went 1.0 and locked in its syntax. Sadly that didn't happen as it was likely already locked in at Google. Go is ultimately kind of brain dead, useful for some very particular features but not so compelling that it can replace any other language.

Post reply on HN