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.