Introduction to Struct

This lesson introduces structs, addressing rudimentary concepts such as declaration and memory allocation.

Go supports user-defined or custom types in the form of alias types or structs. A struct tries to represent a real-world entity with its properties. Structs are composite types to use when you want to define a type that consists of several properties each having their type and value, grouping pieces of data together. Then, one can access that data as if it were part of a single entity.

Structs are value types and are constructed with the new function. The component pieces of data that constitute the struct type are called fields. A field has a type and a name. Field names within a struct must be unique.

The concept was called ADT (Abstract Data Type) in older texts on software engineering. It was also called a record in older languages like Cobol, and it also exists under the same name of struct in the C-family of languages and in the OO languages as a lightweight-class without methods.

However, because Go does not have the concept of a class, the struct type has a much more important place in Go.

Definition of a struct

The general format of the definition of a struct is as follows:

type identifier struct {
  field1 type1
  field2 type2
  ...
}

Also, type T struct { a, b int } is legal syntax and is more suited for simple structs. The fields in this struct have names, like field1, field2, and so on. If the field is never used in code, it can be named _.

These fields can be of any type, even structs themselves, functions or interfaces. Because a struct is a value, we can declare a variable of the struct type, and give the values of its fields, like:

var s T
s.a = 5
s.b = 8

An array could be seen as a sort of struct but with indexed rather than named fields.

Using new() function

Memory for a new struct variable is allocated with the new function, which returns a pointer to the allocated storage:

var t *T = new(T)

This can be put on different lines if needed (e.g., when the declaration has to be package scope, but the allocation is not needed at the start):

var t *T
t = new(T)

The idiom to write this shorter is: t := new(T); the variable t is a pointer to T. At this point, the fields contain the zero-values according to their types. However, declaring var t T also allocates and zero-initializes memory for t, but now t is of type T. In both cases, t in OO jargon is commonly called an instance or object of the type T, but in Go it is merely a value of type T.

The fields can be given a different value by using the dot-notation, as is custom in OO-languages:

structname.fieldname = value

The values of the struct-fields can be retrieved with the same notation:

structname.fieldname

This is called a selector in Go. In order to access the fields of a struct, whether the variable is of the struct type or a pointer to the struct type, we use the same selector-notation:

type myStruct struct { i int, j float32, k string }
var v myStruct // v has struct type
var p *myStruct // p is a pointer to a struct
v.i
p.i

An even shorter notation and the idiomatic way to initialize a struct value (a struct-literal) is the following:

v := &myStruct{10, 15.5, "Chris"} // this means that `v` is of type *myStruct

or:

var mt myStruct
mt = myStruct{10, 15.5, "Chris"}

A simple example is given below:

Get hands-on with 1200+ tech skills courses.