Introduction to Golang - structure

What is a structure?

A structure is a user-defined type that represents a collection of several fields. Sometimes data should be integrated rather than disconnected. In this case, you can use a structure.
For example, an employee has three attributes: firstName, lastName and age, and it is reasonable to combine these attributes in one structure employee.
Declaration of structure

type Employee struct {
    firstName string
    lastName  string
    age       int
}

In the above code fragment, a structure type Employee is declared, which has three fields: firstName, lastName and age. By declaring fields of the same type on the same line, the structure can become more compact. In the above structure, firstName and lastName belong to the same string type, so this structure can be rewritten as:

type Employee struct {
    firstName, lastName string
    age, salary         int
}

The above structure Employee is called Named Structure. We created a new type called Employee, which can be used to create structure variables of Employee type.
You can also declare a structure without declaring a new type. Such a structure type is called an Anonymous Structure.

var employee struct {
    firstName, lastName string
    age int
}

The above code snippet creates an anonymous structure employee.
Create a named structure
Through the following code, we define a named structure Employee.

package main
import (  
    "fmt"
)
type Employee struct {  
    firstName, lastName string
    age, salary         int
}
func main() {
    //creating structure using field names
    emp1 := Employee{
        firstName: "Sam",
        age:       25,
        salary:    500,
        lastName:  "Anderson",
    }
    //creating structure without using field names
    emp2 := Employee{"Thomas", "Paul", 29, 800}
    fmt.Println("Employee 1", emp1)
    fmt.Println("Employee 2", emp2)
}

In line 7 of the above program, we create a named structure Employee. On line 15, we define the structure variable emp1 by specifying the value of each field name. The order of field names does not have to be the same as when declaring struct types. Here, we changed the position of lastName and moved it to the end. There will be no problem doing so.
In line 23 of the above program, we omitted the field name when defining emp2. In this case, you need to ensure that the order of field names is the same as that when declaring the structure.
The program will output:

Employee 1 {Sam Anderson 25 500}
Employee 2 {Thomas Paul 29 800}

Create anonymous structure

package main
import (
    "fmt"
)
func main() {
    emp3 := struct {
        firstName, lastName string
        age, salary         int
    }{
        firstName: "Andreah",
        lastName:  "Nikola",
        age:       31,
        salary:    5000,
    }
    fmt.Println("Employee 3", emp3)
}

In line 3 of the above program, we define an anonymous struct variable emp3. As mentioned above, this structure is called anonymous because it just creates a new structure variable em3 without defining any structure type.

The program outputs:

Employee 3 {Andreah Nikola 31 5000}

Zero Value of structure
When a defined structure is not explicitly initialized, its fields are set to zero by default.

package main
import (  
    "fmt"
)
type Employee struct {  
    firstName, lastName string
    age, salary         int
}
func main() {  
    var emp4 Employee //zero valued structure
    fmt.Println("Employee 4", emp4)
}

The program defines emp4, but does not initialize any values. Therefore, firstName and lastName are assigned the zero value of string (""). age and salary are assigned to the zero value of int (0). The program will output: employee 4 {0}
Of course, you can also specify initial values for some fields and ignore others. In this way, the ignored field name is assigned a value of zero.

package main
import (  
    "fmt"
)
type Employee struct {  
    firstName, lastName string
    age, salary         int
}
func main() {  
    emp5 := Employee{
        firstName: "John",
        lastName:  "Paul",
    }
    fmt.Println("Employee 5", emp5)
}

In lines 14 and 15 of the above program, we initialize firstName and lastName, but age and salary are not initialized. Therefore, age and salary are assigned zero values. The program will output: employee 5 {John Paul 0}

Access the fields of the structure

The dot operator is used to access the fields of the structure.

package main
import (  
    "fmt"
)
type Employee struct {  
    firstName, lastName string
    age, salary         int
}
func main() {  
    emp6 := Employee{"Sam", "Anderson", 55, 6000}
    fmt.Println("First Name:", emp6.firstName)
    fmt.Println("Last Name:", emp6.lastName)
    fmt.Println("Age:", emp6.age)
    fmt.Printf("Salary: $%d", emp6.salary)
}

emp6.firstName in the above program accesses the field firstName of the structure emp6. The program outputs:

First Name: Sam  
Last Name: Anderson  
Age: 55  
Salary: $6000

You can also create a struct with a zero value and assign values to each field later.

package main
import (
    "fmt"
)
type Employee struct {  
    firstName, lastName string
    age, salary         int
}
func main() {  
    var emp7 Employee
    emp7.firstName = "Jack"
    emp7.lastName = "Adams"
    fmt.Println("Employee 7:", emp7)
}

In the above program, we define emp7, and then assign values to firstName and lastName. The program outputs:
Employee 7: {Jack Adams 0 0}

Pointer to structure

You can also create pointers to structures.

package main
import (  
    "fmt"
)
type Employee struct {  
    firstName, lastName string
    age, salary         int
}
func main() {  
    emp8 := &Employee{"Sam", "Anderson", 55, 6000}
    fmt.Println("First Name:", (*emp8).firstName)
    fmt.Println("Age:", (*emp8).age)
}

In the above program, emp8 is a pointer to the structure Employee. (* emp8).firstName means to access the firstName field of the structure emp8. The program outputs:

First Name: Sam
Age: 55

The Go language allows us to use emp8.firstName instead of explicit dereference (* emp8).firstName when accessing the firstName field.

package main
import (  
    "fmt"
)
type Employee struct {  
    firstName, lastName string
    age, salary         int
}
func main() {  
    emp8 := &Employee{"Sam", "Anderson", 55, 6000}
    fmt.Println("First Name:", emp8.firstName)
    fmt.Println("Age:", emp8.age)
}

In the above program, we use emp8.firstName to access the firstName field, and the program will output:

First Name: Sam
Age: 55
Anonymous field
When we create a structure, a field can have only a type, not a field name. Such fields are called anonymous fields.
The following code creates a Person structure that contains two anonymous fields, string and int.

type Person struct {  
    string
    int
}

We next write a program using anonymous fields.

package main
import (  
    "fmt"
)
type Person struct {  
    string
    int
}
func main() {  
    p := Person{"Naveen", 50}
    fmt.Println(p)
}

In the above program, the structure Person has two anonymous fields. P: = Person {"Naveen", 50} defines a variable of type Person. The program outputs {Naveen 50}.

Although the anonymous field has no name, the name of the anonymous field defaults to its type. For example, in the Person structure above, although the fields are anonymous, Go defaults that these field names are their respective types. So the Person structure has two fields named string and int.

package main
import (  
    "fmt"
)
type Person struct {  
    string
    int
}
func main() {  
    var p1 Person
    p1.string = "naveen"
    p1.int = 50
    fmt.Println(p1)
}

In lines 14 and 15 of the above program, we access the anonymous field of the Person structure. We take the field type as the field name, which are "string" and "int" respectively. The output of the above program is as follows: {naveen 50}

Nested structures

The field of a structure may also be a structure. Such a structure is called a nested structure.

package main
import (  
    "fmt"
)
type Address struct {  
    city, state string
}
type Person struct {  
    name string
    age int
    address Address
}
func main() {  
    var p Person
    p.name = "Naveen"
    p.age = 50
    p.address = Address {
        city: "Chicago",
        state: "Illinois",
    }
    fmt.Println("Name:", p.name)
    fmt.Println("Age:",p.age)
    fmt.Println("City:",p.address.city)
    fmt.Println("State:",p.address.state)
}

The above structure, Person, has a field address, and address is also a structure. The program outputs:

Name: Naveen
Age: 50
City: Chicago
State: Illinois

Promoted Fields

If there is an anonymous structure type field in the structure, the field in the anonymous structure is called a promoted field. This is because the promoted field is like belonging to an external structure, which can be accessed directly by the external structure. I know this definition is very complex, so let's study the code directly to understand it.

type Address struct {  
    city, state string
}
type Person struct {  
    name string
    age  int
    Address
}

In the code snippet above, the Person structure has an anonymous field Address, and Address is a structure. Now the structure Address has two fields: city and state. Accessing these two fields is just like directly declared in Person, so we call them promotion fields.

package main
import (
    "fmt"
)
type Address struct {
    city, state string
}
type Person struct {
    name string
    age  int
    Address
}
func main() {  
    var p Person
    p.name = "Naveen"
    p.age = 50
    p.Address = Address{
        city:  "Chicago",
        state: "Illinois",
    }
    fmt.Println("Name:", p.name)
    fmt.Println("Age:", p.age)
    fmt.Println("City:", p.city) //city is promoted field
    fmt.Println("State:", p.state) //state is promoted field
}

In lines 26 and 27 of the above code, we use the syntax p.city and p.state to access the promoted fields city and state as if they were declared in structure P. The program outputs:

Name: Naveen  
Age: 50  
City: Chicago  
State: Illinois

Export structures and fields

If the structure name starts with an uppercase letter, it is the Exported Type that other packages can access. Similarly, if the field in the structure is capitalized, it can also be accessed by other packages.
Let's use the custom package and write a program to better understand it.
In the src directory of your Go workspace, create a folder called structures. In addition, create a directory computer in structs.
In the computer directory, save the following program in a file named spec.go.

package computer
type Spec struct { //exported struct  
    Maker string //exported field
    model string //unexported field
    Price int //exported field
}

In the above code fragment, a computer package is created with an exported structure type spec. Spec has two export fields Maker and Price, and one field model that is not exported. Next, we will import this package in the main package and use the spec structure.

package main
import "structs/computer"  
import "fmt"
func main() {  
    var spec computer.Spec
    spec.Maker = "apple"
    spec.Price = 50000
    fmt.Println("Spec:", spec)
}

The package structure is as follows:

src  
   structs
        computer
            spec.go
        main.go

In line 3 of the above program, we imported the computer package. In lines 8 and 9, we access the two export fields Maker and Price of the struct Spec. Execute the commands go install structures and workspacepath / bin / structures to run the program.

If we try to access the non exported field model, the compiler will report an error. Replace the contents of main.go with the following code.

package main
import "structs/computer"  
import "fmt"
func main() {  
    var spec computer.Spec
    spec.Maker = "apple"
    spec.Price = 50000
    spec.model = "Mac Mini"
    fmt.Println("Spec:", spec)
}

In line 10 of the above program, we tried to access the field model that was not exported. If you run this program, the compiler will generate an error: spec.model undefined (cannot refer to unexported field or method model).

Structures equality

Structure is a value type. If each of its fields is comparable, the structure is also comparable. If the corresponding fields of two structure variables are equal, the two variables are also equal.

package main
import (  
    "fmt"
)
type name struct {  
    firstName string
    lastName string
}
func main() {  
    name1 := name{"Steve", "Jobs"}
    name2 := name{"Steve", "Jobs"}
    if name1 == name2 {
        fmt.Println("name1 and name2 are equal")
    } else {
        fmt.Println("name1 and name2 are not equal")
    }
    name3 := name{firstName:"Steve", lastName:"Jobs"}
    name4 := name{}
    name4.firstName = "Steve"
    if name3 == name4 {
        fmt.Println("name3 and name4 are equal")
    } else {
        fmt.Println("name3 and name4 are not equal")
    }
}

In the above code, the structure type name contains two string types. Because strings are comparable, you can compare two structure variables of type name.
In the above code, name1 and name2 are equal, while name3 and name4 are not equal. The program outputs:
name1 and name2 are equal
name3 and name4 are not equal
If a structure contains fields that are not comparable, the structure variables are also not comparable.

package main
import (  
    "fmt"
)
type image struct {  
    data map[int]int
}
func main() {  
    image1 := image{data: map[int]int{
        0: 155,
    }}
    image2 := image{data: map[int]int{
        0: 155,
    }}
    if image1 == image2 {
        fmt.Println("image1 and image2 are equal")
    }
}

In the above code, the structure type image contains a field of map type. Since the map type is not comparable, image1 and image2 are also not comparable. If the program is run, the compiler will report an error: main.go:18: invalid operation: image1 == image2 (struct containing map[int]int cannot be compared).

Keywords: Go Back-end

Added by pyrodude on Tue, 26 Oct 2021 06:58:22 +0300