
Golang Object Oriented Design - JanLaussmann
http://nathany.com/good/
======
fauigerzigerk
I keep wondering if Go couldn't have gone further in getting rid of the cruft
that has accumulated around OO. Go doesn't have an implicit "this" pointer. It
doesn't have members that are private to an individual object nor members
private to a type. Encapsulation exists only at the package level.

Yet Go keeps that old OO concept of method receivers. Why? I never found it
very plausible to have one special case parameter with its very own syntax,
but with type level encapsulation it did at least have some justification.

Without this kind of encapsulation, the only remaining purpose of the receiver
is method dispatch. But why dispatch based on the type of one parameter and
not the others? Multimethods would have been the logical conclusion of the OO
cleanup that Go's designers apparently intended to achieve.

~~~
dualogy
Without method receivers you wouldn't have methods, only funcs. Then you'd end
up calling your "methods" names like `Address_Compare(addr1, addr2 Address)`,
`Address_ToString(addr Address)` and so forth.

How unpleasant that'd be! With method receivers, you can have
`addr1.CompareTo(addr2)` and `addr.ToString()` etc..

~~~
4ad
Not with higher order type inference (various MLs), but then you have function
overloading and Go decided against function overloading.

/Edit: parallel comments mention multimethods. The difference is that with
higher order type inference you can do static dispatch, but multimethods are
dynamically dispatched AFAIK.

~~~
qznc
Type inference is not necessary. C++ provides function overloading as well.

~~~
4ad
Go has methods only to satisfy interfaces, which are different than most other
language's interfaces and a very crucial part of what gives the feel of Go. No
methods, no interfaces, therefore if Go were to have no methods, it would have
to offer the same features and language feel by some other mechanism. Perhaps
there are many ways to do that, but the only way I can think of is allowing
for code like this:

    
    
      type IPConn struct {
      	ip Ip
      	// contains filtered or unexported fields
      }
      
      func Write(i IPCconn, buf []byte) (int, error) { /* implementation */ }
      
      type File struct {
      	name string
      	// contains filtered or unexported fields
      }
      
      func Write(f File, buf []byte) (int, error) { /* implementation */ }
      
      func WriteString(w T, s string) (int, error) {
      	return Write(w, []byte(s))
      }
    

Please note that there are no explicit interfaces, but WriteString takes an
implicit Writer. You can do that in C++ with overloaded functions _and_
templates (not overloaded functions alone), but templates are an example of
higher order type inference, which was the point I was trying to convey.

------
drunken_thor
Here is the article that got me onto the way of go:
[http://areyoufuckingcoding.me/2012/07/25/object-
desoriented-...](http://areyoufuckingcoding.me/2012/07/25/object-desoriented-
language/) The memes are a bit much but the content is solid.

------
pjmlp
For an understanding how to do OO design in Go, learning about component
programming is a good way.

[http://www.amazon.de/Component-Software-Beyond-Object-
Orient...](http://www.amazon.de/Component-Software-Beyond-Object-Oriented-
Programming/dp/0201745720)

The first edition used Component Pascal from the Oberon family, which Go gets
some influence from. Later editions used Java and C# instead.

Additional learning about how COM and XPCOM work is also a way to get some
ideas.

~~~
discreteevent
Yes Go is similar to COM in that it focuses on interfaces and leaves out
implementation inheritance which causes so much trouble. COM was way ahead of
its time on that.

"Component Oriented Programming = Polymorphism + (Really) Late Binding +
(Real, Enforced) Encapsulation + Interface Inheritance + Binary Reuse"

Apart from "Binary Reuse", the definition above is what object oriented
programming is really all about (I think).

------
munificent
> To apply the uniform access principle to the Part type, we could change the
> struct definition and provide setter/getter methods

If you have to _apply_ it, it isn't _uniform_ access. The point of the
principle is that the call-site shouldn't distinguish between getters and
fields so that the implementer can change that decision freely without
breaking callers.

Nice article, though!

~~~
nathany
Thanks for the clarification.

------
herge
I have a question about go. Let's say I have a struct Foo and a
function/method for Less. What is the quickest way to sort an array of Foo's?

Do I have to implement my own []Foo type with all three methods as described
in the sort package?

~~~
nickpresta
[http://golang.org/pkg/sort/#example_Interface](http://golang.org/pkg/sort/#example_Interface)

~~~
herge
So the answer is yes, I have to implement the whole interface?

~~~
stonemetal
Yes, to use code that relies on an interface you must implement the interface
for your types.

That is one of the reasons go has a guiding design principle that interfaces
should be as small as possible.

------
Touche
Is there any advantage to using OO in a language that doesn't have classes or
inheritance? Does declaring a method on a type give you something that
declaring a function that takes the type as an argument doesn't?

~~~
pjmlp
There are many ways to implement OO.

Self, JavaScript, CLOS, Go, BETA, Clojure Protocols, Type Classes, COM and
probably quite a few others.

What most mainstream developers know, is not the only way.

~~~
patrickg
+1 for mentioning BETA. Any actual user of that language?

~~~
pjmlp
I got to learn about it when I attended ECOOP'99.

Never saw it outside the conference.

~~~
patrickg
BETA was the beginner's language at the University of Dortmund (Germany) back
in 1996/7/8\. Never saw it outside of these buildings.

~~~
pjmlp
Really?! Living in Düsseldorf, small world HN. :)

~~~
patrickg
Yes, I still have my book "Object Oriented Programming in the BETA Programming
Language" by Madsen/Møller-Pedersen/Nygaard with a price tag of 80 DM in 1997
(> 40 EUR now) (I now live in Berlin)

------
mostafah
One of the most common problems people have when they get to know Go is to not
embrace its approach to programming, but try to enforce what they already know
in Go programs.

This is a clear example of that. Implementing “polymorphism” with Go
interfaces is abusing interfaces! Seeing embedding as inheritance misses the
point of both embedding and inheritance. Comparing packages to namespaces
isn’t that bad, but just delays you getting to know Go for real.

I’m not saying that these old concepts are bad or Go’s new approach is
superior. (I believe in that; but that’s not the point here.) I’m saying if
you’ve gotten used to these concepts so much that you can’t think or program
without them, then there’s a problem. Don’t design a solution around
polymorphism or inheritance and then try hard to force that into Go. Design
your program with that your language is giving you.

~~~
burntsushi
Did you RTFA? The conclusion has:

> Composition, embedding and interfaces provide powerful tools for Object-
> Oriented Design in Go. Thinking in terms of inheritance really doesn't work.
> Trust me, I tried.

The OP is clearly trying to introduce ideas in Go by _relating them_ to other
ideas you might be more familiar with. This is, IMO, very much distinct from
trying to shoehorn design techniques from other languages.

In fact, the OP is rather explicitly agreeing with your point and trying to
remedy it.

> Implementing “polymorphism” with Go interfaces is abusing interfaces!

Go's interfaces use structural subtyping, which _is a form of polymorphism_.

------
crazygringo
Off-topic, but it would be nice if the blog didn't use _24-pixel body type_ ,
so that I could see more than a handful of lines at a time on my laptop.

I've never seen a book with 24-point body type, except possibly for the
visually impaired or 3-year-olds. Heck, most _headings_ aren't even 24 point.
What is it with this blog trend of gargantuan type, which seems increasingly
common? It's totally out of proportion with the rest of anyone's OS and
computer interface, and all the common sites. I'm really getting tired of
having to zoom _out_ to an insane _50%_ level just to make things legible
again.

~~~
nathany
Off-topic: You'll be disappointed to learn that I also use an 18-pt font in my
editor. I happen to like big readable text, maybe something to do with my age
and my prescription being -5.5.

P.S. the font-size is actually 1.5rem

~~~
throwit1979
34yo, -9.5 here, and I prefer 10pt fonts for code.

Do you not wear your glasses and/or contacts when working? I don't follow.

~~~
jasomill
This preference could also depend on the font and what's rendering it; on my
Thunderbolt Display, while "18pt" Consolas renders at less than 7 points wide
using OS X defaults, Windows 8, using defaults for the same display, renders
the same font at around 8.5 points wide by default, and Myriad Pro's "M" at
nearly 13 points wide. Since 13/7 is approximately 18/10, your respective
preferences may not be as different as you think.

------
noelherrick
Good article - this covers the basic OO patterns in Go. I really like the
simplicity of the design - objects are just structs and you can define a
method for that object. Coming from C#, it's like every method is an extension
method.

The only critique I have is that there's no way to verify that object X
implements methods A, B, and C. When I'm using C# or Java, I often use an
interface as a test to make sure I've done my work since the code won't
compile if a class that extends an interface fails to implement all the
methods.

~~~
lnmx
The compiler will complain if you attempt to assign (or assert) a value to an
interface that it cannot fulfill.

ex. [http://play.golang.org/p/OLTHIXjgy8](http://play.golang.org/p/OLTHIXjgy8)

