To a large extend, this (and any next posts on Go) reflect my personal journey with the language, from the very basics, to the (hopefully) mastering a new language.
Although Go takes a (few) step(s) away from the traditional object-oriented languages (think Java, Ruby, C#), so far I find it totally possible to write good object-oriented code.
Take for instance polymorphism. The program below show how you can define and execute code that acts much like overridden polymorphic methods. This code also show one very, very nice Go feature -- strong support for composition. Take a close look at how Rect composes a Square within itself, which is basically how we say that a Rect is a Square (well, you can argue that mathematically it's more like the opposite, but it was easier for me to structure the code this way) and as such, all Square's members are automatically accessed via Rect with no call forwarding. This lets us using simply
this.a * this.band not
this.Square.a * this.balthough this would also work fine. In other words, syntactically and semantically, it's very similar to what we achieve with inheritance in traditional OO languages.
package main import ( "fmt" "math" ) func main(){ cir := new(Circle); cir.rad = 10; calc_area(cir); square := new(Square); square.a = 100; calc_area(square); rect := new(Rect); rect.a = 10; rect.b = 50; calc_area(rect); } // common interface for all shapes type Shape interface { area() float32 } type Circle struct { rad float32 } // just for convenience square and rectangle are inverted // i.e. a rectangle is a square which is probably not that // right from purist OO standpoint but makes the code more clear type Square struct { a float32 } // rectangle is a square with additional piece of information // regarding side type Rect struct { Square b float32 } // 'polymorphic' methods in action func (this *Circle) area() float32{ return math.Pi * this.rad * this.rad; } func (this *Square) area() float32 { return this.a * this.a; } func (this *Rect) area() float32 { return this.a * this.b; } func calc_area(this Shape){ fmt.Println(this.area()); }
This code produces the following output: