Go Structs for programmers

RMAG news

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.

Leave a Reply

Your email address will not be published. Required fields are marked *