W3Basic Logo

Go struct

A structure or struct in Golang is a user-defined type that allows to group set of related data together into a single type.

For example, you might want to consider a Point as a structure that contains an x and a y coordinate or a Person as a structure that contains a name, an age, and a list of friends.


Declaring a structure

A structure is declared using the type keyword and has the following general form:

type name struct {
    field1 type1
    field2 type2
    // etc.
}

where name is the name of the structure, field1 and field2 are the names of the fields and type1 and type2 are the associated types.

Basic examples

Let's write a structure for the two examples above:

type Point struct {
    x float64
    y float64
}

that can be used as follows:

p := Point{1.0, 2.0}
fmt.Println(p.x, p.y)

and

type Person struct {
    name    string
    age     int
    friends []Person
}

that can be used as follows:

package main

import "fmt"

func main() {

    type Person struct {
        name    string
        age     int
        friends []Person
    }

    john := Person{"John", 20, []Person{}}
    marc := Person{"Marc", 21, []Person{john}}
    paul := Person{"Paul", 22, []Person{john, marc}}
    fmt.Println(paul)
    fmt.Println(paul.friends[0].name)

}

Output

{Paul 22 [{John 20 []} {Marc 21 [{John 20 []}]}]}
John

This last example shows that a field can be a structure itself. It should remind you of recursive functions (such as the factorial function).

Accessing the properties in Struct

We can access the struct field/properties using its instances. For Example:

package main

import "fmt"

func main() {

    type Person struct {
        name string
        age  int
    }
    
    // create an instance of Person
    employee := Person{"John", 20}
    
    fmt.Println("Name:", employee.name)
    fmt.Println("Age:", employee.age)

}

Output

Name: John
Age: 20

Here, we have created a struct of type Person, and it has two fields, name and age. Later we created an instance of struct with an object john.

Using the dot notation (.), we can now access the fields of the struct.

Functions taking or returning a structure

A function can take a structure as a parameter or return a structure as a result. For example, we can write a function that returns the distance between two points:

func distance(p1, p2 Point) float64 {
    return math.Sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y))
}

Note: the math package should be imported.

Or we might compute the number of friends of a person:

func nbFriends(p Person) int {
    return len(p.friends)
}

But a function might also return a structure.

func translate(p Point, dx, dy float64) Point {
    return Point{p.x + dx, p.y + dy}
}

In this version of the translate function, we create a new Point structure and return it. But sometimes, we might want to modify the structure in place.

Pointers to structures

In order to mutate a structure, we need to pass a pointer to it rather than letting the function create a copy of it.

func translate(p *Point, dx, dy float64) {
    p.x += dx
    p.y += dy
}

and it is used as follows:

p := Point{1.0, 2.0}
translate(&p, 3.0, 4.0)
fmt.Println(p.x, p.y)

The only difference in the syntax is the * before the type of the parameter and the & before the variable name when calling the function.

© 2023 W3Basic. All rights reserved.

Follow Us: