Live data from Hacker News

Go subtleties

harrisoncramer.me

131–140 of 190 posts

Re: Go subtleties

#131

Go has certainly come a long ways from its initial mission to be a simple language for Rob Pike's simple coworkers. type User struct { Name string `json:"name"` Password string `json:"-"` Email string `json:"email"` } So you can specify how to serialize a struct in json using raw string literals containing arbitrary metadata. And json:"X" means to serialize it to X, except the special value "-" means "omit this one,"…

Annotations have been part of programming for ages. This is nothing new or out of the ordinary functionality.

Re: Go subtleties

#132
post #6
post #5

Great list of why one can love and hate Go. I really did enjoy writing it but you never get the sense that you can be truly certain your code is robust because of subtle behaviour around nil.

I guess as a corollary, Go really rewards writing the dumbest code possible. No advanced type shenanigans, no overuse of interfaces, no complex composition of types. Then you will end up with a very fast, resource light system that just runs forever.

> Go really rewards writing the dumbest code possible

Simplicity is hard. You may see it as dumb, other see it as priceless attribute of the language.

Re: Go subtleties

#133
post #53

> The wg.Go Function > Go 1.25 introduced a waitgroup.Go function that lets you add Go routines to a waitgroup more easily. It takes the place of using the go keyword, [...] 99% of the time, you don't want to use sync.WaitGroup, but rather errgroup.Group. This is basically sync.WaitGroup with error handling. It also has optional context/cancellation support. See https://pkg.go.dev/golang.org/x/sync/errgroup I know it…

Wow how did I not know of this?!

How does it cancel in-progress goroutines when the provided context is cancelled?

Re: Go subtleties

#134

Earlier quoted context omitted.

waitgroup's inadequacy is why I end up using structured concurrency like https://github.com/sourcegraph/conc

The last release of this was 2.5 years ago, and it's pre-1.0... is this really ready for production use? Genuinely asking, I'm relatively new to Golang and would love to have a better sense of what parts of the ecosystem are worth learning about.

I used it in production for lots of systems, so yes. It’s pretty great!

That said 2.5 years later there’s been many improvements to the stdlib (like waitGroup.Go) such that I no longer feel the need for it going forward.

Re: Go subtleties

#135
post #87

I had a “wtf” moment when using Go around panic() and recover() I was so surprised by the design choice to need to put recover in in deferred function calls. It’s crazy to smush together the error handling and normal execution code.

Semantics. Go at least does not restrict you to wrap every single panicky call.

func Foo() { try { maybePanic() } catch (err any) { doSomething(err) }

  .. more code
}

vs

func Foo() { defer func() { if err := recover(); err != nil { doSomething(err) } }()

  maybePanic()

  .. more code
}

Re: Go subtleties

#136
post #53

> The wg.Go Function > Go 1.25 introduced a waitgroup.Go function that lets you add Go routines to a waitgroup more easily. It takes the place of using the go keyword, [...] 99% of the time, you don't want to use sync.WaitGroup, but rather errgroup.Group. This is basically sync.WaitGroup with error handling. It also has optional context/cancellation support. See https://pkg.go.dev/golang.org/x/sync/errgroup I know it…

Wow how did I not know of this?! How does it cancel in-progress goroutines when the provided context is cancelled?

They have to all use the special context.

Re: Go subtleties

#137
post #5

Great list of why one can love and hate Go. I really did enjoy writing it but you never get the sense that you can be truly certain your code is robust because of subtle behaviour around nil.

As a Go learner, the best explanation that has made sense to me is that interface types essentially just compose two pointers: P1: The type and its method vtable P2: The value Once I understood that I could intuit how a nil Foo was not a nil Bar and not an untyped nil either

ah yes of course - key semantics of `nil` should totally depend on deep implementation details in my language's runtime.

willem-dafoe-head-tap.gif

Re: Go subtleties

#138
post #108

Earlier quoted context omitted.

If it is because of overflow, the idea was that there could be size classes at compile time. A bit like sub/supertyping but for numeric types. A simple type pointer check would be sufficient.

Size classes would save some space and speed up like-to-like comparisons, but wouldn't really do much for unlike comparisons (especially vs. float or complex). Looking only at type pointers fails to account for custom types (e.g., type Foo int); remember that an untyped integer constant can be compared with these. If you want the same semantics at runtime as you get at compile time, I don't see how you can get much s…

But the LHS can determine how it compares to the RHS when the RHS is determined to be an untyped constant? Or instead of saying RHS (my mistake), let's say the typed side since comparisons are symmetric. A bit like having a special method attached to the type strictly for comparisons? That would be much less expensive than such a type switch if I am not mistaken. Would handle custom types as well. If promotable from the underlying type, that would not even bloat the executable. Unless I'm confused...

Re: Go subtleties

#139
post #53

> The wg.Go Function > Go 1.25 introduced a waitgroup.Go function that lets you add Go routines to a waitgroup more easily. It takes the place of using the go keyword, [...] 99% of the time, you don't want to use sync.WaitGroup, but rather errgroup.Group. This is basically sync.WaitGroup with error handling. It also has optional context/cancellation support. See https://pkg.go.dev/golang.org/x/sync/errgroup I know it…

>golang.org/x/ is stuff that should be in the standard library but isn't, for some reason think of it as testing/staging before being merged into stable stdlib

Except that it's a little bit too convenient, and highly useful things like errgroup stay there instead of having been adopted into the stdlib.

Re: Go subtleties

#140
post #24

Earlier quoted context omitted.

I know it's not exclusive to Go or any language, but you can most certainly write incomprehensible code in it. If anything, expressiveness and proper abstractions can save you from this. I think people often get burnt by bad abstractions in expressive languages, but it's not a problem of the language, but the author's unfamiliarity with the tools at their disposal. If someone starts being clever with abstractions bef…

I like to say this: "Only my code is allowed to be clever" But, on a serious note, I agree with you. Go lacks a lot of power, especially in its type system, that causes a ton of problems (and downtime) that in other languages is trivial to prevent statically.

Formal proof languages are pretty neat, but nobody really uses them in the real world. Among the languages that people actually use on a normal basis, even those that claim to have extensive type systems, they still rely on testing for most everything, and once you're relying on testing anyway the type system isn't any kind of real saviour.

There is, perhaps, some segment of the developer community who believe that they are infallible and don't need to write tests, but then have the type system exclaim their preconceived notions are wrong, and then come to love the type system for steering them in a better direction, while still remaining oblivious to all the things the incomplete type system is unable to statically assert. But that's a rather bizarre place to be.

Post reply on HN