Live data from Hacker News

Go subtleties

harrisoncramer.me

61–70 of 190 posts

Re: Go subtleties

#61
post #57
post #9

Earlier quoted context omitted.

Yes, that'a bit too late after ten+ years perhaps but I wished we had a nil type and checking whether the interface is empty was a type assertion. In all other cases, like any(2) == 2, we compare the values. Then again that would mean that the nil identifier would be coerced into a typed nil and we would check for the nilness of what is inside an interface in any(somepointer) == nil. wrt the current behavior, it also…

> In all other cases, like any(2) == 2, we compare the values. But any(nil) == nil returns true like you'd expect. The reason that any((*int)(nil)) == nil is false is the same reason that any(uint(2)) == 2 is false: interfaces compare values and types .

that's another thing that makes it difficult to fix. Same thing here. 2 is an untyped constant so it should have returned true. (even if int is the default picked on short assignment)

any(uint(2)) == int(2) should return false indeed however.

Re: Go subtleties

#62
post #19

As somebody who only views Go from a distance, I see this list as a combination of „what‘s the big deal?“ and „please don‘t“.

I'm amused by posts like this because it shows that Go is finally slowly moving away from being an unergonomically simplistic language (its original USP?) to adopt features a modern language should have had all along. My experience developing in it always gave me the impression that the designers of the language looked at C and thought "all this is missing is garbage collection and then we'll have the perfect languag…

As a Go developer, I do think that I end up writing more code initially, not just because of the lack of syntactic sugar and "language magic", but because the community philosophy is to prefer a little bit of copying over premature abstraction.

I think the end result is code which is quite easy to understand and maintain, because it is quite plain stuff with a clear control flow at the end of the day. Go code is the most pleasant code to debug of all the languages I've worked with, and there is not a close second.

Given that I spend much more time in the maintenance phase, it's a trade-off I'm quite happy to make.

(This is of course all my experience; very IMO)

Re: Go subtleties

#63
post #43

Earlier quoted context omitted.

Oh that's probably doable. Introducing something like this is a bit orthogonal to the point above, but yes. It's not straightforward but probably something that will be considered at some point I reckon when thinking about making union interfaces first class. That will require to track a not nil typestate/predicate in the backend, something like that I guess.

Having pondered on a bit more.. I think it's the struct that would declare that it's not usable as nil, and that in turn would tell the runtime not to box it if it's nil. That would also help the compiler (and copilot etc) spot calls on nil pointers which will panic.

But that information disappears when you assign to an interface variable/container that is nillable. It requires an assertion to recover the info about the value inside the interface being not nil.

basically `if v.(nil){...}

creates two branches. In one we know v is not nil (outside the if block) and it can therefore be assigned to non nillable variables so to speak...

Re: Go subtleties

#64
post #41

Earlier quoted context omitted.

They are similar in the sense that there are very few abstractions, relying on the programmer to reimplement common patterns and avoid logical mistakes. You have to put thought into such things as: - Did I add explicit checks for all the errors my function calls might return? - Are all of my resources (e.g. file handles) cleaned up properly in all scenarios? Or did I forget a "defer file.Close()"? (A language like C+…

> Did I add explicit checks for all the errors my function calls might return? You can easily check this with a linter. > Are all of my resources (e.g. file handles) cleaned up properly in all scenarios? Or did I forget a "defer file.Close()"? (A language like C++ solved this problem with RAII in the 1980s) You can forget to use `with` in Python, I guess that's also C now too eh? > Does my Go channel spaghetti proper…

>Did I add explicit checks for all the errors my function calls might return?

You can check anything with a linter, but it's better when the language disallows you from making the mistake in the first place.

>You can forget to use `with` in Python, I guess that's also C now too eh?

When using `with` in Python you don't have to think about what exactly needs to be cleaned up, and it'll happen automatically when there is any kind of error. Consider `http.Get` in Go:

resp, err := http.Get(url)

if err == nil { resp.Body.Close() }

return err

Here you need to specifically remember to call `resp.Body.Close` and in which case to call it. Needlessly complicated.

>Then stop writing spaghetti and use a higher level abstraction like `x/sync/errgroup.Group`.

Why is this not part of the standard library? And why does it not implement basic functionality like collecting results?

Re: Go subtleties

#65
post #24

Earlier quoted context omitted.

And code with zero ability to do fancy trickery ("expressive" as some people like to say) is easy to read even if the codebase - or even the language - is unfamiliar. Which is really handy when shit's on fire and you need to find the error yesterday. You can just follow what happens instead of trying to figure out the cool tricks the original programmer put in with their super-expressive language. Yes, the bug is on…

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…

>it's not a problem of the language, but the author's unfamiliarity with the tools at their disposal.

If you have to share a codebase with a large group of people with varying skill levels, limiting their ability to screw up can definitely be a feature, which a language can have or lack.

As always, it comes with tradeoffs. Would you rather have the ability to use good, expressive abstractions or remove the group’s ability to write bad ones? It probably depends on your situation and goals.

Re: Go subtleties

#66
post #19

Earlier quoted context omitted.

I'm amused by posts like this because it shows that Go is finally slowly moving away from being an unergonomically simplistic language (its original USP?) to adopt features a modern language should have had all along. My experience developing in it always gave me the impression that the designers of the language looked at C and thought "all this is missing is garbage collection and then we'll have the perfect languag…

As a Go developer, I do think that I end up writing more code initially, not just because of the lack of syntactic sugar and "language magic", but because the community philosophy is to prefer a little bit of copying over premature abstraction. I think the end result is code which is quite easy to understand and maintain, because it is quite plain stuff with a clear control flow at the end of the day. Go code is the…

How much is premature in time? 10 years? 20, 30 years?

Re: Go subtleties

#67

Ah the old nil values boxed into non-nil interfaces. Even after 8 years writing go code almost every day this still bites me occasionally. I've never seen code that actually uses this. I understand why it is the way it is but I hate it.

Be prepared to be called a newbie for criticising typed nils.

My post https://news.ycombinator.com/item?id=44982491 got a lot of hate from people who defend Go by saying "so just don't do that!", and people trying to explain my own blog post to me.

Re: Go subtleties

#68

Earlier quoted context omitted.

As a Go developer, I do think that I end up writing more code initially, not just because of the lack of syntactic sugar and "language magic", but because the community philosophy is to prefer a little bit of copying over premature abstraction. I think the end result is code which is quite easy to understand and maintain, because it is quite plain stuff with a clear control flow at the end of the day. Go code is the…

How much is premature in time? 10 years? 20, 30 years?

So for me, the question is: are these two things intrinsically the same or coincidentally the same? If it is intrinsically the same, then an abstraction/centralization of logic is correct. If they are coincidentally the same, then its better to keep them separate.

Its premature if I don't know the answer to that question with my current information, which is a common scenario for me when I'm initially writing a new set of usecases.

If I get a 3rd copy of a thing, then its likely going to become an abstraction (and I'll probably have better understanding of the thing at the time to do that abstraction). If I don't get a 3rd copy of that thing, then its probably fine for the thing to be copied in 2 places, regardless of what the answer to my question is.

Re: Go subtleties

#69
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

Re: Go subtleties

#70
post #24

Earlier quoted context omitted.

And code with zero ability to do fancy trickery ("expressive" as some people like to say) is easy to read even if the codebase - or even the language - is unfamiliar. Which is really handy when shit's on fire and you need to find the error yesterday. You can just follow what happens instead of trying to figure out the cool tricks the original programmer put in with their super-expressive language. Yes, the bug is on…

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…

>most certainly write incomprehensible code in it

I've tried my best to make indecipherable go code and failed. Do you have any examples?

Post reply on HN