Day 3 of golang Learning Series: Learn array, slice, map, structure, pointer, function, interface type, channel

Time:2021-12-29

 

Following the second day of the golang Learning Series: variables, constants, data types and process statements, today we begin to learn the advanced types of data types: derived types.

Anyone who has studied Java knows that Java actually has eight basic types: byte, short, int, long, float, double, char and Boolean, but it has reference data types: string, array, set, class, interface, etc.

Golang is also divided into basic types (learned in the second day of golang Learning Series) and derived types (not called reference types). Derived types include the following: array type, slice type, map type, struct type, pointer type, function type, interface type and channel type.

 

1. Array type

An array is a sequence of elements with the same data type. Array has a fixed length defined in the declaration, so it cannot be extended beyond that length. Array declared as

var variable_name [SIZE] variable_type

Let’s take the code as an example

package main

import "fmt"

func main() {
    var city [5]string
    City [0] = "Beijing"
    City [1] = "Shanghai"
    City [2] = "Guangzhou"
    City [3] = "Shenzhen"
    City [4] = "Puyang"
    fmt.Println(city[0], city[1], city[2], city[3], city[4])
    fmt.Println(city)
}

Declare the variable city as an array of 5 strings and execute the output

However, you can also set the array entry when declaring the array. See the concise version

package main

import "fmt"

func main() {
    Var city = [5] string {"Beijing", "Shanghai", "Guangzhou", "Shenzhen", "Puyang"}
    fmt.Println(city[0], city[1], city[2], city[3], city[4])
    fmt.Println(city)
    
    //Simplified version
    Othercity: = [5] string {"Beijing", "Shanghai", "Guangzhou", "Shenzhen", "Puyang"}
    fmt.Printf("%q", othercity)
}

Output results

Even when you pass values, you can use ellipsis to use implicit length

package main

import "fmt"

func main() {
    Var city = [5] string {"Beijing", "Shanghai", "Guangzhou", "Shenzhen", "Puyang"}
    fmt.Println(city[0], city[1], city[2], city[3], city[4])
    fmt.Println(city)
    
    //Simplified version
    Othercity: = [5] string {"Beijing", "Shanghai", "Guangzhou", "Shenzhen", "Puyang"}
    fmt.Printf("%q\n", othercity)
    
     //Hermit length
    other_ city := [...] String {"Beijing", "Shanghai", "Guangzhou", "Shenzhen", "Puyang"}
    fmt.Printf("%q", other_city)
}

Output results

Print arrays in different ways

Notice how we use the FMT package with printf and how we use%q “verbs” to print each referenced element.

If we use the println or% s verbs, we will get different results

package main

import "fmt"

func main() {  
     //Print arrays in different ways
    other_ city := [...] String {"Beijing", "Shanghai", "Guangzhou", "Shenzhen", "Puyang"}
    fmt. Println ("print array differently")
    fmt.Println(other_city)
    fmt.Printf("%s\n", other_city)
    fmt.Printf("%q", other_city)
}

The output after execution is shown in the figure

 

Multidimensional array

You can also create multidimensional arrays. Example code:

package main

import "fmt"

func main() {
    var multi [2][3]int
    for i := 0; i < 2; i++ {
        for j := 0; j < 3; j++ {
            multi[i][j] = i + j
        }
    }
    fmt. Println ("2D array:", multi)
}

Output results

 

2. Slices type

Slice wrapped array can provide a more general, powerful and convenient interface for data sequence. With the exception of items with explicit dimensions (such as conversion matrices), most array programming in go is done using slices rather than simple arrays.

Slices contain references to the underlying array. If you assign one slice to another, both slices refer to the same array. If the function takes the slice parameter, the changes made to the elements of slice will be visible to the caller, which is similar to passing a pointer to the underlying array.

The slice points to an array of values and also contains the length. Slices can be resized because they are just wrappers on top of another data structure.

For example, [] t is a slice with elements of type t means that [] t is a slice with elements of type T.

Take a small example

package main

import "fmt"

func main() {
    Var city = [] string {"Beijing", "Shanghai", "Guangzhou", "Shenzhen", "Puyang"}
    fmt.Println(city[0], city[1], city[2], city[3], city[4])
    fmt.Println(city)
}

2.1} slicing

You can slice slices to create a new slice value that points to the same array. The expression is

slice[start:end]

Represents part of the element from start to END-1 inclusive.

Note: start and end are integers representing the index.

Let’s take a small demo

package main

import "fmt"

func main() {
    Var city = [] string {"Beijing", "Shanghai", "Guangzhou", "Shenzhen", "Puyang", "Zhengzhou"}
    
    fmt.Println(city)
	fmt.Println(city[1:4])

	// missing low index implies 0
	fmt.Println(city[:3])
	// [2 3 5]

	// missing high index implies len(s)
	fmt.Println(city[4:])
}

Output results

2.2 manufacturing slices

In addition to creating slices by passing values (slice text) immediately, you can also use the make keyword to create slices. You create an empty slice of a specific length and then populate each entry.

package main

import "fmt"

func main() {

	fmt. Println ("ready to create slices by making")
	cities := make([]string, 3)
	Cities [0] = "Zheng Zhou"
	Cities [1] = "Puyang"
	Cities [2] = "Anyang"
	fmt.Printf("%q", cities)
}

Output results:

It works by allocating a zeroed array and returning slices that reference the array.

 

2.3} attach to slice

You can append values to slices

package main

import "fmt"

func main() {
	//Attach to slice
	other_cities := []string{}
	other_ Cities = append (other_cities, "Puyang")
	fmt.Println(other_cities)
}

Look at the output

 

You can also attach multiple values to the slice at the same time. The sample code includes two cities, Zhengzhou and Puyang

package main

import "fmt"

func main() {
  
	//Attach multi value to slice
	other_cities := []string{}
	
	other_ Cities = append (other_cities, "Zheng Zhou", "Puyang")
	
	fmt.Println(other_cities)
}

Output results

 

You can even use an ellipsis to attach a slice to another slice

package main

import "fmt"

func main() {
	fmt. Println ("ready to create slices by making")
	cities := make([]string, 3)
	Cities [0] = "Zheng Zhou"
	Cities [1] = "Puyang"
	Cities [2] = "Anyang"
	fmt.Printf("%q\n", cities)
	
	//Attach slice to slice
	other_ Cities: = [] string {"Nanjing"}
	
	other_cities = append(other_cities,  cities...)
	
	fmt.Println(other_cities)
}

Output results

Note: ellipsis is a built-in feature of the language, which means that the element is a collection. We cannot attach elements of string type ([] string) to a string slice, only strings can be attached. However, an ellipsis (…) is used after the slice to indicate each element of the slice to be attached. Because we want to append a string from another fragment, the compiler will accept the operation because the types are matched.

You obviously cannot attach a slice of type [] int to another slice of type [] string.

 

2.4 # duplicate slices

Slices can also be copied. Here, we create one with other_ Cities are empty slices of the same length and copied from other_ Copy cities to copycities.

package main

import "fmt"

func main() {
   
	fmt. Println ("ready to create slices by making")
	cities := make([]string, 3)
	Cities [0] = "Zheng Zhou"
	Cities [1] = "Puyang"
	Cities [2] = "Anyang"
	fmt.Printf("%q\n", cities)
	
	//Attach multi value to slice
	other_ Cities: = [] string {"Nanjing"}
	
	other_cities = append(other_cities,  cities...)
	
	fmt.Println(other_cities)
	
	//Copy slice
    fmt. Println ("ready to create slice by copy")
    copycities := make([]string, len(other_cities))
    copy(copycities, other_cities)
    fmt.Println("copycities:", copycities)
}

Output results

2.5 slice length

You can use len to check the length of the slice at any time.

package main

import "fmt"

func main() {
    fmt. Println ("ready to create slices by making")
	cities := make([]string, 3)
	Cities [0] = "Zheng Zhou"
	Cities [1] = "Puyang"
	Cities [2] = "Anyang"
	fmt.Printf("%q\n", cities)
	
	//Attach multi value to slice
	other_ Cities: = [] string {"Nanjing"}
	
	other_cities = append(other_cities,  cities...)
	
	fmt.Println(other_cities)
	
	//Print slice length
	fmt.Println(len(cities))
	countries := make([]string, 42)
	fmt.Println(len(countries))
}

Output results

2.6} zero piece

The slice has a zero value of nil. The length and capacity of no slice is 0.

package main

import "fmt"

func main() {
	//Zero piece
	var temp []int
    fmt.Println(temp, len(temp), cap(temp))
    if temp == nil {
        fmt.Println("nil!")
    }
}

Output results

 

3. Map type

Map is an unordered set of key value pairs. The most important point of map is to quickly retrieve data through key. Key is similar to index and points to the value of data.

Map is a collection, so we can iterate it like iterating arrays and slices. However, the map is unordered, and we cannot determine its return order, because the map is implemented using a hash table.

package main

import "fmt"

func main() {
	users := map[string]int{
		"admin":       0,
		"donguangming":       1,
		"student":           2,
	}

	fmt.Printf("%#v", users)
}

Output results

 

When the above map is not used, you must use make (not new) to create a map before use. The nil map is empty and cannot be assigned to it.

package main

import "fmt"

type User struct {
	name string
	age int
	city string
}

var user map[string]User

func main() {

    //Create with make
	user = make(map[string]User)

	User ["DGM"] = user {"Dong Guangming", 99, "Nanjing"}
	fmt.Println(user["dgm"])
}

Output results

 

3.1} operation map

3.1. 1) insert or update elements in the map

m[key] = elem

3.1. 2. Query an element

elem = m[key]

3.1. 3. Delete an element

delete(m, key)

3.1. 4. Test whether the key exists and has a value

elem, ok = m[key]

Determines true if the key is in M. If not, OK is false and elem is the zero value of the map element type. Similarly, when reading from a map (if there is no key), the result is a zero value of the map element type.

To sum up, the code is as follows

package main

import "fmt"

type User struct {
	name string
	age int
	city string
}

var user map[string]User

func main() {
	user = make(map[string]User)
	//Assignment
	User ["DGM"] = user {"Dong Guangming", 99, "Nanjing"}
	fmt.Println("user:", user)
	//Inquiry
	fmt.Println(user["dgm"])

    //Delete
    delete(user, "dgm")
    fmt. Println ("at this time, user:", user)

    //Test key
    _, u := user["dgm"]
    fmt.Println("u:", u)

	var users = map[string]User{
	"DMG": {"Dong Guangming", 99, "Nanjing"},
	"Dongguangming": {"Dong Guangming", 88, "Nanjing"},
    }
    
	fmt.Println(users)
}

Output results

 

3.2} map cycle

How to iterate on a map? You can use the loop scope to iterate over the map, because the map is an unordered collection, so the value of this loop may be different.

package main

import "fmt"

type User struct {
	name string
	age int
	city string
}

var user map[string]User

func main() {
	
	var users = map[string]User{
	"DMG": {"Dong Guangming", 99, "Nanjing"},
	"Dongguangming": {"Dong Guangming", 88, "Nanjing"},
    }
    
	fmt.Println(users)
	
	/*Use the key to output the map key value*/
    for username := range users {
        fmt. Println (username, "user =", users [username])
    }
}

Output results

 

4. Pointer type

Anyone who has studied C (the first programming language at school is c) knows that the pointer is the place where the value memory address is stored. The pointer is defined by * and the pointer is defined according to the data type. Go also plays this way. The declaration format is as follows

var var_name *var-type

Var type is pointer type, VAR_ Name is the pointer variable name, and the * sign is used to specify that the variable is used as a pointer.

The & operator can be used to obtain the address of the variable. such as

var ap *int

a := 12
ap = &a

The value pointed to by the pointer can be accessed using the * operator, as shown in the following example

package main

import "fmt"

func main() {
   Var age int = 99 / * declare actual variable*/
   Var IP * int / * declare pointer variables*/

   IP = & age / * storage address of pointer variable*/

   fmt. Printf ("the address of the age variable is:% X \ n", & age)

   /*Storage address of pointer variable*/
   fmt. Printf ("pointer address stored in IP variable:% X \ n", IP)

   /*Accessing values using pointers*/
   fmt. Printf ("* IP pointer variable value:% d \ n", * IP)
}

Execute the above code and output the result

 

4.1} null pointer

When a pointer is defined and not assigned to any variable, its value is nil, and nil pointer is also called null pointer.

Like null, none, nil and null in other programming languages, nil conceptually refers to zero or null values.

A pointer variable is usually abbreviated as PTR. Null pointer judgment method:

If (PTR! = Nil) / * PTR is not a null pointer*/
If (PTR = = Nil) / * PTR is a null pointer*/

To sum up, the example code is as follows

package main

import "fmt"

func main() {
   Var age int = 99 / * declare actual variable*/
   Var PTR * int / * declare pointer variable*/
   var other_ PTR * int / * declare pointer variable*/
   
   PTR = & age / * storage address of pointer variable*/
   fmt. Printf ("the address of the age variable is:% X \ n", & age)

   /*Accessing values using pointers*/
   fmt. Printf ("* PTR pointer variable value:% d \ n", * PTR)
   
   if(ptr != nil)  {
      /*PTR is not a null pointer*/  
      fmt. Printf ("pointer address stored in PTR pointer variable:% X \ n", PTR)
   }  
   if(other_ptr == nil)  {
      /* other_ PTR is a null pointer*/
      fmt. Printf ("other_ptr pointer address stored in pointer variable:% X \ n", other_ptr)
   }  
}

Output results

 

4.2 pointer array

Pointer array: simply put, it is an array. Each element in the array is a pointer. The number of bytes occupied by the array is determined by the array itself. It is short for “array of pointers”. The format is as follows

var ptr [MAX]* type;

PTR is an array of type pointers, so each element points to a value, but its value is a pointer.

package main

import "fmt"

const MAX int = 5

func main() {
  Var city = [Max] string {"Beijing", "Shanghai", "Guangzhou", "Shenzhen", "Puyang"}
   var i int
   var othercity [MAX]*string;

   for  i = 0; i < MAX; i++ {
      Othercity [i] = & City [i] / * string address assigned to pointer array*/
   }

   for  i = 0; i < MAX; i++ {
      fmt. Printf ("pointer array: index:% d value:% s memory address of value:% d \ n", I, * othercity [i], othercity [i])
   }
}

Output results

 

4.3 pointer of pointer

If a pointer variable stores the address of another pointer variable, the pointer variable is called the pointer variable pointing to the pointer.

When defining a pointer variable pointing to a pointer, the first pointer stores the address of the second pointer and the second pointer stores the address of the variable.

The declaration format of pointer variable pointing to pointer is as follows:

var ptr **type;

Indicates that the pointer variable pointing to the pointer is type. Two * signs are required to access the pointer variable value pointing to the pointer.

package main

import "fmt"

func main() {
  
   var age int
   var ptr *int
   var pptr **int

   age = 99

   /*Pointer PTR address*/
   ptr = &age
   /*Pointer PTR address*/
   pptr = &ptr

   /*Gets the value of PPTR*/
   fmt. Printf ("variable age =% d \ n", age)
   fmt. Printf ("pointer variable * PTR =% D, memory address is:% d \ n", * PTR, PTR)
   fmt. Printf ("pointer variable pointing to pointer * * PPTR =% D, memory address is:% d \ n", * PPTR, PPTR ")
}

Output results

 

4.4} create pointer through new function

Go supports the creation of pointers through the new function, which takes the type as a parameter and returns a pointer to the newly allocated zero value of the type passed as a parameter.

package main

import "fmt"

func main() {
   //Create pointer through new function
    size := new(int)
    fmt. Printf ("default value of size =% D, type:% T, address:% v \ n", * size, size, size ")
    *size = 99
    fmt. Println ("the new value after change is:", * size ")
    
}

Output results

 

4.5 pointer parameters

You can pass a pointer to a function

package main

import "fmt"

func changeValue(val *int) {  
    *val = 66
}

func main() {
   var age int
   var ptr *int
   var pptr **int

   age = 99

   /*Pointer PTR address*/
   ptr = &age
   /*Pointer PTR address*/
   pptr = &ptr

   /*Gets the value of PPTR*/
   fmt. Printf ("variable age =% d \ n", age)
   fmt. Printf ("pointer variable * PTR =% D, memory address is:% d \ n", * PTR, PTR)
   fmt. Printf ("pointer variable pointing to pointer * * PPTR =% D, memory address is:% d \ n", * PPTR, PPTR ")
   
   //Function call
   changeValue(ptr)
   fmt. Printf ("changed value of variable age =% d \ n", age)

   //Create pointer through new function
    size := new(int)
    fmt. Printf ("default value of size =% D, type:% T, address:% v \ n", * size, size, size ")
    *size = 99
    fmt. Println ("the new value after change is:", * size ")
}

Output results

Pay special attention to the difference between the two parameters

func change(val int) {  
    val = 88
}

func changeValue(val *int) {  
    *val = 66
}

 

 

5. Function type

Functions are basic blocks of code used to perform a task.

The go language has at least one main() function.

You can divide different functions by functions. Logically, each function performs a specified task.

The function declaration tells the compiler the name, parameters, and return type of the function. The format is as follows

func function_name( [parameter list] ) [return_types] {
   //Function body
}

Function definition resolution:

  • Func: functions are declared starting with the keyword func
  • function_ Name: function name. Function name and parameter list together form a function signature.
  • Parameter list: parameter list. The parameter is like a placeholder. When the function is called, you can pass the value to the parameter. This value is called the actual parameter. The parameter list specifies the parameter type, order, and number. Parameters are optional, that is, functions can also contain no parameters.
  • return_ Types: return type. The function returns a list of values. return_ Types is the data type of the column value. Some functions do not need a return value. In this case, return_ Types is not required.
  • Function body: a collection of code defined by a function.

5.1} parameterless function with no return value

package main

 import (
     "fmt"
 )

func hello(){
  fmt.Println("Hello World")
}

 func main() {
    fmt. Println ("function started")
    hello()
 }

5.2} function with parameter and no return value

package main

 import (
     "fmt"
 )

func hello(message string){
  fmt.Println(message)
}

 func main() {
    fmt. Println ("function started")
    hello("hello world")
 }

5.3} nonparametric function with return value

package main

 import (
     "fmt"
 )

func hello() string {
  return "Hello world"
}


 func main() {
    fmt. Println ("function started")
    greeting := hello()
    fmt.Println(greeting)
 }

5.4} functions with parameters and return values

package main

 import (
     "fmt"
 )

func hello(message string) string {
  return message
}


 func main() {
    fmt. Println ("function started")
    greeting := hello("hello world")
    fmt.Println(greeting)
 }

5.5} multi parameter multi return value function

package main

 import (
     "fmt"
 )

func hello(name string, age int) (string, int) {
  return name, age
}


 func main() {
    fmt. Println ("function started")
    Name, age: = hello ("Dong Guangming", 99)

   fmt.Printf("name=%s, age = %d\n", name,age )
 }

5.6} predefined function with return value in function

package main

 import (
     "fmt"
 )

func hello() (message string) {
  message = "hello world!"

  return
}

 func main() {
    fmt. Println ("function started")
    greeting := hello()

   fmt.Printf(greeting)
 }

Message is defined as the return variable. Therefore, the defined variable message will be returned automatically without having to be defined in the last return statement.

5.7} functions that discard return values

package main

 import (
     "fmt"
 )

func hello() (string, string) {
  return "hello world!", "hahaha"
}

 func main() {
    fmt. Println ("function started")
   greeting, _ := hello()


   fmt.Printf(greeting)
 }

5.8 pointer transfer function

package main

 import (
     "fmt"
 )

func change(name *string) {
  *name = "dongguangming"
}


 func main() {
    fmt. Println ("function started")
    Name: = "Dong Guangming"
    fmt.Println(name)

    change(&name)
    fmt.Printf(name)
 }

It changes the original value, which is easy to understand

5.9 variable parameter function

You can use the… Operator in golang to pass an array, or you can use the same… Operator to receive parameters.

package main

 import (
     "fmt"
 )

func print(items ...string) {
  for _, v := range items {
    fmt.Println(v)
  }
}

 func main() {
    fmt. Println ("function started")
 
    Print ("Dong Guangming", "Dong Guangming", "DMG")

    list := []string{"Hello", "World"}
    print(list...) // An array argument
 }

Actual output results

 

5.10 anonymous functions

Functions without names are called anonymous functions

package main

 import (
     "fmt"
 )

 func main() {
    fmt. Println ("function started")
   
    func () {
      fmt. Println ("I am an anonymous function")
    } ()
 }

 

6. Structure

In the world of golang, there is no concept of class like Java, but it has a structure like C language, struct.

A structure is a typed collection of different fields. A structure is used to group data together.

For example, if we want to group user type data, define a user attribute, which can include name, age, gender and city. You can define the structure using the following syntax

package main

import "fmt"

type User struct {
     name   string
     age    int
     gender string
     city   string
 }

func main() {
   fmt. Println ("structure started")

   User: = user {Name: "Dong Guangming", age: 31, gender: "man", city: "Nanjing"}

   fmt.Println(user)
   
   //Abbreviation
   U: = user {"Dong Guangming", 31, "man", "Nanjing"}

   fmt.Println(u)
   
    //Access by pointer
   U1: = & user {"Dong Guangming", 31, "man", "Nanjing"}

   fmt.Println(u1.name)
}

Output results

 

6.1} method

Method is a special function with a receiver. The recipient can be a value or a pointer.

package main

import "fmt"

type User struct {
     name   string
     age    int
     gender string
     city   string
 }

//Method definition
 func (u *User) describe() {
     fmt. Printf ("% v is% v years old this year \ n", u.name, u.age)
 }
 //Pointer parameter
 func (u *User) setAge(age int) {
     u.age = age
 }
 //Value parameter
 func (u User) setName(name string) {
     u.name = name
 }
 
func main() {
   fmt. Println ("structure started")

   User: = user {Name: "Dong Guangming", age: 31, gender: "man", city: "Nanjing"}

   fmt.Println(user)
   
   user.describe()
   user.setAge(99)
   fmt.Println(user.age)
   user.setName("dongguangming")
   fmt.Println(user.name)
   user.describe()

}

Output results

As you can see, you can now use the dot operator user Describe calls the method. Note that the receiver is a pointer. Using pointers, we pass a reference to the value, so if you make any changes to the method, it will be reflected in the receiver user. It also does not create a new copy of the object, saving memory.

Note that in the above example, the value of age has changed and the value of name has not changed because the method setname is the receiver type and setage is the pointer type.

 

6.2} structure domain field export

If the field name starts with an uppercase letter, code outside the package that defines the structure can read and write it. If the field starts with a lowercase letter, only the code in the structure package can read and write the field.

package main

import "fmt"

type User struct {
    Name string
    Type string

    password string
}

func main() {
    u := User{
        Name: "Dong Guangming",
        Type: "1",

        password: "secret",
    }
    fmt. Println (u.name, "level:", u.type)
    fmt. Println ("password is:", u.password)
}

In the same package, we can access these fields. As shown in this example, since main is also in the main package, it can refer to u.password and retrieve the values stored therein. Usually, there are fields in the structure that are not exported, and they are accessed through the exported method. It is similar to the access permission private domain and public access method in Java.

The above program output results

Dong Guangming level: 1
The password is: secret

6.3 creating anonymous structures

Anonymous only creates new structure variables, and does not define any new structure types.

package main

import "fmt"


func main() {
  
   emp := struct {
        firstName, lastName string
        age, salary         int
    }{
        Firstname: "Dong",
        LastName: "Guangming",
        age:       31,
        salary:    5000,
    }

    fmt. Println ("employee", EMP)
}

In the above program code, an anonymous structure variable EMP is defined. As we have mentioned, this structure is called anonymous structure because it only creates a new structure variable EMP without defining any new structure types.

Output results

Employee {Dong Guangming 31 5000}

6.4 nested structures

A structure may contain a field, which in turn is a structure. These types of structures are called nested structures.

For example, when we often shop online, we fill in the order receiving address (home, company, deposit point)

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 = "Dong Guangming"
    p.age = 31
    p.address = Address {
        City: "a street in Nanjing",
        State: "first receiving address",
    }
    fmt. Println ("Name:", p.name)
    fmt. Println ("age:", p.age)
    fmt. Println ("shipping address:", p.address. City)
    fmt. Println ("first:", p.address. State)
}

The person structure in the above program has a field address, which is a structure.

 

6.5 pointer to structure

You can use the & operator to get a pointer to the structure

package main

import "fmt"

type User struct {
     name   string
     age    int
     gender string
     city   string
 }

func main() {
   fmt. Println ("structure started")

   User: = user {Name: "Dong Guangming", age: 31, gender: "man", city: "Nanjing"}

   fmt.Println(user)
   
    // Pointer to the user struct
	user_point := &user
	fmt.Println(user_point)

	// Accessing struct fields via pointer
	fmt.Println((*user_point).name)
	fmt.Println(user_point.name) // Same as above: No need to explicitly dereference the pointer

	user_point.age = 99
	fmt.Println(user_point)
}

As shown in the above example, go enables you to access the fields of a structure directly through a pointer.

Output results

 

6.6} structure is a value type

A structure is a value type, and when you assign a structure variable to another, a new copy of the structure is created and assigned. Similarly, when you pass a structure to another function, the function gets a copy of its own structure.

package main

import "fmt"

type User struct {
     name   string
     age    int
     gender string
     city   string
 }
 
func main() {
   fmt. Println ("structure started")

   User: = user {Name: "Dong Guangming", age: 31, gender: "man", city: "Nanjing"}
   user2 := user // A copy of the struct `user` is assigned to `user2`
   fmt.Println("user = ", user)
   fmt.Println("user2 = ", user2)
   
   //
   user2.name = "dongguangming"
   user2.age = 99
   user2. City = "Shanghai"
   fmt. Println ("\ nchange user2:")
   fmt.Println("user = ", user)
   fmt.Println("user2 = ", user2)
}

Output results

 

7. InterfaceInterfacetype

Go programming provides another data type called an interface, which represents a set of method signatures.

The struct data type implements the methods defined in the interface.

package main
 
import "fmt"
import "math"

type Shape interface {
   area() float64
}
 
type Rectangle struct{
   height float64
   width float64
}
 
type Circle struct{
   radius float64
}
 
func (r Rectangle) area() float64 {
    return r.height * r.width
}
 
func (c Circle) area() float64 {
    return math.Pi * math.Pow(c.radius, 2)
} 
 
func getArea(shape Shape) float64{
 
    return shape.area()
 
}

func main() {
   fmt. Println ("interface started")
   rect := Rectangle{20, 50}
   circ := Circle{4}
 
   fmt. Println ("rectangular area =" ", getarea (rect))
   fmt. Println ("area of circle =", getarea (CIRC))
}

Output results

 

8. Channels type

A channel is a typed pipe, and you can use the channel operator

Channel // send value to channel
Value: = // query from the channel and assign the value to value

Note: the data flows in the direction of the arrow

Similar to other data types, channels must be created before use, and their initial value is nil. The syntax format for creating a channel is as follows:

var c1 chan [value type]
c1 = make([channel type] [value type], [capacity])

  • [value type] defines the type of data transmitted in the channel.
  • [channel type] defines the type of channel. There are three types:
    • “Chan” is readable and writable – “Chan int” indicates the channel for reading and writing int data
    • “chan
  • [capacity] is an optional parameter, which defines the buffer in the channel. If it is not filled in, the channel has no buffer by default. For a channel without buffer, the sending and receiving of messages must be completed at the same time, otherwise it will cause blocking and prompt deadlock error.

For example, we want to create a channel C1 with a read-write int type and a buffer length of 100, as follows:

var c1 chan int
c1 = make(chan int, 100)

Through this channel, we can send int type data. We can send and receive data in this channel

package main

 import "fmt"

 func main() {
     ch := make(chan int)
     go func() { ch 31 }()
     age :=

Output results:

The receiver channel waits until the sender sends data to the channel.

 

8.1 # one way channel

In some cases, we want to receive data through the channel but not send data. For this purpose, we can also create a one-way channel. Let’s take a simple example:

package main

 import (
     "fmt"
 )

 func main() {
     ch := make(chan string)
     go sc(ch)
     fmt.Println(func sc(ch chanstring) {
     Ch "Hello, Dong Guangming"
 }

In the above example code, SC is a go coroutine, which can only send messages to the channel, but cannot receive messages.

Execute code output results

$go run main.go
Hello, Dong Guangming

 

8.2} cache channel(Buffered channel

You can create a buffered channel in golang. For buffered channels, messages sent to the channel are blocked if the buffer is full. Let’s look at a small example

package main

 import "fmt"

 func main() {
     ch := make(chan string, 2)
     ch "hello"
     ch "world"
     
     ch "!!!" //  If the maximum buffer value is exceeded, an error will be reported
     fmt.Println(

In fact, if the maximum buffer value is exceeded, an error will be reported

What should I do? Fortunately, there are the following solutions

package main

 import "fmt"

 func main() {
     ch := make(chan string, 2)
     ch "hello"
     ch "world"

     //Create anonymous function
     function := func(name string) { ch //
     Go function ("Dong Guangming") 
     go function("donguangming") 
     go function("dgm") 
     go function("dgmdgm") 
     go function("3dgm") 

     fmt.Println(

Output results

 

 

Test results

golang测验结果得分

 

Conclusion: golang is a comprehensive programming language. Fortunately, I have done Java, Python and JavaScript development before, and learned C language (the first programming language) at school. Therefore, I learned golang very quickly, and very few of them are unique to golang itself.

In a word: golang is a mixture of several languages, plus its own characteristics. If you don’t consider the language itself, you will feel like writing C, sometimes like writing python, and writing functions like variants of functions in JavaScript.

 

reference resources:

  1.  Golang Tutorial — from zero to hero  https://milapneupane.com.np/2019/07/06/learning-golang-from-zero-to-hero/

  2. Understanding Maps in Go   https://www.digitalocean.com/community/tutorials/understanding-maps-in-go

  3. Golang Maps  https://www.geeksforgeeks.org/golang-maps/

  4. Golang Tutorial – Learn Golang by Examples https://www.edureka.co/blog/golang-tutorial/#map

  5. The anatomy of Slices in Go  https://medium.com/rungo/the-anatomy-of-slices-in-go-6450e3bb2b94

  6. GoLang Tutorial – Structs and receiver methods – 2020 https://www.bogotobogo.com/GoLang/GoLang_Structs.php

  7. Golang Cheatsheet: Functions https://ado.xyz/blog/golang-cheatsheet-functions/

  8. Ultimate Guide to Go Variadic Functions  https://medium.com/m/global-identity?redirectUrl=https%3A%2F%2Fblog.learngoprogramming.com%2Fgolang-variadic-funcs-how-to-patterns-369408f19085

  9. Golang Methods Tutorial with Examples https://www.callicoder.com/golang-methods-tutorial/

  10. Go Best Practices: Should you use a method or a function? https://flaviocopes.com/golang-methods-or-functions/

  11. Methods that satisfy interfaces in golang https://suraj.io/post/golang-methods-interfaces/

  12.  Pass by pointer vs pass by value in Go https://goinbigdata.com/golang-pass-by-pointer-vs-pass-by-value/

  13. Go Data Structures: Interfaces https://research.swtch.com/interfaces

  14. How to Define and Implement a Go Interface https://code.tutsplus.com/tutorials/how-to-define-and-implement-a-go-interface–cms-28962

  15. Methods and Interfaces in Go https://dev-pages.info/golang-interfaces/

  16. Go (Golang) – understanding the object oriented features with structs, methods, and interfaces https://unixsheikh.com/articles/go-understanding-the-object-oriented-features-with-structs-methods-and-interfaces.html#interfaces-in-go

  17. Understand the channel type of golang https://studygolang.com/articles/25805

  18. Anatomy of Channels in Go – Concurrency in Go  https://medium.com/rungo/anatomy-of-channels-in-go-concurrency-in-go-1ec336086adb