Live data from Hacker News

Interface Upgrades in Go

avtok.com

1–10 of 43 posts

Re: Interface Upgrades in Go

#2
The important thing is to make sure that your 'upgrade' is semantically indistinguishable from the non-upgraded version, and to the extent that it differs, document it. There's an old blog post[^1] where someone describes code that performed this kind of "interface upgrade" in a way that broke underlying assumptions about the code. This is a horrible (and unexpected!) kind of bug. One should be really, really sure that this is the correct way of solving a problem before actually reaching for this tool.

[^1]: In particular, a function which took a Reader would attempt to cast that Reader to something with a Close method, which broke the programmer's assumptions about that function. It didn't help that said behavior was at the time undocumentated: http://how-bazaar.blogspot.co.nz/2013/07/stunned-by-go.html and the HN discussion https://news.ycombinator.com/item?id=6060351

Re: Interface Upgrades in Go

#3
Has anyone quantified the runtime cost of doing interface upgrades? I have a vague memory that the vtable for a specific type/interface pair is constructed at runtime and then cached -- is this true?

Re: Interface Upgrades in Go

#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 because it's hilarious: http://www.forbes.com/sites/quora/2012/08/31/what-are-the-mo...

* 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. To write clean Java you really need to avoid much of the standard library (read Effective Java by Josh Bloch) and add a few important missing parts (use Guava).

Golang is really unique in that regard. You can learn Go by reading the standard library. It is beautiful, linear code. The library is pretty complete--eg you can write a one-line HTTP file server out of the box--but nothing feels extraneous. Lastly, I think it gets close to Knuth's ideal of Literate Programming. Paragraph-length comments thoughout the standard library explain what's happening, how, and why.

For example, the post talks about how io.Copy is awesome. For a concise English explanation, why not go directly to the source!

https://golang.org/src/pkg/io/io.go#L329

Re: Interface Upgrades in Go

#7
Go's interfaces are great, but one of my annoyances is that you can't define an interface with values (methods only). Which makes little sense considering it works just fine with getters and setters. i.e:

    type Blah interface { Var string }
wont work, but

    type Blah interface { GetVar() string } 
does. I'm sure theres a reason for this. Can someone shed some light?

Re: Interface Upgrades in Go

#8

Has anyone quantified the runtime cost of doing interface upgrades? I have a vague memory that the vtable for a specific type/interface pair is constructed at runtime and then cached -- is this true?

An interesting question. Using [1], which note can't be executed on the Playground but you can execute by copying and pasting into a file "upgrade_test.go" in a new directory and executing

    GOPATH=`pwd` go test -bench=.
I get:

    BenchmarkInterfaceUpgrade        24.9 ns/op
    BenchmarkDoNothingInterfaceCall   5.32 ns/op
    BenchmarkInterfaceUpgradeAndCall 29.4 ns/op
    BenchmarkInterfaceUpgradeFail    23.9 ns/op
For clarity, I've elided the "execution count" column which is not useful information for us here.

InterfaceUpgrade is testing the cost of having an interface-referenced value in hand and asking if it implements another interface. My belief based on the understanding of the runtime is that this is all a static check at runtime (i.e., taking the type of the value, looking that type's info up, and then reading from that type whether it implements a given interface, with all calculation done at compile time and only the lookup being done dynamically), and that while that number may go up a bit if there are more interfaces in play it shouldn't go up much.

DoNothingInterfaceCall is the time to call a function that does nothing and returns nothing through the interface. I tried adding a benchmark time for a do-nothing static call but Go inlines it away into nothing, making it a useless test of how fast the loop itself is running. 0.89 ns, FWIW.

InterfaceUpgradeAndCall combines the upgrade check and call into one pass. InterfaceUpgradeFail just checks to see if the fail case times very differently (no).

It's fairly easy to tweak these if you'd like to ask different questions. (Note some of the tests have a bit of spurious stuff at the end to make it so Go doesn't complain about unused values. Go really doesn't like to see unused values.)

Also, for those who may have spent some time benchmarking the more dynamic languages, I call your attention to the "ns" there. That's not milli- or microseconds, that's nanoseconds. (I once benchmarked something between Go and Erlang, and mistakingly though the Go was slower when it took 700 and Erlang was taking 70, but it turned out to be nanoseconds and microseconds respectively. FWIW, the code wasn't doing exactly the same thing, either, it was just some code I was benchmarking at the time, and it is expected that the Go code was doing less; point being, watch your units.)

http://play.golang.org/p/K1LedMxMPL

Re: Interface Upgrades in Go

#9
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…

One thing Golang did that was really smart was to have a very slick documentation generator run from unformatted comments, using just a convention for how to write the prose. You have an incentive to write good comments (they're how you document your library to its users), and the comments godoc demands you write also work naturally as comments qua comments.

A lot of Golang is like this: very simple, almost trivial-seeming decisions that potently improve the language in practice. It's a fundamentally simple weapon, it's forged from Damascus steel.

Re: Interface Upgrades in Go

#10

Go's interfaces are great, but one of my annoyances is that you can't define an interface with values (methods only). Which makes little sense considering it works just fine with getters and setters. i.e: type Blah interface { Var string } wont work, but type Blah interface { GetVar() string } does. I'm sure theres a reason for this. Can someone shed some light?

[deleted]
Post reply on HN