Live data from Hacker News

Stunned by Go

how-bazaar.blogspot.co.nz

31–40 of 115 posts

Re: Stunned by Go

#31
post #5

Wow, this is pretty unfortunate. Also a very good example of why so many people maintain that Go is not nearly as statically typed as languages like Haskell or OCaml: casting (essentially subverting the type system) is very common, and limits most of the type system's advantages. In large part this is because Go's type system is not very expressive. I would just like to point out that OCaml did the same things as Go…

Thanks for the informative comment. > So it would automatically realize that the function called the close method, and infer the appropriate type. So, if i understand this correctly, OCaml would infer that the function takes "an object with write() and close() methods" because it uses both methods in its definition. That's reasonable. But wouldn't that prevent it from accepting objects that don't have a close() metho…

> (assuming, of course, that Go accepts Reader as a valid subtype of ReaderCloser (i would hope so!)).

Yes it does: http://play.golang.org/p/OnBotL9zfF

Re: Stunned by Go

#32
post #27

for those not familiar with Go, here's the problem translated in C terms: "I passed a pointer to your function and it called free() on it. how dare you!"

More "I passed a pointer to your function and it called free() on it, without documenting that it was taking ownership of the memory". Ownership contracts are an important part of the API of any function that does stuff with resources, whether memory, file descriptions, network connections, etc. If the API implies that it takes a pointer to a resource but will only read from or write to it, and then disposes of it, that's a bug.

Re: Stunned by Go

#33
post #21

Earlier quoted context omitted.

Yes, Roger Peppe, one of the Go contributors, had exactly the same issue, but luckily Brad and Russ, two core devs, were able to solve the mystery immediately and updated the documentation. It's now quite funny to read a blog post from someone completely different (Tim Penhey) who had encountered and solved the same issue with exactly the same usecase on the very same day, complaining about Go without even mentioning…

That is pretty funny, but it doesn't really change anything. It's unfortunate that it called Close() without at least giving proper notice, and most people will probably agree that in a perfect world where we could start over without breaking APIs, the implementation would be different.

Why can't this API be fixed, isn't that the whole point of the 'go fix' command?

Re: Stunned by Go

#34
post #2

This is pretty interesting, but I wonder if it's just a one-off problem with the http library. It'll be interesting to see if someone familiar with Go has a response to this, but from the blog post it doesn't appear that this contract is being habitually violated, only that it can be, which is still a problem in practice.

It's a bit insidious since even if that situation is rare, just knowing that it's possible introduces a new dimension of doubt next time things go awry with any code you didn't write. Enter a "Seriously, No Groping" type modifier ;)

Re: Stunned by Go

#35
I am just wondering whether you can write your own wrapper class that implements (exposes) the read method and doesn't expose a close method (or expose a close method that does nothing) and pass that in?

I am not suggesting this is a good solution, just curious.

Re: Stunned by Go

#36

Earlier quoted context omitted.

That is pretty funny, but it doesn't really change anything. It's unfortunate that it called Close() without at least giving proper notice, and most people will probably agree that in a perfect world where we could start over without breaking APIs, the implementation would be different.

Why can't this API be fixed, isn't that the whole point of the 'go fix' command?

http://golang.org/doc/go1compat.html

'go fix' was mainly used before Go 1, but it would be useful again for e.g. a Go 2.

Re: Stunned by Go

#37
post #12

This behavior is explicitly defined in the godoc for io. I don’t see why the author should be "stunned" by a function doing exactly what it says it does.

That'll be because it's only been in the docs since they reported their issue.

Re: Stunned by Go

#38

I am just wondering whether you can write your own wrapper class that implements (exposes) the read method and doesn't expose a close method (or expose a close method that does nothing) and pass that in? I am not suggesting this is a good solution, just curious.

Yes, easily:

    var rc io.ReadCloser // a file, whatever
    readerOnly := struct{io.Reader}{rc} // only a Reader

Re: Stunned by Go

#39
post #31

Earlier quoted context omitted.

Thanks for the informative comment. > So it would automatically realize that the function called the close method, and infer the appropriate type. So, if i understand this correctly, OCaml would infer that the function takes "an object with write() and close() methods" because it uses both methods in its definition. That's reasonable. But wouldn't that prevent it from accepting objects that don't have a close() metho…

> (assuming, of course, that Go accepts Reader as a valid subtype of ReaderCloser (i would hope so!)). Yes it does: http://play.golang.org/p/OnBotL9zfF

Thanks for the example.

Playing with the example a little bit left me with a nice feeling about Go's structural typing:

- Passing a ReaderCloser reference to a function that expects a Reader is possible: http://play.golang.org/p/PZCKvmp5Sj

- Composing interfaces, though very useful, is not required in order to make one a proper subtype of the other: http://play.golang.org/p/fXn0zzM60D

Re: Stunned by Go

#40
post #27

for those not familiar with Go, here's the problem translated in C terms: "I passed a pointer to your function and it called free() on it. how dare you!"

No, that's not what the problem is. Translated to C++, the problem is "you passed a pointer to A∗, you dynamic_cast'd it to a subtype B∗ without documenting that you did so".
Post reply on HN