Here’s an introduction to Go structs. This tutorial is aimed at readers who are familiar with at least on other programming language. I’ve omitted pointers as they may be too advanced for non C/C++ developers.
type Square struct { Side int
}
This is a square & it has one field: side
. Let’s add a simple method to it, to calculate its perimeter. Unlike most non .NET programming languages, fields & methods are capitalized on the basis of their being public or private. Here Side
is capitalized as it’s a public field.
Methods are created outside the struct
body.
func (s Square) Perimeter() int { return 4 * s.Side
}
Devs from other languages, may be confused as to why there’s an (s Square)
before the method name.
In Go, the implicit variable is explicit
i.e. instead of using this
(Java, C++, ECMAScript, C#) or self
(Python), we explicitly declare a variable s
of type Square
. It marks the function as a method of Square
& allows us to use fields & methods of the current instance.
Let’s add another method area
& make both their return types float64, (we’ll see why later).
func (s Square) Perimeter() float64 { return float64(4 * s.Side)
} func (s Square) Area() float64 { return float64(s.Side * s.Side)
}
Let’s create another struct for circles.
type Circle struct { Radius int
} func (c Circle) Diameter() int { return c.Radius * 2
} func (c Circle) Perimeter() float64 { return c.Circumference()
} func (c Circle) Circumference() float64 { return math.Pi * float64(c.Diameter())
} func (c Circle) Area() float64 { return math.Pi * math.Pow(float64(c.Radius),float64(2))
}
I want to draw your attention to the last 2 methods. We cannot simply do
math.Pow(c.Radius, 2)
. The compilation would fail as math.Pow
expects 2 float64 arguments. There are no other versions, since
Go does not support overloading despite being a typed language.
Also, in Circumference
, since c.Radius
is declared as an int
, multiplying it with a float64
returns an int
, & hence the cast is needed. This cast wouldn’t be necessary while multiplying a float64
with an int
literal (eg: f1 * 5
vs f1 * float64(i1)
) .
Interfaces (this isn’t polymorphism)
Suppose we want to create an array containing shapes, & find each their respective perimeter & area, as below.
arr := [4]Shape{ Circle{5} , Circle{7}, Square{15}, Triangle{8, 5, 4} }
for _,sh := range arr { fmt.Println(sh.Perimeter()) fmt.Println(sh.Area())
}
We would need to create an interface Shape
. Go interfaces aren’t like your traditional super-classes like Java, C++ or C#. There’s no struct Foo implements Bar
kind of code involved.
It actually embodies the
walks like a duck, quacks like a duck, is a duck
principle, a bit similar to ECMAScript i.e.
struct implements all methods specified in an interface ⇔ struct implements the interface
We’ll just add the below interface.
type Shape interface { Area() float64 Perimeter() float64
}
That’s it. Circle
, Triangle
& Square
implement Shape automatically. Can you now infer why, our even our Square
methods had to return float64
?
That’s all folks. To know more about structs especially about using pointers you can take the tour of Go.