A struct in Golang is a user defined data type which can contain multiple items in key-value pairs. It is a collection of related properties grouped into a single named type.
A simple example is an employee structure which contains fields such as name, age, address of an employee along with its values.
Once a struct is defined, you can create multiple variables having different values.
A struct is a user defined data type. As such, it is declared using
type
keyword.Syntax is
type <struct_name> struct { property_name data_type property_name data_type }
Here,
struct
is a keyword which identifies that we are declaring a struct.
struct_name and property_name are user defined names of struct and its properties respectively.
data_type is the data type of the value a property will contain.
Note that there may be any number of properties in a struct and there is no separator between multiple properties.
Example of an employee struct is,
type employee struct { firstName string lastName string age int }
If multiple properties have the same data type, they can be declared in the same line without repeating the data type as
type employee struct { firstName, lastName string age int }
In this case, property names should be separated by comma.
Create struct
Once a struct is declared and defined, you can create variables of its type having different values.
There are two ways to create or initialize a struct variable
1. With only values
Supply values to struct properties as
var emp = employee{"ABC", "XYZ", 23} // short form emp := employee{"ABC", "XYZ", 23}
Property values are initialized in the order in which they appear in declaration.
This syntax has a disadvantage that if the order of properties in struct definition changes, then it needs to be updated in initialization as well.
2. With property names and values
In this method, property names are used along with their values separated by a colon as shown below.
var emp = employee{firstName:"ABC", lastName:"XYZ", age:23} // short form emp := employee{firstName:"ABC", lastName:"XYZ", age:23}
Changing the order of properties in struct definition has no effect on its values.
Properties of a struct can be accessed using struct name and the name of property separated by a dot(.) as shown below.
// create a struct emp := employee{firstName:"ABC", lastName:"XYZ", age:23} // get the first name fn := emp.firstName ln := emp.lastName age := emp.age
Printing struct
A struct when printed outputs the values of all its properties separated by a space enclosed between curly braces. Example,
// create a struct emp := employee{firstName:"ABC", lastName:"XYZ", age:23} fmt.Println(emp)
This will print
{ABC XYZ 23}
struct example
Below is a complete example showing how to define a struct, initialize struct variable, access and modify its properties.
package main import ( "fmt" ) // define struct type employee struct { firstName string lastName string age int } func main() { // create struct emp := employee{firstName: "ABC", lastName: "XYZ", age: 23} // print its properties fmt.Println("Employee Name:", emp.firstName+" "+emp.lastName) fmt.Println("Employee Age:", emp.age) // modify property value emp.age = 24 fmt.Println("Updated employee Age:", emp.age) // print struct fmt.Println("Employee struct:",emp) }
This prints
Employee Name: ABC XYZ
Employee Age: 23
Updated employee Age: 24
Employee struct: {ABC XYZ 24}
An anonymous struct is a struct without a name. Anonymous structs are defined at the point where they are needed.
These should be used when a struct is required only once.
Anonymous struct combines the definition of fields and their values in two separate blocks within curly braces.
Anonymous struct is created using only the
struct
keyword followed by the definition of fields that it will contain and the value of those fields, both in separate blocks. Example, package main import ( "fmt" ) func main() { emp := struct { firstName, lastName string age int }{firstName: "ABC", lastName: "XYZ", age: 23} fmt.Println("Employee Name:", emp.firstName+" "+emp.lastName) fmt.Println("Employee Age:", emp.age) }
Note that anonymous structs do not need to be defined at the top.
Functions in struct
You can also define a function as a struct field in Go. This makes a struct more dynamic since it enables it to perform computations or processing power as well.
For using a function as struct field,
1. a function needs to be defined before struct definition using type
keyword.
Function definition includes name of the function, data types of parameters that it will accept and its return type.
This definition does not have names of parameters, only their data types.
2. struct definition needs to have a field, that is bound to the function name.
Function body is written while initializing struct. It is written in the same way as a function is defined in Go but without a name.
It contains func
keyword with the name and types of parameters, return type of function along with the logic that the function should perform.
Example,
package main import ( "fmt" ) // define function type getName func(string, string) string // define struct type employee struct { firstName, lastName string age int name getName } func main() { // create struct with function emp := employee{"ABC", "XYZ", 23, func(fn string, ln string) string { return fn + " " + ln }} // print struct fmt.Println("Employee struct:", emp) // invoke struct function fmt.Println("Employee name:", emp.name(emp.firstName, emp.lastName)) }
Notice how the function is invoked using struct field which is of type function. This outputs
Employee struct: {ABC XYZ 24 0x499200}
Employee name: ABC XYZ
Note that the last value when the struct is printed is the memory address of function.
Nested struct
A struct may contain another struct as a field and this is called struct nesting or embedding struct.
For embedding a struct, first it needs to be defined using type
just as we defined till now and then a field is added in the main or outer struct whose data type is the name of the struct that we defined earlier. Example,
package main import ( "fmt" ) // define inner struct type empAddress struct { city, country string pin int } // embedding struct type employee struct { firstName, lastName string age int address empAddress } func main() { // create inner struct address := empAddress{"Sydney","Australia",2063} // embedded struct emp := employee{"ABC","XYZ", 23, address} fmt.Println("Employee struct:", emp) }
Notice how a struct is defined and used inside another struct. This example prints
Employee struct: {ABC XYZ 24 {Sydney Australia 2063}}
Embedded struct can be initialized in the same line as
emp := employee{"ABC","XYZ", 23, empAddress{"Sydney","Australia",2063}}
Accessing nested struct fields
In order to access the fields of the inner struct, first we need to access the inner struct property and then the required properties of the inner struct.
This requires using dot multiple times as shown below.
package main import ( "fmt" ) // define inner struct type empAddress struct { city, country string pin int } // embedding struct type employee struct { firstName, lastName string age int address empAddress } func main() { // create inner struct add := empAddress{"Sydney","Australia",2063} // embedded struct emp := employee{"ABC","XYZ", 23, add} fmt.Println("Employee country:", emp.add.country) fmt.Println("Employee city:", emp.add.city) fmt.Println("Employee pin:", emp.add.pin) }
which prints
Employee country: Australia
Employee city: Sydney
Employee pin: 2063