Structs are a way to structure and use data. It allows us to group data. In this article, we will see how to declare and use it.
Defining a Struct in Go
To use a struct we declare the type of struct we are going to use. The code below shows how to define a struct type using the type keyword.
package main
import (
"fmt"
)
type Fruit struct {
name string
}
// to define a struct type use
// type structname struct {
// field1 type1
// field2 type2
// ...
// }
func main() {
}
Declaring Struct Variables
We will see how to declare a struct variable. It is really simple as shown below.
var variablename structname // declare a struct variable
What is a zero-value Struct?
When a struct is declared but has not assigned any value, it is then a zero-valued struct. That means, all the fields will take their respective zero-values from their types.
package main
import (
"fmt"
)
type Fruit struct {
name string
}
func main() {
var apple Fruit
fmt.Println(apple) // prints {}
}
Creating and initializing a Struct in Golang
Now, we will create structs and initialize them with values. There are a few ways we could do that.
1. Using struct Literal Syntax
Struct literal syntax is just assigning values when declaring and it is really easy.
package main
import (
"fmt"
)
type Fruit struct {
name string
}
func main() {
var apple = Fruit{"Apple"} // struct literal syntax
fmt.Println(apple) // prints {Apple}
}
2. Using the new keyword
We can use the new keyword when declaring a struct. Then we can assign values using dot notation to initialize it.
package main
import (
"fmt"
)
type Fruit struct {
name string
}
func main() {
var banana = new(Fruit)
banana.name = "Banana"
fmt.Println(banana) // prints &{Banana}
}
3. Using pointer address operator
The pointer address operator(&) can be used to declare a struct. Let’s see how we would do that.
package main
import (
"fmt"
)
type Fruit struct {
name string
}
func main() {
var mango = &Fruit{"Mango"}
fmt.Println(mango) // prints &{Mango}
}
Types of Structs in Go
A struct can both be named as well as unnamed or anonymous. Both have their uses. We will what are those and how to use them.
1. Named struct
A named struct is any struct whose name has been declared before. So, it can be initialized using its name.
type Food struct {} // Food is the name
2. Anonymous struct
Now we will see the anonymous structs. They come in very handy. We will see how we create and use them.
package main
import (
"fmt"
)
func main() {
pizza := struct {
name string
}{
name: "Pizza",
}
fmt.Println(pizza) // prints {Pizza}
}
Fields of a Struct Object
Structs have fields. It can be named or unnamed. They can be assigned values or can remain empty and thus have zero-value. Let’s see how to initialize and use them.
1. Named fields in a struct
Named fields are those whose name has been declared in the struct type declaration. Below is an example.
type Food struct {
name string // this field has name
quantity int // ...
}
2. Anonymous fields in a struct
Anonymous fields are those whose type is declared only. In the example, we can see that any type can be used inside the struct. But this can create ambiguity and may result in a problem as you will see in the code.
package main
import (
"fmt"
)
// none of the fields are named
// these are anonymous fields
// Throws error because of ambiguity
// There are two string fields to choose from
// p.string makes no sense to the compiler
// type Painting struct {
// string // painting's name
// string // artist's name
// }
type Painting struct {
string // painting name
Artist // artist
}
type Artist struct {
string
}
func main() {
var p Painting
p.string = "Starry Night"
// p.string = "Van Gogh" // it will throw an error
// "ambiguous selector p.string"
p.Artist.string = "Van Gogh"
fmt.Println(p) // prints {Starry Night {Van Gogh}}
}
3. Functions as a field
Structs can have functions as their field. Below is the code showing the usage of function inside a struct.
import (
"fmt"
)
// declare function type
type FoodNameGetter func(string) string
type Food struct {
name string
getter FoodNameGetter // declare function
}
func main() {
pizza := Food{
name: "Pizza",
getter: func(name string) string { // declare function body
return "This is " + name + "."
},
}
fmt.Println(pizza.getter(pizza.name)) // prints "This is Pizza."
}
Accessing fields of a Struct
Accessing fields of the struct are really simple. We use the dot operator for that. When a nested structure is there we use dot inside the nested struct as well.
// declaration
type Car struct {
name string
cost int
}
var c Car = Car{"Mercedes", 3500000}
// accessing
carMake := c.name
carPrice := c.cost
Now, for a nested struct, we can do like this:
package main
import (
"fmt"
)
type User struct {
name string
}
type Service struct {
name string
user User
}
func main() {
google := Service{
name: "Google",
user: User{
name: "John Doe",
},
}
// accessing from nested struct
fmt.Println(google.user.name) // prints "John Doe"
}
Promoted fields
When we use an anonymous struct inside another struct, all the fields from the anonymous struct becomes accessible from the outer struct as if it is a part of it. These fields are called promoted fields.
package main
import (
"fmt"
)
type Person struct {
name string
}
type StoreKeeper struct {
Person
}
func main() {
var p = StoreKeeper{}
p.Person = Person{"Jane Doe"}
// access the field as normal field
fmt.Println(p.name) // prints "Jane Doe"
}
Using pointers of struct
We can create pointers of a struct using the address-of operator(&). Here is an example showing just that.
package main
import (
"fmt"
)
type Student struct {
name string
}
func main() {
ptrStudent := &Student{name: "John"}
fmt.Println(ptrStudent) // prints &{John}
}
We can use new() function to get a pointer of that struct.
Comparing Structs
The structs can be compared if they have the same values in the same fields. Here is an example.
package main
import (
"fmt"
)
type Student struct {
name string
}
func main() {
s1 := Student{"John"}
s2 := Student{"John"}
if(s1 == s2) {
fmt.Println("They are equal")
} else {
fmt.Println("They are not equal")
}
// output: "They are equal"
}
Array of Structs
Now we will see how to use structs in arrays. It is pretty simple and straightforward.
1. Declaring and initializing an Array of Structs
We simply declare an array with the type of that struct.
var arrayOfStruct []StructName // declaration
2. Inserting values in an Array of Structs
Use append function which returns the slice after insertion.
package main
import (
"fmt"
)
type Student struct {
name string
}
func main() {
// declare array
var students []Student
s := Student{"Kate"}
kate := append(students, s)
fmt.Println(kate) // [{Kate}]
}
Or, we can simply use indexing like this.
students[1] = Student{"Peter"}
This is how we can use structs in Go for various purposes.