Golang provides built-in types such as bool
, byte
, string
as well as the ability to define custom types. Users create a custom type by defining a collection of fields known as a struct
. Each field has an explicitly defined type; the type can be a built-in type or a user defined type. Because they can be used to store complex information records and accommodate associated method functions, structs are considered the go equivalent of classes used in traditional object oriented programming.
Creating Structs
Empty Structs
You can create an empty struct instance by not specifying any fields when instantiating. Doing so sets each struct field to the default value for its type (e.g. an empty string for string
, 0
for float64
, etc.):
type Planet struct {
class string
diameter float64
name string
}
func main() {
var planet1 Planet
planet2 := Planet{}
fmt.Println("planet1:", planet1)
fmt.Println("planet2:", planet2)
}
planet1: { 0 }
planet2: { 0 }
You can also use pointers to create the usual empty struct instance or a nil
struct instance:
type Planet struct {
class string
diameter float64
name string
}
func main() {
var planet1 *Planet
planet2 := &Planet{}
planet3 := new(Planet)
fmt.Println("planet1:", planet1)
fmt.Println("planet2:", planet2)
fmt.Println("planet3:", planet3)
}
planet1: <nil>
planet2: &{ 0 }
planet3: &{ 0 }
Struct Literals
Struct instances aren’t very helpful if they’re empty, so we define struct fields when instantiating with struct literals:
type Planet struct {
class string
diameter float64
name string
}
func main() {
// instantiate with field keys and values
planet1 := Planet{
class: "M",
diameter: 12742,
name: "Earth",
}
// instantiate with field values
planet2 := Planet{"K", 6779, "Mars"}
// instantiate pointer with field keys and values
planet3 := &Planet{
class: "J",
diameter: 116460,
name: "Saturn",
}
fmt.Println("planet1:", planet1)
fmt.Println("planet2:", planet2)
fmt.Println("planet3:", planet3)
}
planet1: {M 12742 Earth}
planet2: {K 6779 Mars}
planet3: &{J 116460 Saturn}
Nested Structs
In addition to the built-in types, you can also define a struct field as a user defined type (i.e. another struct):
type Class struct {
description string
name string
}
type Planet struct {
class Class
diameter float64
name string
}
func main() {
planet := Planet{
class: Class{
description: "Earth-like atmosphere containing oxygen - habitable for humanoid life forms",
name: "M",
},
diameter: 12742,
name: "Earth",
}
fmt.Println("planet:", planet)
}
planet: {{Earth-like atmosphere containing oxygen - habitable for humanoid life forms M} 12742 Earth}
Accessing Structs
Struct fields can be accessed with dot notation. If the struct instance is a pointer, golang de-references the pointer automatically and accesses the struct fields:
type Class struct {
description string
name string
}
type Planet struct {
class Class
diameter float64
name string
}
func main() {
classM := Class{
description: "Earth-like atmosphere containing oxygen - habitable for humanoid life forms",
name: "M",
}
classJ := Class{
description: "Gas giant",
name: "J",
}
planet1 := Planet{
class: classM,
diameter: 12742,
name: "Earth",
}
planet2 := &Planet{
class: classJ,
diameter: 116460,
name: "Saturn",
}
fmt.Println("planet:")
fmt.Println(" name:", planet1.name)
fmt.Println(" class:", planet1.class.name)
fmt.Println(" diameter:", planet1.diameter, "km")
// planet2 is a pointer to a struct instance that is
// automatically dereferenced and its fields accessed for printing
fmt.Println("planet:")
fmt.Println(" name:", planet2.name)
fmt.Println(" class:", planet2.class.name)
fmt.Println(" diameter:", planet2.diameter, "km")
}
planet:
name: Earth
class: M
diameter: 12742 km
planet:
name: Saturn
class: J
diameter: 116460 km
Modifying Structs
All struct instances are mutable so they can be modified after they have been instantiated:
type Planet struct {
class string
diameter float64
name string
}
func main() {
var planet Planet
planet.class = "N"
planet.diameter = 12104
planet.name = "Venus"
fmt.Println("planet:", planet)
planet.class = "J"
planet.diameter = 139820
planet.name = "Jupiter"
fmt.Println("planet:", planet)
}
planet: {N 12104 Venus}
planet: {J 139820 Jupiter}
Struct Methods
You can define a method for a struct by specifying the struct as a receiver to a function:
type Planet struct {
class string
diameter float64
name string
}
func (p Planet) getCircumference() float64 {
return math.Pi * p.diameter
}
func main() {
planet := Planet{
class: "J",
diameter: 49244,
name: "Neptune",
}
fmt.Println("planet:")
fmt.Println(" name:", planet.name)
fmt.Println(" class:", planet.class)
fmt.Println(" circumference:", planet.getCircumference(), "km")
fmt.Println(" diameter:", planet.diameter, "km")
}
planet:
name: Neptune
class: J
circumference: 154704.58863337577 km
diameter: 49244 km