Hacker News new | ask | show | jobs
How to use interfaces in Go (2012) (jordanorelli.com)
49 points by abeinstein 3845 days ago
8 comments

When navigating unfamiliar Go codebases, it's hard to know which types fulfill an interface. Say you have a function that takes an Animal; how do you figure out what to call it with?

Or to give a concrete example, say you want to do formatted output to stderr. How is one supposed to determine that os.Stderr is something that can be passed to fmt.Fprintf? Is there a better way than manually comparing method signatures?

A pattern that helps with this (tangentially) is to explicitly declare methods to implement an interface at type declaration time:

    type File struct {
        ...
    }
    
    var _ io.Writer = (*File)(nil)
It's not a panacea, but it helps. If you write all your own code this way, at least it will be easy to see which interfaces your own types implement, and (with a grep or GoRef) vice versa.

Plus you get interface implementation checking, so your error messages actually make sense if the interface or type method signatures unexpectedly change.

Again, this is not a real solution to your problem, but it has enough advantages to be worth mentioning.

Use the Go oracle with an "implements" query.
Hey, that's pretty cool. I was able to get it to work, though it is very awkward to use directly (it's designed to be integrated into text editors).
Yes, I use it via vim-go.

You can also use it from a local godoc instance: https://golang.org/lib/godoc/analysis/help.html

And there's Pythia: https://github.com/fzipp/pythia

So beside familiarizing the language syntax, I need to be aware of a set of unofficial tools and plugins, which are likely going to change in the next couple months, to be able to read the code.
It's an official tool. Also, most interfaces are very small (one to two methods) so it's pretty easy to figure out. I read/write a decent amount of Go every day and it's not often that I'm asking myself "what implements this interface?".
"go oracle" is right there with "go build" etc, an official tool that shouldn't change any more than the other tools that's part of the Go distribution.
> type JavaProgrammer struct { > }

> func (j JavaProgrammer) Speak() string { > return "Design patterns!" > }

shrug At least our language designers trusted our intelligence enough to implement generics.

> shrug At least our language designers trusted our intelligence enough to implement generics.

Trusted you so much that they even tripped on co/contravariance to add to the challenge :p

Read this when I was first getting into Go; super helpful and a fun(ish) read for people curious about the language
Interesting. For pointers and interfaces, in this sample http://play.golang.org/p/Lf8nn_pcYO, `h3.Add2()` should fail as per OP said. I am sure, I am missing something important here. Please help.
It shouldn't. The method you're calling takes a pointer receiver, and the Go Spec[1] says:

>A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for(&x).m()

In other words, if a type T no method M, it will look for M in *T's methods.

[1] https://golang.org/ref/spec#Calls

The article is a pretty good intro to how to use interfaces. I think some people, especially those not familiar with the language would benefit from reading such articles and learning how to write idiomatic Go code, rather than ask for features that would allow them to write idiomatic $LANGUAGE_THEY_LIKE code.
Previously on HN:

https://news.ycombinator.com/item?id=9320235

The blog post is from 2012.

> func main() {

> animals := []Animal{Dog{}, Cat{}, Llama{}, JavaProgrammer{}}

> for _, animal := range animals {

> fmt.Println(animal.Speak())

> }

> }

This makes my eyes hurt. In this modern age we still haven't learned to create easy to read languages?

Not sure I understand - what part of this is not easy to read? It's quite familiar to read and make sense to any programmer who's had experience with any of the C-like languages.
Is this sarcasm? That code snippet doesn't look like any C-like language that I'm familiar with.
I think the syntax is terse mostly for the sake of example.

There's a lot going on in about 3 lines.

I don't think "terse" quite describes it. Python can be terse, as you can say:

    n = sum(x for x in my_sequence if x % 2 == 0)
But the Go code listed above is not just plagued with a lot going on in "3 lines". I think there's something to be said about gratuitous operators, and a sort of beauty to letting the parser do more work than the programmer themselves. I don't use Go at all, but from the example above I can tell it is a horribly grotesque language considering when it was created. Sure, even C or C++ have curly braces and array specifiers for types; however, at least these have the excuse of age and compatibility to work with. Go is relatively new, and I think that welder was getting at is that syntax shouldn't be some overly complex thing in this day and age. Nim and Elixir come to mind as two (newer) languages that avoid many syntax warts without making significant trade-offs because of it.
> I don't use Go at all, but from the example above I can tell it is a horribly grotesque language...

If you don't us Go at all then you can't tell anything from a single 3 line example. It's like judging an entire Linux distro based solely on a couple of screenshots.

What the he'll is going wrong with HN lately that I can't open a programming thread without superficial criticisms from someone who's never actually coded in that particular language, and troll posts about how Java / whatever is better / already supports feature x.....

People complain about the zealous attitudes of language fanboys, but honestly I think the dogmatic negativity on HN is becoming a far greater issue.

</rant>

Everyone's a PL expert.
And Python itself is pretty verbose compared to modern languages:

    mySequence.filter { it % 2 == 0 }.sum()
This is a very contrived example to illustrate what an interface is in Go. You will almost likely never see code written like that in a good project.
On top of that, the code above ignores errors, something that Go makes all too easy by not supporting exceptions.
This is an extremely contrived critique.

The only place an error could occur in this code is if fmt.Println returns an error. What should happen if you can't display the output? Try to print an error? This is entirely appropriate for demo code and use of stdout like this. No one honors the return value from printf(3) in demo code either. Considering other languages, Python's print functionality doesn't have anything about returning or raising errors, and it wasn't even available as a function until 2.6.

I don't understand why you would share a three year old post explaining the basics of interfaces in Go.