Comment on page
22. Structs
Working with different types together
Slice and array are good for storing collection of data which is of same type. What if our data is made up of smaller types which are different? This is where struct comes in handy.A struct is a type that contains named fields. Struct is a value that is constructed out of other values of many different types.
Slices and maps are used to store collection of similar data where as struct is used to groups together zero or more named values of arbitrary types as a single entity. Grouping together data of different types, that's where struct is useful.
A simple struct can be constructed using
struct
keyword asstruct {field type}
main.go
var person struct {
name string
age int
}
name
and age
are called fields of struct.Generally, we will use multiple instance of struct in code. It is very common define struct as user defined type using
type
keyword for reuse.main.go
type person struct {
name string
age int
}
var p1 person
var p2 person
now
person
is a user defined struct
type. p1
and p2
variables are both of type person
.Declaring a variable of a particular struct type creates a struct. There is no explicit call required to any other function.
main.go
var p1 person
var p2 person
fmt.Println(p1)
fmt.Println(p2)
Struct fields are accessed using dot operator
.
This can be used to read as well as write to struct fields.main.go
p1.name = "Joey"
p1.age = 30
fmt.Println(p1)
When a struct is declared, it gets initialized to zero values for its all the fields.
main.go
type show struct {
name string
price float64
isAvailable bool
rating int
}
var s show
fmt.Printf("%#v\n", s)
// output
// main.show{name:"", price:0, isAvailable:false, rating:0}
We can use struct literals to declare and initialize struct with initial value instead of zero value. We can define person struct type using struct literal as
main.go
var p3 person = person{
name: "Chandler",
age: 32,
}
fmt.Printf("%#v\n", p3)
Two structs of same type are comparable if and only if all the fields of the struct are comparable using
==.
main.go
var p4 person = person{
name: "Chandler",
age: 32,
}
var p5 person = person{
name: "Joey",
age: 30,
}
fmt.Println("are p4 and p5 equal? ==>", p4 == p5)
Like we can use data types like integers ,floats and strings as fields for a struct, we can also user another struct as field for building new structs. This is useful for reusing already created user defined types.
main.go
type human struct {
name string
age int
}
type superHuman struct {
human human
power string
}
superman := superHuman{
human: human{
name: "Clark Kent",
age: 30,
},
power: "Flying",
}
fmt.Printf("%#v\n", superman)
// output
// main.superHuman{human:main.human{name:"Clark Kent", age:30}, power:"Flying"}
Note that if we need to access name of superman we need to use
superman.human.name
main.go
fmt.Println(superman.human
.name)
What if we wish to use
superman.name
instead of superman.human.name
in above code? Go supports this by providing type embedding. An inner struct that is stored within an outer struct using an anonymous field is said to be embedded within the outer struct.We are embedding
human
type inside superHero
type. There is no named field inside superHero
to which we are assigning human
type. Outside struct literal, we can access fields of human
type directly as if these fields exists on superHero
. This is called type promotion.main.go
type superHero struct {
livesSaved int
human // embedding type
}
batman := superHero{}
ironman := superHero{
livesSaved: 100000,
human: human{
name: "Tony",
age: 40,
},
}
batman.name = "Bruce" // accessing embedded type's field
batman.age = 50 // accessing embedded type's field
batman.livesSaved = 100
fmt.Printf("%#v\n", batman)
fmt.Printf("%#v\n", ironman)
Last modified 4yr ago