DEV Community

CitronBrick
CitronBrick

Posted on • Edited on

Go Structs for programmers

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
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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#), 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)
}
Enter fullscreen mode Exit fullscreen mode

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))
}
Enter fullscreen mode Exit fullscreen mode

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())
}
Enter fullscreen mode Exit fullscreen mode

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
}
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)