LanguagesHow to Use Structures in Go

How to Use Structures in Go

Go Programming ``

Structures are used to hold multiple values to create a user-defined type in Go. Unlike arrays, slices, or maps which typically hold homogeneous types of values, structures are composed of heterogeneous types of values within a single group. The idea is akin to Classes used in Object-Oriented Programming (OOP) languages, which enable the creation of abstract data types. There is no such so-called “Class” type in Go.

The keyword for creating structures is struct. The struct type aggregates and embeds polymorphic values together. Therefore, we can create a custom type of data using structures. Although we may think of struct types as “Classes” used in object-oriented systems, it actually more closely resembles structs used in C rather than C++ Classes.

Read: Arrays and Slices in Go

How Do You Define a Structure in Go?

The simplest way to define a structure in Go is as follows:

type Book struct {
	isbn 	string
	title 	string
	price	float
}

In Go, if we are to create any new type, we do so using the type keyword. According to the Go documentation, a type definition creates a new, distinct type with the same underlying type and operations as the given type and binds an identifier, the type name, to it. Therefore, here we use the type keyword followed by the type name and struct keyword. This typically creates a structure type with a defined name.

How Do You Initialize a Structure in Go?

Once the structure is defined we can initialize it in different ways. For example, we can do so with the following Go code example:

book := Book{"123456789", "Art of Programming", 456.78}

This creates a new struct with its field initialized to the values given. Note that the order of the values supplied must match with the order of the fields and type specified while defining the structure. This means we cannot supply values just in any order. The following is an error:

book := Book{456.78, "123456789", "Art of Programming"} //error

Another way to initialize a structure in Go is as follows:

book := Book{price: 456.78, isbn: "123456789", title: "Art of Programming"} 

Here, we supplied the field name along with the value. Note that in this case the order of fields does not matter during initialization. However, we could write our Go code in the following manner:

book := Book{
	price: 456.78, 
	isbn: "123456789", 
	title: "Art of Programming",
}

The comma used in the last field initialization is compulsory and not a mistake.

Now, what if we do not initialize a struct type:

book := Book{} 

In such a case the fields will have the default values of their type, such as 0 for integer types, “” for string types, nil for pointer types, and so on. Later, we can use the dot(.) operator to access the fields, as show in the following Goland code example:

book.price = 456.78, 
book.isbn = "123456789", 
book.title = "Art of Programming"

Read: Go Maps: A Simple, Structured Data Structure

Structure Pointers in Go and Golang

A pointer to a struct is created with the ampersand (&) operator and for dereference, the asterisk (*) operator is used. However, we can also use the dot (.) operator for dereferencing. Here is an example of how to use structure pointers in Go:

type Product struct {
	name      string
	unitPrice float32
	quantity  int
}

p1 := Product{"T107", 56.78, 12}

ptr2p1 := &p1
(*ptr2p1).name = "T203"
(*ptr2p1).quantity = 20
(*ptr2p1).unitPrice = 5.67

fmt.Printf("%+vn", ptr2p1)

The following code has the same effect as above. Note that here we are using dot (.) operator for dereferencing:

ptr2p1.name = "T301"
ptr2p1.quantity = 40
ptr2p1.unitPrice = 8.98

fmt.Printf("%+vn", ptr2p1)

Alternatively, we can create struct pointers using the new keyword. The new() function allocates dynamic memory for the structure and returns a pointer to the structure type. Here is an example of how to use new() in Go:

ptr := new(Product)
ptr.name = "T333"
ptr.quantity = 50
ptr.unitPrice = 8.97

fmt.Printf("%+vn", ptr)

Read: How to Use Pointers in Go

Nested Structures in Go and Golang

In Go, we can create a nested structure. This means that we can have a structure as a field in another structure. If we take the above example, a book can be written by multiple authors, and also a book has a publisher. Let’s redefine the structures to illustrate the idea of nested structures in Go:

package main

import "fmt"

type Book struct {
	isbn      string
	title     string
	edition   int
	price     float32
	authors   []Author
	publisher Publisher
}

type Author struct {
	id        int
	firstName string
	lastName  string
}

type Publisher struct {
	name  string
	email string
}

func main() {

b1 := Book{"978-0-262-03384-8", "Introduction to Algorithms", 3, 233.56,
		[]Author{
			{11, "Thomas", "Cormen"},
			{22, "Charles", "Leiserson"},
			{33, "Ronald", "Rivest"},
			{44, "Clifford", "Stein"},
		},
		Publisher{"MIT Press", "special_sales@mitpress.mit.edu"},
	}
	fmt.Println(b1)
	fmt.Printf("%vn", b1)
	
	fmt.Printf("%+vn", b1)

	fmt.Printf("%#vn", b1)

	fmt.Printf("ISBN: %s, Title: %s, Edition: %d, Price: %f", b1.isbn, b1.title, b1.edition, b1.price)

}

This results in the following output when run in your integrated development environment (IDE) or code editor:

-----------------------------------------------------------
{978-0-262-03384-8 Introduction to Algorithms 3 233.56 [{11 Thomas Cormen} {22 Charles Leiserson} {33 Ronald Rivest} {44 Clifford Stein}] {MIT Press special_sales@mitpress.mit.edu}}
-----------------------------------------------------------
{978-0-262-03384-8 Introduction to Algorithms 3 233.56 [{11 Thomas Cormen} {22 Charles Leiserson} {33 Ronald Rivest} {44 Clifford Stein}] {MIT Press special_sales@mitpress.mit.edu}}
-----------------------------------------------------------
{isbn:978-0-262-03384-8 title:Introduction to Algorithms edition:3 price:233.56 authors:[{id:11 firstName:Thomas lastName:Cormen} {id:22 firstName:Charles lastName:Leiserson} {id:33 firstName:Ronald lastName:Rivest} {id:44 firstName:Clifford lastName:Stein}] publisher:{name:MIT Press email:special_sales@mitpress.mit.edu}}
-----------------------------------------------------------
main.Book{isbn:"978-0-262-03384-8", title:"Introduction to Algorithms", edition:3, price:233.56, authors:[]main.Author{main.Author{id:11, firstName:"Thomas", lastName:"Cormen"}, main.Author{id:22, firstName:"Charles", lastName:"Leiserson"}, main.Author{id:33, firstName:"Ronald", lastName:"Rivest"}, main.Author{id:44, firstName:"Clifford", lastName:"Stein"}}, publisher:main.Publisher{name:"MIT Press", email:"special_sales@mitpress.mit.edu"}}
-----------------------------------------------------------
ISBN: 978-0-262-03384-8, Title: Introduction to Algorithms, Edition: 3, Price: 233.559998

Note that here, the Book structure contains another structure called the Publisher struct and an array of the Author structure as its field. The initialization part is self-explanatory. The code illustrates how we can create a Book object and how each field can be initialized with values accordingly.

Observing the output, we can simply supply the structure to the fmt.Println function and it prints the values in the standard output. This means the following two mean the same thing and have the same output:

fmt.Println(b1)
fmt.Printf("%vn", b1)

However:

 
fmt.Printf("%+vn", b1)

means we also want to print the field names defined in the structure:

 
fmt.Printf("%#vn", b1)

Printing with #v means we not only want to print the field names but also the package name where this structure is defined:

fmt.Printf("ISBN: %s, Title: %s, Edition: %d, Price: %f", b1.isbn, b1.title, b1.edition, b1.price)

And the last one is a typical formatted print by accessing each field with dot (.) operator. No surprises here.

Read: How to Handle Errors in Go

Anonymous Structures in Go

As may be obvious, anonymous structures do not have a name and can be declared only once. Anonymous structures are created using only the struct keyword and the declaration must follow initialization as follows:

proj := struct {
	id       int
	name     string
}{
	id:       101,
	name:     "Project X",
}

But, the following is also a valid way to create anonymous structures in Go:

proj := struct {
	id       int
	name     string
}{}

Technically, in the first case, we are supplying initialization values explicitly, but in the latter case, the fields get initialized implicitly by their default values.

We also can create a nested anonymous structure in Go as follows:

type Department struct {
	name     string
	location string
}

proj := struct {
	id   int
	name string
	Department
}{
	id:         101,
	name:       "Project X",
	Department: Department{"X Lab", "Mars"},
}

Note that here, the anonymous structure has another anonymous Department structure. It has an undefined field name of a structure type called Department.

How to use the Structure Method in Go

The structure typically contains data fields but also can include methods to define the behavior of the structure. The following is a quick example of how to use the structure method in Go:

type Product struct {
	name      string
	unitPrice float32
	quantity  int
}

func (p Product) totalPrice() float32 {
	return p.unitPrice * float32(p.quantity)
}

//...

p1 := Product{"T107", 56.78, 12}
fmt.Printf("Name = %s, Total Price = %.2f", p1.name, p1.totalPrice())

Here, we have added a totalPrice() function to the structure Product. The totalPrice() function works in tandem with Product type as we define the function as func (p Product) totalPrice() float32.

Key Points for Using the Go Structure Method

Here are some key points to keep in mind when using the Go structure method:

    • Use type to define a structure, followed by a and the struct keyword.
    • Structure fields can be accessed using the dot (.) operator.
    • Structure pointers can also access the fields using the dot (.) operator. Go uses automatic dereferencing in this case.
    • Structure fields are implicitly initialized to their respective default values or can be explicitly initialized at the time of its definition.

When initialized using field names, the order does not matter, otherwise order matters.

Final Thoughts Using Structures and struct in Go

Complex data structures are stored in structures in Go. Unlike many other OOP languages, Go does not have a Class-Object architecture. But if we are to implement OOP technique in Go, the structure type provides the base for data abstraction. In this Go programming tutorial, we have given a quick introduction to the use of structures in Golang.

Read more Go and Golang programming tutorials and software development guides.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories