Non zero basic accelerated Go language_ Basic chapter

Posted by leebo on Sat, 05 Mar 2022 01:29:52 +0100

Non zero basic accelerated Go language_ Basic chapter

There is no need to install the Go environment here. It is recommended that you prepare the Goland + Go environment

Here are the features of all languages. See what's different about Go

Plastic subdivision

In Go language, integer types can be subdivided into 10 types

int stands for signed and can represent negative numbers. uint stands for unsigned and can only represent positive numbers.

Structure package

array

array define

An array is a sequence of elements of a specific type with a fixed length. An array can consist of zero or more elements. Because the length of arrays is fixed, arrays are rarely used directly in Go language. It is generally replaced by slicing, that is, the List structure in Java

// [3] 3 in represents the number and capacity of elements in the array
var arr [3]int
arr[0] = 1
arr[1] = 2
arr[2] = 3

Define and use

// The first method
var arr [3]int = [3]int{1,2,3}

// The second method
arr := [3]int{1,2,3}

section

Like an array, Slice is also a container that can hold several elements of the same type. Unlike arrays, the length of their values cannot be determined by the Slice type. Each Slice value takes the array as its underlying data structure. We also call such an array the underlying array of slices

When you do not specify the capacity during initialization, it is an array with dynamic capacity changes

The function of the slice append element is the append method:

func main() {
		//Initialize a slice
    myarr := []int{1}
    // Append an element
    myarr = append(myarr, 2)
    // Append multiple elements
    myarr = append(myarr, 3, 4)
    // Append a slice Indicates unpacking and cannot be omitted
    myarr = append(myarr, []int{7, 8}...)
    // Insert element in first position
    myarr = append([]int{0}, myarr...)
    // Insert a slice (two elements) in the middle
    myarr = append(myarr[:5], append([]int{5,6}, myarr[5:]...)...)

Dictionaries

A HashMap similar to Java is used to store key value pair elements.

Like HashMap, the key is required to be unique in order to support the Hash feature

When declaring a dictionary, you must specify the type of your key and value, and then use the map keyword to tell Go that it is a dictionary

map[KEY_TYPE]VALUE_TYPE

Three methods of declaring and initializing Dictionaries

// The first method
var scores map[string]int = map[string]int{"english": 80, "chinese": 85}

// The second method
scores := map[string]int{"english": 80, "chinese": 85}

// The third method
//map points to the memory space
scores := make(map[string]int)
scores["english"] = 80
scores["chinese"] = 85

It should be noted that if the first method is divided into multiple steps (declaration, initialization and re assignment), it is very different from the other two methods and will be relatively troublesome.

    // Declare a dictionary named score
    var scores map[string]int

    // The zero value of uninitialized score is nil, otherwise it cannot be assigned directly
    if scores == nil {
        // You need to use the make function to initialize it first
        scores = make(map[string]int)
    }

    // After initialization, you can assign values directly
    scores["chinese"] = 90
    fmt.Println(scores)
}

Impairment of circular access map

    scores := map[string]int{"english": 80, "chinese": 85}

		//Both keys and values are required
    for subject, score := range scores {
        fmt.Printf("key: %s, value: %d\n", subject, score)
    }
		//As long as the value
    for _, score := range scores {
        fmt.Printf("key: %s, value: %d\n", subject, score)
    }
		//Just key
    for subject, _ := range scores {
        fmt.Printf("key: %s, value: %d\n", subject, score)
    }

Pointer

In Java, the transfer of basic data type is value transfer, and the transfer of reference type is address transfer. It is similar in Go, but there are still some differences in operation: the pointer / reference in Go is an improvement on C + +

When we define a variable name

var name string = "Go"

At this time, name is the variable name, which is just a label in the programming language that is convenient for programmers to write and understand code.

When we access this tag, we will return the value stored in the memory address it points to: "Go".

For some needs, we will assign this memory address to another variable name, usually called ptr (short for pointer), and this variable is called pointer variable.

In other words, the value of the pointer variable (a label) is the pointer, that is, the memory address, just like the reference variable in Java

According to the value pointed to by the variable, whether it is the memory address or the value in the memory, I divide the variable into two types:

  • Common variable: save the data value itself
  • Pointer variable: the memory address of the stored value belongs to the reference type

Create pointer

There are three ways to create pointers

1. First define the corresponding variable, then obtain the memory address through the variable and create the pointer

//
// Define common variables
aint := 1
// Define pointer variables
ptr := &aint

2. First create the pointer, allocate the memory, and then write the corresponding value to the memory address pointed to by the pointer.

// Create pointer
astr := new(string)
// Assign value to pointer
*astr = "Go"

3. First declare a pointer variable, and then get the memory address from other variables and assign it

aint := 1
var bint *int  // Declare a pointer
bint = &aint   // initialization

In the above three codes, the operation of the pointer is inseparable from these two symbols:

  • &: get the memory address from a common variable
  • *: when * is on the right side of the assignment operator (=), the value of the variable is obtained from a pointer variable. When * is on the left side of the assignment operator (=), it refers to the variable pointed to by the pointer

Process control

The process control methods in Go are quite rich. There are as follows:

  • if - else conditional statement
  • switch - case selection statement
  • for - range loop statement
  • goto unconditional jump statement
  • defer execution delay

Conditional model

if Condition 1 {
  Branch 1
} else if Condition 2 {
  Branch 2
} else if condition ... {
  branch ...
} else {
  branch else
}

Needless to say, I can speak any language

It should be noted here that after the if of go, it is allowed to receive the expression to judge the returned value, which is a common writing method

    if age := 20;age > 18 {
        fmt.Println("I'm an adult")
    }

Swith-case

Like other languages

switch expression {
    case Expression 1:
        Code block
    case Expression 2:
        Code block
    case Expression 3:
        Code block
    case Expression 4:
        Code block
    case Expression 5:
        Code block
    default:
        Code block
}

for

There is only one loop of go: for

for [condition |  ( init; condition; increment ) | Range]
{
   statement(s);
}

Based on its model, there is an equivalent writing method of while

a := 1
for a <= 5 {
    fmt.Println(a)
    a ++
}

Conventional for writing

    for i := 1; i <= 5; i++ {
        fmt.Println(i)
    }

Infinite loop writing

for {
    Code block
}

// Equivalent to
for ;; {
    Code block
}

[common] set traversal writing method for range

Traversing an iteratable object is a very common operation. You can use for range in Go

range can be followed by array, slice, string, etc

Because range will return two values: index and data, if you can't use the index in the following code, you need to use it_ express

    myarr := [...]string{"world", "python", "go"}
    for _, item := range myarr {
        fmt.Printf("hello, %s\n", item)
    }

Note: if you use a variable to receive, you will receive an index

go to unconditional jump

goto can break the original code execution order and directly jump to a line to execute the code

    goto flag
    fmt.Println("B")
flag:
    fmt.Println("A")

The execution result will not output B, but only A

goto statements are usually used in conjunction with conditional statements. It can be used to realize conditional transfer, form a loop, jump out of the loop body and other functions, similar to Java break and continue keywords

    i := 1
    for {
        if i > 5 {
            goto flag
        }
        fmt.Println(i)
        i++
    }
flag:

Using goto to realize the effect of type continue

    i := 1
flag:
    for i <= 10 {
        if i%2 == 1 {
            i++
            goto flag
        }
        fmt.Println(i)
        i++
    }

Note: there must be no variable declaration between goto statement and label, otherwise compilation error will occur.

defer deferred statement

This is a unique feature of Go. It allows the function to execute defer and jump after execution. For example, our program uses some resources in the function and can use defer when closing, such as returning database connection resources

func myfunc() {
    fmt.Println("B")
}

func main() {
    defer myfunc()
    fmt.Println("A")
}

Using defer only delays calling the function. At this time, the variables passed to the function should not be affected by subsequent programs.

For example, here's an example

import "fmt"

func main() {
    name := "go"
    defer fmt.Println(name) // Output: go

    name = "python"
    fmt.Println(name)      // Output: python
}

The output is as follows. It can be seen that name is reassigned to python, and the unassigned variable value is still used in subsequent calls to defer. Fortunately, here in defer, all this is the same as taking a snapshot.

python
go

If defer is followed by an anonymous function, the situation will be different. Defer will get the last variable value

package main

import "fmt"


func main() {
    name := "go"
    defer func(){
    fmt.Println(name) // Output: python
}()
    name = "python"
    fmt.Println(name)      // Output: python
}

Note: defer is called after return

Abnormal mechanism

Programming languages generally have exception capture mechanisms. In Java, throw / catch and try statements are used to throw and capture exceptions

In Golang, there are many conventional errors that can be alarmed in advance during the compilation stage, such as syntax errors or type errors, but some errors can only occur after the program runs, such as array access out of bounds, null pointer reference, etc. These runtime errors will cause the program to exit.

Of course, it can also be ourselves that can trigger the shutdown and exit of the program. For example, after inspection and judgment, when the current environment cannot meet the expected conditions of our program (for example, the specified listening port of a service is occupied by other programs), we can manually trigger panic to stop the program from running.

Manually triggering downtime is a very simple thing. You only need to call the built-in function panic, just like this

func main() {
    panic("crash")
}

When an exception occurs, you sometimes have to catch it

This leads to another built-in function - recover, which allows the program to regenerate after downtime.

However, there is a condition for the use of recover, that is, it must be in the defer function to take effect. Under other scopes, it does not work.

This is a simple example:

import "fmt"

func set_data(x int) {
    defer func() {
        // recover() can print the captured panic information
        if err := recover(); err != nil {
            fmt.Println(err)
        }
    }()

    // Deliberately create array out of bounds and trigger panic
    var arr [10]int
    arr[x] = 88
}

func main() {
    set_data(20)

    // If this sentence can be executed, panic is captured
    // Subsequent programs can continue to run
    fmt.Println("everything is ok")
}

Note: no cross process: even if panic will cause the whole program to exit, if there is a defer delay function before exiting, you still have to execute defer.

However, this defer has no effect among multiple coroutines. Triggering panic in a child coroutine can only trigger the defer in its own coroutine, rather than calling the defer function in the main coroutine.

Topics: Go Programming pointer