Go Struct

Summary: in this tutorial, you will learn how to use the Go struct including defining a struct, accessing and modifying fields, and passing a struct to a function.

In Go, a struct is a composite type that groups one or more variables under a single name. These variables may have different types. They are known as the fields of the struct.

A struct in Go is similar to a class in other object-oriented programming languages such as Java and C# but it is simpler and more lightweight.

Defining a struct

To define a struct, you use the following syntax:

type structName struct {
   field1 type1
   field2 type2
   ...
}Code language: Go (go)

In this syntax:

  • First, use the type keyword followed by the name of the struct and the struct keyword.
  • Second, list the field names with their corresponding types within the curly braces.

For example, the following defines a struct Person that has two fields Name and Age. The Name field has type string and the Age field has type int:

type Person struct {
    Name string
    Age  int
}Code language: Go (go)

Creating a struct instance

After having a struct, you can define a variable with the type of the struct name. For example:

var p PersonCode language: Go (go)

In this example, p is a variable with the type Person struct. It is called an instance of the Person struct.

When you create a struct instance without setting its fields, Go automatically assign zero values to those fields. For example:

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    var p Person
    fmt.Println(p)
}Code language: Go (go)

Output:

{ 0}Code language: Go (go)

In this example, we define the Person struct instance without setting its fields. The Name and Age are empty and zero respectively.

To print a struct variable that includes both field names and values, you use the fmt.Printf() function with the %+v format:

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    var p Person
    fmt.Printf("%+v\n", p)
}Code language: Go (go)

Output:

{Name: Age:0}Code language: Go (go)

The following shows how to assign a value to the instance of the Person struct:

var p Person
p = Person{"Joe", 30}
fmt.Printf("%+v\n",p)Code language: Go (go)

Output:

{Name:Joe Age:30}Code language: Go (go)

In this syntax, Go assigns "Joe" to the Name field and 30 to the Age field respectively.

In practice, you should avoid creating a struct value using this syntax because it depends on the order of fields in the Person struct.

If you change the order of the fields in the struct definition, you may encounter errors or unexpected behaviors.

A better approach is to explicitly specify the field names and their values when creating a struct instance:

var p Person
p = Person{Name: "Joe", Age: 30}
fmt.Printf("%+v\n", p)Code language: Go (go)

Output:

{Name:Joe Age:30}Code language: Go (go)

Alternatively, you can use the shorthand notation to declare and initialize a struct variable as follows:

p := Person{Name: "Joe", Age: 30}Code language: Go (go)

This code is more concise and robust. But you can use it only inside a function.

When using a multi-line initialization, you need to place a comma after the last field:

p := Person {
    Name: "Joe",
    Age:  30,
}Code language: Go (go)

Notice that there is a comma (,) after the line Age: 30.

Put it all together:

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    p := Person{
        Name: "Joe",
        Age:  30,
    }
    fmt.Printf("%+v\n", p)
}Code language: Go (go)

Output:

{Name:Joe Age:30}Code language: Go (go)

Accessing struct fields

To access a field of a struct, you use the dot notation:

structVariable.fieldCode language: Go (go)

For example, to access the Name and Age fields of the Person struct, you use p.Name and p.Age:

p := Person{
    Name: "Joe",
    Age:  30,
}
fmt.Println("Name:", p.Name)
fmt.Println("Age:", p.Age)Code language: Go (go)

Output:

Name: Joe
Age: 30Code language: Go (go)

Modifying struct fields

To modify a field in a string, you assign a new value to that field using the dot notation. For example, the following increases the Age field value by one:

p := Person{
    Name: "Joe",
    Age:  30,
}
p.Age += 1
fmt.Println("Age:", p.Age)Code language: Go (go)

Output:

Age: 31Code language: Go (go)

Nested structs

Go allows a struct to be nested within another struct to create a complex data structure. For example:

package main

import "fmt"

type Address struct {
    City, State, ZipCode string
}
type Person struct {
    Name    string
    Age     int
    Address Address
}

func main() {
    p := Person{
        Name: "Joe",
        Age:  30,
        Address: Address{
            City:    "New York",
            State:   "NY",
            ZipCode: "10001",
        },
    }
    fmt.Printf("%+v", p)
}Code language: Go (go)

How it works.

First, define a struct Address that includes three string fields City, State, and ZipCode:

type Address struct {
    City, State, ZipCode string
}Code language: Go (go)

Since three fields have the same type, you can specify them in a single declaration.

Second, define the Person struct that has three fields Name, Age, and Address. The type of the Address field is the Address struct:

type Person struct {
    Name    string
    Age     int
    Address Address
}Code language: Go (go)

Third, declare and initialize a Person struct inside the main() function and print it out:

func main() {
    p := Person{
        Name: "Joe",
        Age:  30,
        Address: Address{
            City:    "New York",
            State:   "NY",
            ZipCode: "10001",
        },
    }
    fmt.Printf("%+v", p)
}Code language: Go (go)

Output:

{Name:Joe Age:30 Address:{City:New York State:NY ZipCode:10001}}Code language: Go (go)

Passing a struct to a function

The following program attempts to pass a struct instance to a function and change the field value within the function.

package main

type Person struct {
    Name string
    Age  int
}

func IncreaseAge(p Person) {
    p.Age += 1
}

func main() {
    p := Person{
        Name: "Joe",
        Age:  30,
    }
    IncreaseAge(p)
    println(p.Age) // 30
}Code language: Go (go)

How it works.

First, define the struct Person with two fields Name and Age:

type Person struct {
    Name string
    Age  int
}Code language: Go (go)

Next, define the IncreaseAge function that accepts a Person struct instance. Inside the IncreaseAge function, increase the Age field value by one:

func IncreaseAge(p Person) {
    p.Age += 1
}Code language: Go (go)

Then, declare and initialize a struct variable inside the main() function:

p := Person{Name: "Joe", Age: 30}Code language: Go (go)

After that, pass the struct instance to the IncreaseAge variable:

IncreaseAge(p)Code language: Go (go)

Finally, display the Age value:

println(p.Age)Code language: Go (go)

The value of Age field doesn’t change outside of the IncreaseAge function. This is because Go passes a struct to the IncreaseAge function by value.

This means Go makes a copy of the p struct and changes the Age on the copied version. Therefore, the change is not reflected outside the IncreaseAge function.

To fix this issue, you need to use a pointer. Instead of passing a struct instance to the IncreaseAge function, you can pass a pointer that points to the struct instance:

package main

type Person struct {
    Name string
    Age  int
}

func IncreaseAge(p *Person) {
    (*p).Age += 1
}

func main() {
    p := Person{Name: "Joe", Age: 30}
    IncreaseAge(&p)
    println(p.Age)
}Code language: Go (go)

Output:

31Code language: Go (go)

How it works.

First, change the struct instance in the increaseAge() function to a pointer of type Person struct:

func IncreaseAge(p *Person) {
   (*p).Age += 1
}Code language: Go (go)

Inside the IncreaseAge function, add one to the Age field via the pointer.

Second, pass a pointer to the p variable to the increaseAge function in the main() function:

IncreaseAge(&p)Code language: Go (go)

Summary

  • A struct is a composite type that includes multiple fields, which can have different types.
  • To define a struct, use the type keyword followed by the struct name, struct keyword, and a list of fields.
  • Use dot notation to access and modify fields.
  • A struct can also be nested within another struct.
Was this tutorial helpful?