Live data from Hacker News

Interface Upgrades in Go

avtok.com

21–30 of 43 posts

Re: Interface Upgrades in Go

#21
post #14

Earlier quoted context omitted.

The purpose of the interface is to abstract how something is done. In your example, GetVar() can be implemented in a number of ways. Returning Var field of Blah struct is only one such way (and if there was only one implementation, there would be no need for an interface). In that light, adding variables as part of interface doesn't make sense. Variables are fixing the thing that interface is meant to make flexible.…

It seemed to me that interfaces have a second function of providing partial uniformity across types (not just abstracting procedures). I.e the Animal interface has a method `Speak() string` and you have a function that takes an Animal that prints something like "Animal type {species} says {speak}" you would have to define a getter on the Animal's species even though its not a really a procedure. But I see what you me…

If you have a function that requires both the species and a speak message from an animal, it would make sense for the interface to have a function that returns both the species and speak strings. I think that this [0] does what you would want.

If you want to guarantee that two structs contain a set of the same required fields, I believe the best practice would be to include an anonymous field for a struct with the fields across both. [1]

[0] http://play.golang.org/p/0zMqPUicgq [1] http://play.golang.org/p/cM3XPfitxH

Re: Interface Upgrades in Go

#22

I'm wondering what programmers in functional programmers do about this sort of thing? It seems like they have much stronger type constrants; subclassing and upcasting just plain don't work. And if they did work, it would invalidate the sort of proofs that functional programmers like to do.

Treating "upgrades" as a specific case of reflection, typically what happens is that the function that wants to do reflection declares that it wants to perform reflection on its arguments via the type system. For example, in Haskell this mechanism is called "typeable" and in Rust this is called "any".

The nice thing about this approach is that it signals to callers that reflection is going to happen, so callers can be ready for it—the types become a form of documentation. If reflection is unrestricted it's easy for callers to get surprised when methods are called that they didn't expect. (Go has had breakage during point release upgrades from this, for example.)

This stricter approach requires that you plan ahead for "upgrading" in advance since you can't change a non-upgradeable argument to an upgradeable one without changing the type signature and breaking your callers. On the other hand, your callers are secure in the knowledge that you won't do that: they know that if you didn't give them access to one of your type's methods they can't sneak around and get access to it through the "back door". Non-upgradeable interfaces can also be more efficient since there is no need to store the reflection metadata at runtime; with this approach you only pay for what you use. Altogether it's a classic static-versus-dynamic-typing tradeoff.

Re: Interface Upgrades in Go

#23
post #18

Earlier quoted context omitted.

For all the comments Go gets on its typesystem, I suppose if rt, ok := dst.(ReaderFrom); ok { return rt.ReadFrom(src) } Isn't the most terrible way anyone has seen pattern matching implemented. At least it is better than Java's instanceof + cast.

For even more similar look to pattern matching look at Go's type switch. switch i.(type) { case OptionalInterface1: // do some extra thing we allow case OptionalInterface2: // do some other extra thing we allow } It's really good when you have a set of mutually exclusive interfaces or types.

You should use switch v := i.(type) so you can access v as the type in a case.

Re: Interface Upgrades in Go

#24
post #6

The zero-copy IO in Go is so elegant. I think you can really judge a language accurately by checking out its standard library. This is one of my favorite things about Go. By comparison, * The C++ STL. Fast and useful, but the implementation is nearly unreadable due to template soup. Here's one of the simpler parts! https://www.sgi.com/tech/stl/stl_vector.h * PHP. So bad it's basically a strawman. I'll include it beca…

For all the comments Go gets on its typesystem, I suppose if rt, ok := dst.(ReaderFrom); ok { return rt.ReadFrom(src) } Isn't the most terrible way anyone has seen pattern matching implemented. At least it is better than Java's instanceof + cast.

At least it is better than Java's instanceof + cast.

Except that in a language with generics you have to cast far less, so it is no surprise that Java is less optimized for type casting.

(The primary exception being the equals(Object) method, which most classes should have.)

Re: Interface Upgrades in Go

#25
post #6

The zero-copy IO in Go is so elegant. I think you can really judge a language accurately by checking out its standard library. This is one of my favorite things about Go. By comparison, * The C++ STL. Fast and useful, but the implementation is nearly unreadable due to template soup. Here's one of the simpler parts! https://www.sgi.com/tech/stl/stl_vector.h * PHP. So bad it's basically a strawman. I'll include it beca…

> Java. A bit better. Compare the readability of OpenJDK's ArrayList.java to the STL vector.h, which does essentially the same thing: http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/00cd9dc3c2b5/s.... But of course the Java standard library is immense and has a lot of cruft in it.

Really? Java's success is - rightly - attributed to its simple and usable libraries.

> To write clean Java you really need to avoid much of the standard library (read Effective Java by Josh Bloch)

Lol, the standard ArrayList.java is written by ... Josh Bloch!

Re: Interface Upgrades in Go

#26

The author of that article is also the author of the Goji framework (very nice web framework for Golang): https://goji.io/

I was looking for the example proxy around http.ResponseWriter the author talked about which is implemented in Goji, I believe it's this code: https://github.com/zenazn/goji/blob/master/graceful/middlewa...

I understand it fine except this bit right at the end:

    var _ http.CloseNotifier = &fancyWriter{}
    var _ http.Flusher = &fancyWriter{}
    var _ http.Hijacker = &fancyWriter{}
    var _ io.ReaderFrom = &fancyWriter{}
What's the purpose of this ? According to effective go this just silences the unused imports but I don't think there's a need for that here.

Re: Interface Upgrades in Go

#27
post #6

The zero-copy IO in Go is so elegant. I think you can really judge a language accurately by checking out its standard library. This is one of my favorite things about Go. By comparison, * The C++ STL. Fast and useful, but the implementation is nearly unreadable due to template soup. Here's one of the simpler parts! https://www.sgi.com/tech/stl/stl_vector.h * PHP. So bad it's basically a strawman. I'll include it beca…

For all the comments Go gets on its typesystem, I suppose if rt, ok := dst.(ReaderFrom); ok { return rt.ReadFrom(src) } Isn't the most terrible way anyone has seen pattern matching implemented. At least it is better than Java's instanceof + cast.

There are other ways in Java

http://benjiweber.co.uk/blog/2014/05/03/pattern-matching-in-...

http://benjiweber.co.uk/blog/2014/08/26/deep-pattern-matchin...

Re: Interface Upgrades in Go

#28
post #26

The author of that article is also the author of the Goji framework (very nice web framework for Golang): https://goji.io/

I was looking for the example proxy around http.ResponseWriter the author talked about which is implemented in Goji, I believe it's this code: https://github.com/zenazn/goji/blob/master/graceful/middlewa... I understand it fine except this bit right at the end: var _ http.CloseNotifier = &fancyWriter{} var _ http.Flusher = &fancyWriter{} var _ http.Hijacker = &fancyWriter{} var _ io.ReaderFrom = &fancyWriter{} What's…

They are static assertions that fancyWriter implements all those interfaces. They are compiled away to nothing but provide a kind of test of correctness.

Re: Interface Upgrades in Go

#29
post #28
post #26

Earlier quoted context omitted.

I was looking for the example proxy around http.ResponseWriter the author talked about which is implemented in Goji, I believe it's this code: https://github.com/zenazn/goji/blob/master/graceful/middlewa... I understand it fine except this bit right at the end: var _ http.CloseNotifier = &fancyWriter{} var _ http.Flusher = &fancyWriter{} var _ http.Hijacker = &fancyWriter{} var _ io.ReaderFrom = &fancyWriter{} What's…

They are static assertions that fancyWriter implements all those interfaces. They are compiled away to nothing but provide a kind of test of correctness.

Oh, ok, makes sense. Thank you.

Re: Interface Upgrades in Go

#30
post #26

The author of that article is also the author of the Goji framework (very nice web framework for Golang): https://goji.io/

I was looking for the example proxy around http.ResponseWriter the author talked about which is implemented in Goji, I believe it's this code: https://github.com/zenazn/goji/blob/master/graceful/middlewa... I understand it fine except this bit right at the end: var _ http.CloseNotifier = &fancyWriter{} var _ http.Flusher = &fancyWriter{} var _ http.Hijacker = &fancyWriter{} var _ io.ReaderFrom = &fancyWriter{} What's…

The relevant part of Effective Go is here: http://golang.org/doc/effective_go.html#blank_implements

It allows you to make sure fancyWriter implements all those interfaces, so that any future refactoring that breaks compatibility breaks at compile time.

You know how Go makes interfaces concordance implicit ? Whatever has a Read() method is a io.Reader without asking for it ? This explicitly tells the compiler (and other developers) the same thing.

Post reply on HN