
Why I like Golang's interfaces - theburningmonk
https://medium.com/@theburningmonk/why-i-like-gos-interfaces-2891adf2803c
======
realharo
I've been writing quite a bit of TypeScript recently (which works similar to
Go in this regard), and I must say I've become quite a fan of structural
typing.

Especially when you have features like union and intersection types (which Go
doesn't have), you can really mold the structure into whatever you need (i.e.
to fit whatever data model you're working with), and be very productive
without having to come up with weird inheritance hierarchies "just because".

It'd be nice to have the option to explicitly enforce nominal typing in
specific places (maybe with its own keyword), but for most cases, structural
typing seems good enough so far.

~~~
infogulch
I admit the syntax is less than ideal (especially with gofmt), but I believe
adding two interfaces to an interface definition is equivalent to union:

    
    
        func myrw(rw interface { io.Reader; io.Writer }) {
            rw.Read(nil)
            rw.Write(nil)
        }
    

[https://play.golang.org/p/D-lJ1pL3MZ](https://play.golang.org/p/D-lJ1pL3MZ)

~~~
hiker
Not really, it's equivalent to a product type.

------
Drup
Since the author likes both F# and structural typing, he might be interested
in OCaml. F# took a lot of stuff from OCaml, but avoided both the object
system and most of the module system, which both feature different flavor of
structural typing.

In both case, as opposed to Go interfaces, they are actually safe (downcasting
is forbidden, upcasting is checked at compile time) and the OCaml language has
very good type inference, type annotations are not needed.

------
micah_chatt
The thing that tripped me up was you can't pass lists of interfaces across
function boundaries. It's confusing when you're starting out

~~~
zellyn
Could you post an example of what you're talking about? Passing slices of
interface values works just fine.
[https://play.golang.org/p/9CWzdnRb8U](https://play.golang.org/p/9CWzdnRb8U)

Is this what you mean? Trying to pass a []fooint as a []Fooer doesn't work:
[https://play.golang.org/p/dmFfr0Exnk](https://play.golang.org/p/dmFfr0Exnk)
\- that doesn't work in many languages, which is sad, but is for reasons that
make sense if I think about what it would actually be doing under the covers:
an interface value needs to store type information and/or a pointer to some
kind of function pointer table, so you'd have to recreate that for each list
element if you change the type of the list.

~~~
adonovan
Also, a []Fooer supports the operation of storing any element assignable to
Fooer, whereas a slice []fooint does not support that operation, so it makes
sense that a []fooint cannot be used anywhere a []Fooer can.

~~~
zellyn
That is a nice way of putting it.

------
eximius
Have any go developers run into issues where an interface is satisfied where
it shouldn't be due to name conflicts?

~~~
ryancouto
what do you mean?

~~~
zellyn
I think they mean accidentally satisfied interfaces.

~~~
ryancouto
i was hoping they'd have an example to point to, can't imagine this being a
huge problem but i'd be happy to be proven wrong.

