[www.liwenzhou.com/][https://w…]
Golang 中文文档 address: studygolang.com/pkgdoc Go language basic syntax (1)
1. The operator
Operators built into the Go language are:
- Arithmetic operator
- Relational operator
- Logical operator
- An operator
- The assignment operator
Arithmetic operator
The operator | describe |
---|---|
+ | add |
– | Subtracting the |
* | multiply |
/ | division |
% | For more than |
Note: ++ (increment) and — (decrement) are separate statements in Go, not operators.
Relational operator
The operator | describe |
---|---|
= = | Checks if two values are equal, returning True if they are, False otherwise. |
! = | Checks if two values are not equal, returning True if not False otherwise. |
> | Checks if the value on the left is greater than the value on the right, and returns True if so, False otherwise. |
> = | Checks if the value on the left is greater than or equal to the value on the right, and returns True if so, False otherwise. |
< | Checks if the value on the left is less than the value on the right, and returns True if so, False otherwise. |
< = | Checks if the value on the left is less than or equal to the value on the right, and returns True if it is False otherwise. |
Logical operator
The operator | describe |
---|---|
&& | The logical AND operator. True if both operands are True, False otherwise. |
|| | The logical OR operator. True if the operands on both sides have a True, False otherwise. |
! | Logical NOT operator. False if the condition is True, True otherwise. |
An operator
Bitwise operators operate on the binary bits of integers in memory.
The operator | describe |
---|---|
& | The binary phase of each of the two numbers involved in the operation. (1 only if both of them are 1) |
| | The binary phase or of each of the two numbers involved in the operation. (If one of them is 1, it’s 1.) |
^ | The result is 1 when the corresponding binary digits of the two numbers involved in the operation are different or when the corresponding binary digits are different. (1 if the two digits are different) |
<< | To the left n is 2 to the n. “A <<b” is to move all the binary bits of A to the left by B bits, discard the high bits and fill the low ones with 0 bits. |
>> | If you move to the right n places, you divide by 2 to the n. “A >> B” is to shift all the binaries of A to the right by B bits. |
The assignment operator
The operator | describe |
---|---|
= | A simple assignment operator that assigns the value of an expression to an lvalue |
+ = | Add them and assign them |
– = | Subtract and assign |
* = | Multiply and assign |
/ = | Divide and assign |
% = | Remainder and then assign |
< < = | Assign after left shift |
> > = | Assign after right shift |
& = | Assignment by bit and post |
| = | Assignment by bit or post |
^ = | Xor post assignment by bit |
An array of 2.
An array is a collection of elements of the same data type. In Go, arrays are defined from the time they are declared, and the array members can be changed as you use them, but the array size cannot be changed. Basic syntax:
// Define an array a of length 3 and type int
var a [3]int
Copy the code
2.1 Array Definition:
Var Array variable name [element number]TCopy the code
For example, var a [5]int, the length of the array must be constant, and the length must be part of the array type. Once defined, the length cannot change. [5]int and [10]int are different types.
var a [3]int
var b [4]int
a = b // Do not do this because a and B are of different types
Copy the code
Array can be accessed by subscript, the subscript is 0, the last element subscript is: len-1, access out of bounds (index is outside the legal range), triggering access out of bounds, panic.
2.2 Array initialization:
Arrays can also be initialized in a number of ways.
Methods a
When initializing an array, you can use the initializer list to set the values of the array elements.
func main(a) {
var testArray [3]int // The array is initialized to a zero value of type int
var numArray = [3]int{1.2} // Complete the initialization with the specified initial value
var cityArray = [3]string{"Beijing"."Shanghai"."Shenzhen"} // Complete the initialization with the specified initial value
fmt.Println(testArray) / / [0 0 0]
fmt.Println(numArray) / / [1, 2 0]
fmt.Println(cityArray) //[Beijing, Shanghai and Shenzhen]
}
Copy the code
Method 2
Make sure the initial value is the same as the length of the array. In general, we can let the compiler infer the length of the array based on the number of initial values. For example:
func main(a) {
var testArray [3]int
var numArray = [...]int{1.2}
var cityArray = [...]string{"Beijing"."Shanghai"."Shenzhen"}
fmt.Println(testArray) / / [0 0 0]
fmt.Println(numArray) / / [1, 2]
fmt.Printf("type of numArray:%T\n", numArray) //type of numArray:[2]int
fmt.Println(cityArray) //[Beijing, Shanghai and Shenzhen]
fmt.Printf("type of cityArray:%T\n", cityArray) //type of cityArray:[3]string
}
Copy the code
Methods three
We can also initialize an array by specifying an index value, for example:
func main(a) {
a := [...]int{1: 1.3: 5}
fmt.Println(a) // [0 1 0 5]
fmt.Printf("type of a:%T\n", a) //type of a:[4]int
}
Copy the code
2.3 Array traversal:
There are two ways to traverse group A:
func main(a) {
var a = [...]string{"Beijing"."Shanghai"."Shenzhen"}
// Method 1: for loop through
for i := 0; i < len(a); i++ {
fmt.Println(a[i])
}
// method 2: for range
for index, value := range a {
fmt.Println(index, value)
}
}
Copy the code
3. Multidimensional arrays
The Go language supports multi-dimensional arrays, so let’s take two-dimensional arrays as an example (arrays nested within arrays).
3.1 Definition of two-dimensional array:
func main(a) {
a := [3] [2]string{{"Beijing"."Shanghai"},
{"Guangzhou"."Shenzhen"},
{"Chengdu"."Chongqing"},
}
fmt.Println(a) //[[Beijing Shanghai] [Guangzhou Shenzhen] [Chengdu Chongqing]]
fmt.Println(a[2] [1]) // Index Value: Chongqing
}
Copy the code
3.2 Traversal of two-dimensional arrays:
func main(a) {
a := [3] [2]string{{"Beijing"."Shanghai"},
{"Guangzhou"."Shenzhen"},
{"Chengdu"."Chongqing"}},for _, v1 := range a {
for _, v2 := range v1 {
fmt.Printf("%s\t", v2)
}
fmt.Println()
}
}
Copy the code
Output:
Beijing Shanghai Guangzhou Shenzhen Chengdu ChongqingCopy the code
Note: Only the first layer of a multidimensional array can be used… To let the compiler derive the array length. Such as:
// The supported writing methoda := [...] [2]string{{"Beijing"."Shanghai"},
{"Guangzhou"."Shenzhen"},
{"Chengdu"."Chongqing"}},// The inner layer of multidimensional arrays is not supported...
b := [3] [...].string{{"Beijing"."Shanghai"},
{"Guangzhou"."Shenzhen"},
{"Chengdu"."Chongqing"}},Copy the code
3.4 Arrays are value types
Arrays are value types. Assignments and passes copy the entire array. So changing the value of the copy does not change the value of the copy itself.
func modifyArray(x [3]int) {
x[0] = 100
}
func modifyArray2(x [3][2]int) {
x[2] [0] = 100
}
func main(a) {
a := [3]int{10.20.30}
modifyArray(a) // Modify is a copy of A x
fmt.Println(a) / / 20 30 [10]
b := [3] [2]int{{1.1},
{1.1},
{1.1},
}
modifyArray2(b) // Modify is a copy of B x
fmt.Println(b) //[[1 1] [1 1]]
}
Copy the code
Note:
- Arrays support “==”, “! = “operator, because memory is always initialized.
[n]*T
Represents an array of Pointers,*[n]T
Represents an array pointer.
Complete code:
package main
import "fmt"
func main(a) {
// Array definition
var a1 [3]bool
fmt.Println(a1) // [false false false]
var a2 [4]bool
fmt.Printf("a1:%T a2:%T\n", a1, a2)
// Array initialization
a1 = [3]bool{true.true.false}1 / / way
fmt.Println(a1)
a3 := [...]int{1.2.3.4.5.6.7.8.9}2 / / way
fmt.Println(a3)
a4 := [5]int{1.2}3 / / way
fmt.Println(a4)// [1 2 0 0 0]
a5 := [5]int{0:1.4:2}4 / / way
fmt.Println(a5)// [1 0 0 0 2]
// Array traversal
citys := [...]string{"Beijing"."Shanghai"."Shenzhen"}
// 1. Traversal by index
for i:=0; i<len(citys); i++ { fmt.Println(citys[i]) }// 2
for index,value := range citys{
fmt.Println(index,value)
}
// Multi-dimensional array
var arr [3] [2]int
arr = [3] [2]int{[2]int{1.2},2]int{3.4},2]int{5.6},
}
fmt.Println(arr)
// Multi-dimensional array traversal
for _,value := range arr{
for _,v := range value{
fmt.Println(v)
}
}
// Arrays are value types
b1 := [3]int{1.2.3}
b2 := b1
b2[0] = 100
fmt.Println(b1,b2)// [1 2 3] [100 2 3]
}
Copy the code
4. Slice
4.1 the introduction
Because the length of an array is fixed and is part of a type, arrays have many limitations. Such as:
func arraySum(x [3]int) int{
sum := 0
for _, v := range x{
sum = sum + v
}
return sum
}
Copy the code
This summation function accepts only [3] ints, and nothing else. For example,
a := [3]int{1.2.3}
Copy the code
We already have three elements in array A, so we can’t add any more elements to array A.
4.1 Definition of slice
A Slice is a variable-length sequence of elements of the same type. It is a layer of encapsulation based on the array type. It is very flexible and supports automatic expansion.
A slice is a reference type whose internal structure contains an address, length, and capacity. Slicing is generally used to quickly manipulate a collection of data.
4.2 Slice declaration syntax
The basic syntax for declaring slice types is as follows:
var name []T
Copy the code
Among them:
name
: indicates the variable nameT
: indicates the element type in the slice
Here’s an example:
func main(a) {
// Declare the slice type
var a []string // Declare a string slice
var b = []int{} // Declare an integer slice and initialize it
var c = []bool{false.true} // Declare a Boolean slice and initialize it
var d = []bool{false.true} // Declare a Boolean slice and initialize it
fmt.Println(a) / / []
fmt.Println(b) / / []
fmt.Println(c) //[false true]
fmt.Println(a == nil) //true
fmt.Println(b == nil) //false
fmt.Println(c == nil) //false
// FMT.Println(c == d) // Slice is a reference type and can only be compared to nil
}
Copy the code
4.3 Section length and capacity
Slices have their own length and capacity. We can calculate the length of slices by using the built-in len() function and the capacity of slices by using the built-in cap() function.
4.4 Slice expression
A slice expression constructs a substring or slice from a string, array, or pointer to an array or slice. It comes in two variants: a simple form that specifies low and high index bounds, and a full form that specifies capacity in addition to low and high index bounds.
Simple slice expression
The bottom layer of a slice is an array, so we can get a slice based on an array through a slice expression. Low and high in the slice expression represent an index range (left included, right excluded), that is, in the following code, elements 1<= index value <4 from array A are selected to form slice S, the length of the slice obtained is =high-low, and the capacity is equal to the capacity of the underlying array of the slice obtained.
func main(a) {
a := [5]int{1.2.3.4.5}
s := a[1:3] // s := a[low:high]
fmt.Printf("s:%v len(s):%v cap(s):%v\n", s, len(s), cap(s))
}
Copy the code
Output:
s:[2 3] len(s):2 cap(s):4
Copy the code
For convenience, you can omit any indexes in the slice expression. Omitting low defaults to 0; Omitting high defaults to the length of the slice operand:
a[2:] // same as a[2:len(a)]
a[:3] // equivalent to a[0:3]
a[:] // same as a[0:len(a)]
Copy the code
Note:
For arrays or strings, the index is valid if 0 <= low <= high <= len(a), otherwise the index is out of range.
When the slice expression is executed for the slice again (slice again slice), the upper bound of high is the capacity cap(a) of the slice, not the length. A constant index must be non-negative and can be represented by a value of type int; For arrays or constant strings, the constant index must also be in a valid range. If both low and high are constants, they must satisfy low <= high. A runtime panic occurs if the index is out of range at run time.
func main(a) {
a := [5]int{1.2.3.4.5}
s := a[1:3] // s := a[low:high]
fmt.Printf("s:%v len(s):%v cap(s):%v\n", s, len(s), cap(s))
s2 := s[3:4] // Index cap(s) instead of len(s)
fmt.Printf("s2:%v len(s2):%v cap(s2):%v\n", s2, len(s2), cap(s2))
}
Copy the code
Output:
s:[2 3] len(s):2 cap(s):4
s2:[5] len(s2):1 cap(s2):1
Copy the code
Complete slice expression
For arrays, Pointers to arrays, or slice a(not strings) support full slice expressions:
a[low : high : max]
Copy the code
The above code constructs a slice of the same type, length, and elements as the simple slice expression A [low: high]. In addition, it sets the capacity of the resulting slice to max-low. Only the first index value (low) can be omitted in the full slice expression; It defaults to 0.
func main(a) {
a := [5]int{1.2.3.4.5}
t := a[1:3:5]
fmt.Printf("t:%v len(t):%v cap(t):%v\n", t, len(t), cap(t))
}
Copy the code
Output result:
t:[2 3] len(t):2 cap(t):4
Copy the code
The conditions for a complete slice expression are 0 <= low <= high <= Max <= cap(a), and other conditions are the same as those for a simple slice expression.
4.5 Use the make() function to construct slices
If you want to create a slice dynamically, you need to use the built-in make() function, which has the following format:
make([]T, size, cap)
Copy the code
Among them:
T
: The element type of the slicesize
: The number of elements in the slicecap
: Slice capacity
Here’s an example:
func main(a) {
a := make([]int.2.10)
fmt.Println(a) / / [0, 0]
fmt.Println(len(a)) / / 2
fmt.Println(cap(a)) / / 10
}
Copy the code
In the code above, 10 internal storage Spaces of A have been allocated, but only 2 are actually used. Capacity does not affect the number of current elements, so len(a) returns 2 and cap(a) returns the capacity of the slice.
4.6 Nature of slicing
The essence of slicing is to encapsulate the underlying array. It contains three pieces of information: the pointer to the underlying array, the length of the slice (Len) and the capacity of the slice (CAP).
For example, we now have an array a := [8]int{0, 1, 2, 3, 4, 5, 6, 7}, sliced s1 := a[:5], as shown in the following diagram.
Section S2 := a[3:6], corresponding schematic diagram is as follows:
4.7 Determine whether the slice is empty
To check if the slice is empty, always use len(s) == 0 and should not use s == nil.
4.8 Sections cannot be directly compared
Slices cannot be compared, and we cannot use the == operator to determine whether two slices contain all equal elements. The only valid comparison operation for slicing is to compare to nil. A nil slice has no underlying array. A nil slice has a length and a capacity of 0. But we can’t say that a slice with both length and capacity 0 is nil, as in the following example:
var s1 []int //len(s1)=0; cap(s1)=0; s1==nil
s2 := []int{} //len(s2)=0; cap(s2)=0; s2! =nil
s3 := make([]int.0) //len(s3)=0; cap(s3)=0; s3! =nil
Copy the code
Therefore, to determine whether a slice is empty, len(s) == 0 should not be used to determine s == nil.
4.9 Assigned copy of slices
The following code demonstrates that both variables share the underlying array before and after the copy. It is important to note that changes to one slice affect the contents of the other.
func main(a) {
s1 := make([]int.3) / / [0 0 0]
s2 := s1 // Assign s1 directly to s2. S1 and S2 share the same underlying array
s2[0] = 100
fmt.Println(s1) / / [100 0 0]
fmt.Println(s2) / / [100 0 0]
}
Copy the code
4.10 Slice traversal
Slice traversal is the same as array traversal, supporting index traversal and for range traversal.
func main(a) {
s := []int{1.3.5}
for i := 0; i < len(s); i++ {
fmt.Println(i, s[i])
}
for index, value := range s {
fmt.Println(index, value)
}
}
Copy the code
4.11 Append () method adds elements to slice
The Go language’s built-in function Append () can dynamically add elements to slices. You can add one element at a time, you can add multiple elements, or you can add elements from another slice (followed by…). .
func main(a){
var s []int
s = append(s, 1) / / [1]
s = append(s, 2.3.4) // [1 2 3 4]
s2 := []int{5.6.7}
s = append(s, s2...) // [1 2 3 4 5 6 7]
}
Copy the code
** Note: the null slice declared by var can be used directly in the append() function without initialization.
var s []int
s = append(s, 1.2.3)
Copy the code
There is no need to initialize a slice and pass it into the append() function as shown below,
s := []int{} // No initialization is necessary
s = append(s, 1.2.3)
var s = make([]int) // No initialization is necessary
s = append(s, 1.2.3)
Copy the code
Each slice points to an underlying array, and when the array is large enough, new elements are added. When the underlying array cannot contain new elements, the slice will be automatically expanded according to certain policies, and the underlying array pointed to by the slice will be replaced. The “expansion” operation usually occurs when the append() function is called, so we usually need to receive the return value of the Append function in the original variable.
Here’s an example:
func main(a) {
//append() adds elements and slices for expansion
var numSlice []int
for i := 0; i < 10; i++ {
numSlice = append(numSlice, i)
fmt.Printf("%v len:%d cap:%d ptr:%p\n", numSlice, len(numSlice), cap(numSlice), numSlice)
}
}
Copy the code
Output:
[0] len:1 cap:1 ptr:0xc0000a8000
[0 1] len:2 cap:2 ptr:0xc0000a8040
[0 1 2] len:3 cap:4 ptr:0xc0000b2020
[0 1 2 3] len:4 cap:4 ptr:0xc0000b2020
[0 1 2 3 4] len:5 cap:8 ptr:0xc0000b6000
[0 1 2 3 4 5] len:6 cap:8 ptr:0xc0000b6000
[0 1 2 3 4 5 6] len:7 cap:8 ptr:0xc0000b6000
[0 1 2 3 4 5 6 7] len:8 cap:8 ptr:0xc0000b6000
[0 1 2 3 4 5 6 7 8] len:9 cap:16 ptr:0xc0000b8000
[0 1 2 3 4 5 6 7 8 9] len:10 cap:16 ptr:0xc0000b8000
Copy the code
As can be seen from the above results:
append()
The function appends the element to the end of the slice and returns the slice.- The capacity of numSlice is automatically expanded according to the rule 1,2,4,8,16. After each expansion, the capacity is doubled.
The append() function also supports appending multiple elements at once. Such as:
var citySlice []string
// Appends an element
citySlice = append(citySlice, "Beijing")
// Append multiple elements
citySlice = append(citySlice, "Shanghai"."Guangzhou"."Shenzhen")
// Append slices
a := []string{"Chengdu"."Chongqing"}
citySlice = append(citySlice, a...)
fmt.Println(citySlice) //[Beijing Shanghai Guangzhou Shenzhen Chengdu Chongqing]
Copy the code
4.12 The copy() function copies slices
Let’s start with a question:
func main(a) {
a := []int{1.2.3.4.5}
b := a
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(b) //[1 2 3 4 5]
b[0] = 1000
fmt.Println(a) //[1000 2 3 4 5]
fmt.Println(b) //[1000 2 3 4 5]
}
Copy the code
Since slices are references, both A and B actually refer to the same memory address. When you change B, you change the value of A.
Go’s built-in copy() function can quickly copy data from one slice to another. The format of copy() function is as follows:
copy(destSlice, srcSlice []T)
Copy the code
Among them:
- SrcSlice: indicates the slice of data source
- DestSlice: indicates the destination slice
Here’s an example:
func main(a) {
// copy() copies slices
a := []int{1.2.3.4.5}
c := make([]int.5.5)
copy(c, a) // Use copy() to copy the elements in slice A to slice C
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(c) //[1 2 3 4 5]
c[0] = 1000
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(c) //[1000 2 3 4 5]
}
Copy the code
4.13 Deleting elements from a slice
There is no special way to delete slice elements in Go, we can use the features of slice itself to delete elements. The code is as follows:
func main(a) {
// Remove the element from the slice
a := []int{30.31.32.33.34.35.36.37}
// Delete the element with index 2
a = append(a[:2], a[3:]...). fmt.Println(a)//[30 31 33 34 35 36 37]
}
Copy the code
A = append(a[:index], a[index+1:]…)
Pointer to 5.
Different from the pointer in C/C++, the pointer in Go language cannot be offset and operation, is a safe pointer.
To understand Pointers in Go, you need to know three concepts: pointer address, pointer type, and pointer value.
5.1 Pointers in Go
Any program data loaded into memory has its address in memory, which is called a pointer. In order to store an address in memory, we need pointer variables.
For example, “Never overestimate yourself” is my motto, AND I want to write it into the program. As soon as the program starts, this sentence is loaded into memory (assuming memory address 0x123456), and I assign this statement to variable A and memory address to variable B in the program. The variable B is a pointer variable. My motto can be found in both variable A and variable B.
Pointers in Go cannot be offset and computed, so pointer manipulation in Go is very simple and we only need to remember two symbols:
&
Address:*
: The value is based on the address
5.2 Pointer Address and Pointer type
Each variable has an address at run time that represents its location in memory. The Go language uses the & character in front of a variable to “fetch the address”. Value types (int, float, bool, string, array, struct) in Go have corresponding pointer types, such as: *int, *int64, *string, etc.
The syntax for fetching a variable pointer is as follows:
ptr := &v // v is of type T
Copy the code
Among them:
- v: Represents the variable to be fetched, of type
T
- ptr: the variable used to receive the address. PTR is of type
*T
, called a pointer type to T. * stands for pointer.
Here’s an example:
func main(a) {
a := 10
b := &a
fmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078
fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int
fmt.Println(&b) // 0xc00000e018
}
Copy the code
Let’s take a look at the diagram of b := &a:
5.3 Pointer Values
A pointer to an ordinary variable can be obtained by using the & operator to fetch the address. A pointer can then be operated on with *, the value of the pointer, as follows.
func main(a) {
// Pointer value
a := 10
b := &a // take the address of variable A and save the pointer to b
fmt.Printf("type of b:%T\n", b)
c := *b // Pointer value (based on the pointer to memory)
fmt.Printf("type of c:%T\n", c)
fmt.Printf("value of c:%v\n", c)
}
Copy the code
The output is as follows:
type of b:*int
type of c:int
value of c:10
Copy the code
Conclusion: the address-fetch operator & and the value operator * are complementary operators. The & retrieves the address, and * retrieves the value pointed to by the address.
The interrelations and characteristics of variable, pointer address, pointer variable, address fetch, and value are as follows:
- Fetch the address of a variable (
&
) to get a pointer to the variable. - The value of a pointer variable is a pointer address.
- Value a pointer variable (
*
) to obtain the value of the original variable to which the pointer variable points.
Example of pointer value transfer:
func modify1(x int) {
x = 100
}
func modify2(x *int) {
*x = 100
}
func main(a) {
a := 10
modify1(a)
fmt.Println(a) / / 10
modify2(&a)
fmt.Println(a) / / 100
}
Copy the code
5.4 the new and the make
Let’s start with an example:
func main(a) {
var a *int
*a = 100
fmt.Println(*a)
var b map[string]int
b[shahenaza] = 100
fmt.Println(b)
}
Copy the code
Executing the above code causes panic. Why? In Go, when we use a variable of reference type, we not only declare it, but also allocate memory space for it, otherwise our value cannot be stored. Declarations of value types do not allocate memory because they are already allocated memory by default when they are declared. To allocate memory, we have today’s new and make. New and make are two built-in functions in Go that allocate memory.
new
New is a built-in function with the following function signature:
func new(Type) *Type
Copy the code
Among them,
- Type stands for Type, and the new function takes only one argument, which is a Type
- The new function returns a pointer to the memory address of the Type.
The new function is not very common. You get a pointer to a type that has a zero value for that type. Here’s an example:
func main(a) {
a := new(int)
b := new(bool)
fmt.Printf("%T\n", a) // *int
fmt.Printf("%T\n", b) // *bool
fmt.Println(*a) / / 0
fmt.Println(*b) // false
}
Copy the code
In the example code at the beginning of this section, var a *int only declares a pointer variable a but does not initialize it. The pointer, as a reference type, needs to be initialized before it has the memory to assign a value to it. We should initialize a using the built-in new function as follows:
func main(a) {
var a *int
a = new(int)
*a = 10
fmt.Println(*a)
}
Copy the code
make
Make is also used to allocate memory. Unlike new, it is only used to create memory for slice, map, and chan, and it returns the three types themselves, not their pointer types. Since these three types are reference types, there is no need to return their Pointers. The make function has the following function signature:
func make(t Type, size ... IntegerType) Type
Copy the code
There is no substitute for make. Slice, Map, and channel all need to be initialized with make before they can be manipulated. We explained this in the previous chapter, and we will elaborate on channel in the following chapters.
Var b map[string]int specifies that b is a map variable, and that it needs to be initialized using the make function as in the following example:
func main(a) {
var b map[string]int
b = make(map[string]int.10)
b[shahenaza] = 100
fmt.Println(b)
}
Copy the code
The difference between new and make
- Both are used for memory allocation.
- Make is only used to initialize slice, map, and channel, and returns the three reference types themselves.
- New is used for the memory allocation of the type, and the corresponding value of the memory is type zero, and returns a pointer to the type.
6. Map
The mapping container provided by Go language is Map, which uses hash internally.
6.1 the map is introduced
A map is an unordered key-value based data structure. In Go, a map is a reference type and must be initialized before it can be used.
6.2 the map definition
The map definition syntax in Go language is as follows:
map[KeyType]ValueType
Copy the code
Among them,
- KeyType: indicates the KeyType.
- ValueType: indicates the ValueType of the key.
Map variables default to nil and use the make() function to allocate memory. Grammar:
make(map[KeyType]ValueType, [cap])
Copy the code
Cap represents the capacity of the map. This parameter is not required, but an appropriate capacity should be specified when the map is initialized.
6.3 Basic Use of Map
The data in map comes in pairs. The basic code for using map is as follows:
func main(a) {
scoreMap := make(map[string]int.8)
scoreMap["Zhang"] = 90
scoreMap["Xiao Ming"] = 100
fmt.Println(scoreMap)
fmt.Println(scoreMap["Xiao Ming"])
fmt.Printf("type of a:%T\n", scoreMap)
}
Copy the code
Output:
[Xiaoming :100 zhangs3:90] 100type of a:map[string]int
Copy the code
Map also supports padding elements at declaration time, for example:
func main(a) {
userInfo := map[string]string{
"username": "The Little Prince of Sand River"."password": "123456",
}
fmt.Println(userInfo) // map[password:123456 username: 123456]
}
Copy the code
6.4 Checking whether a Key Exists
In Go, there is a special way to determine whether a key exists in a map. The format is as follows:
value, ok := map[key]
Copy the code
Here’s an example:
func main(a) {
scoreMap := make(map[string]int)
scoreMap["Zhang"] = 90
scoreMap["Xiao Ming"] = 100
// if key exists, ok is true and v is the corresponding value; There is no zero value where OK is false and v is a value type
v, ok := scoreMap["Zhang"]
if ok {
fmt.Println(v)
} else {
fmt.Println("No trace of him.")}}Copy the code
6.5 Map Traversal
Go uses for range to traverse a map.
func main(a) {
scoreMap := make(map[string]int)
scoreMap["Zhang"] = 90
scoreMap["Xiao Ming"] = 100
scoreMap["娜扎"] = 60
for k, v := range scoreMap {
fmt.Println(k, v)
}
}
Copy the code
But if we just want to iterate over the key, we can write it like this:
func main(a) {
scoreMap := make(map[string]int)
scoreMap["Zhang"] = 90
scoreMap["Xiao Ming"] = 100
scoreMap["娜扎"] = 60
for k := range scoreMap {
fmt.Println(k)
}
}
Copy the code
Note: The order in which the elements are iterated through the map is independent of the order in which the key-value pairs are added.
6.6 The delete() function Deletes key-value pairs
Delete a set of key-value pairs from a map using the delete() built-in function, which has the following format:
delete(map, key)
Copy the code
Among them:
- Map: indicates the map of the key-value pair to be deleted
- Key: indicates the key of the key-value pair to be deleted
Example code is as follows:
func main(a){
scoreMap := make(map[string]int)
scoreMap["Zhang"] = 90
scoreMap["Xiao Ming"] = 100
scoreMap["娜扎"] = 60
delete(scoreMap, "Xiao Ming")// Delete xiaoming :100 from map
for k,v := range scoreMap{
fmt.Println(k, v)
}
}
Copy the code
6.7 Traversing the Map in the Specified Sequence
func main(a) {
rand.Seed(time.Now().UnixNano()) // Initializes the random number seed
var scoreMap = make(map[string]int.200)
for i := 0; i < 100; i++ {
key := fmt.Sprintf("stu%02d", i) // Generate a string beginning with stu
value := rand.Intn(100) // Generate random integers from 0 to 99
scoreMap[key] = value
}
// Remove all keys from map and store them in slice keys
var keys = make([]string.0.200)
for key := range scoreMap {
keys = append(keys, key)
}
// Sort the slices
sort.Strings(keys)
// Traverses the map according to the sorted key
for _, key := range keys {
fmt.Println(key, scoreMap[key])
}
}
Copy the code
6.8 Elements are Slices of map type
The following code shows what happens when elements in a slice are of type map:
func main(a) {
var mapSlice = make([]map[string]string.3)
for index, value := range mapSlice {
fmt.Printf("index:%d value:%v\n", index, value)
}
fmt.Println("after init")
// Initialize the map element in the slice
mapSlice[0] = make(map[string]string.10)
mapSlice[0] ["name"] = "The Little Prince"
mapSlice[0] ["password"] = "123456"
mapSlice[0] ["address"] = "Sha"
for index, value := range mapSlice {
fmt.Printf("index:%d value:%v\n", index, value)
}
}
Copy the code
6.9 The value is a slice map
The following code demonstrates an operation with a value of slice type in a map:
func main(a) {
var sliceMap = make(map[string] []string.3)
fmt.Println(sliceMap)
fmt.Println("after init")
key := "China"
value, ok := sliceMap[key]
if! ok { value =make([]string.0.2)
}
value = append(value, "Beijing"."Shanghai")
sliceMap[key] = value
fmt.Println(sliceMap)
}
Copy the code
Function of 7.
Go supports functions, anonymous functions, and closures, and functions are “first-class citizens” in Go.
7.1 Function Definition
Func keyword is used to define functions in Go language, and the specific format is as follows:
funcThe function name(parameters)(Return value){function body}Copy the code
Among them:
- Function name: Contains letters, digits, and underscores (_). But the first letter of the function name cannot be a number. Function names cannot be the same within the same package (see package concepts below).
- Parameter: A parameter consists of a parameter variable and the type of the parameter variable. It is used between multiple parameters
.
Space. - Return value: A return value consists of a return value variable and its variable type. You can also write only the type of the return value. Multiple return values must be used
(a)
Wrap and use.
Space. - Function body: a block of code that implements a specified function.
Let’s first define a function that adds two numbers:
func intSum(x int, y int) int {
return x + y
}
Copy the code
Function arguments and return values are optional. For example, we can implement a function that takes neither arguments nor returns values:
func sayHello(a) {
fmt.Println(Shahe, "Hello")}Copy the code
7.2 Function Invocation
Once the function is defined, we can call the function by its name (). For example, if we call the two functions defined above, the code looks like this:
func main(a) {
sayHello()
ret := intSum(10.20)
fmt.Println(ret)
}
Copy the code
Note that you can call a function with a return value without receiving its return value.
7.3 parameter
7.3.1 Type shorthand
If adjacent variables in a function have the same type, the type can be omitted. For example:
func intSum(x, y int) int {
return x + y
}
Copy the code
In the above code, the intSum function takes two arguments, both of type int, so we can omit the type of x, because y is typed, and x is the same type.
7.3.2 Variable Parameters
A variable parameter is a function that has an unfixed number of arguments. Variable arguments in the Go language are made by adding… To identify.
Note: A variable argument is usually the last argument to a function.
Here’s an example:
func intSum2(x ...int) int {
fmt.Println(x) //x is a slice
sum := 0
for _, v := range x {
sum = sum + v
}
return sum
}
Copy the code
Call the above function:
ret1 := intSum2()
ret2 := intSum2(10)
ret3 := intSum2(10.20)
ret4 := intSum2(10.20.30)
fmt.Println(ret1, ret2, ret3, ret4) / / 0 10 30 to 60
Copy the code
When a fixed parameter is used with a variable parameter, the variable parameter should be placed after the fixed parameter. The example code is as follows:
func intSum3(x int, y ...int) int {
fmt.Println(x, y)
sum := x
for _, v := range y {
sum = sum + v
}
return sum
}
Copy the code
Call the above function:
ret5 := intSum3(100)
ret6 := intSum3(100.10)
ret7 := intSum3(100.10.20)
ret8 := intSum3(100.10.20.30)
fmt.Println(ret5, ret6, ret7, ret8) / / 100 110 130 160
Copy the code
Essentially, the variable arguments of a function are implemented by slicing.
7.4 the return value
In Go, the return keyword is used to output the return value.
7.4.1 Multiple Return Values
The Go language supports multiple return values for functions. If a function has multiple return values, it must wrap all return values with ().
Here’s an example:
func calc(x, y int) (int.int) {
sum := x + y
sub := x - y
return sum, sub
}
Copy the code
7.4.2 Return Value naming
A function can be defined by naming its return value, using these variables directly in the function body, and finally returning it with the return keyword.
Such as:
func calc(x, y int) (sum, sub int) {
sum = x + y
sub = x - y
return
}
Copy the code
7.4.3 Return Value Supplement
When one of our functions returns a value of type slice, nil is considered a valid slice, there is no need to show that it returns a slice of length 0.
func someFunc(x string) []int {
if x == "" {
return nil // Return []int{}}... }Copy the code
7.5 Variable scope
7.5.1 Global Variables
A global variable is a variable defined outside of a function that is valid for the entire running life of a program. Global variables can be accessed in functions.
package main
import "fmt"
// Define the global variable num
var num int64 = 10
func testGlobalVar(a) {
fmt.Printf("num=%d\n", num) The global variable num can be accessed in the function
}
func main(a) {
testGlobalVar() //num=10
}
Copy the code
7.5.2 Local variables
Local variables are divided into two types: variables defined inside a function cannot be used outside the function. For example, in the following example, the variable x defined in testLocalVar cannot be used in the main function:
func testLocalVar(a) {
// define a function local variable x that is valid only within the function
var x int64 = 100
fmt.Printf("x=%d\n", x)
}
func main(a) {
testLocalVar()
fmt.Println(x) // The variable x cannot be used at this time
}
Copy the code
If the local variable has the same name as the global variable, the local variable is preferentially accessed.
package main
import "fmt"
// Define the global variable num
var num int64 = 10
func testNum(a) {
num := 100
fmt.Printf("num=%d\n", num) // Local variables are preferred in functions
}
func main(a) {
testNum() // num=100
}
Copy the code
Next, let’s look at block-defined variables. We usually use this method for if conditions, for loops, and switch statements.
func testLocalVar2(x, y int) {
fmt.Println(x, y) // Function parameters are valid only in this function
if x > 0 {
z := 100 // The z variable applies only to the if block
fmt.Println(z)
}
// fmt.println (z)// Variable z cannot be used here
}
Copy the code
The variables defined in the for loop are only valid in the for block:
func testLocalVar3(a) {
for i := 0; i < 10; i++ {
fmt.Println(i) // The variable I is valid only in the current for block
}
// fmt.println (I) // The variable I cannot be used here
}
Copy the code
7.6 Function Types and Variables
7.6.1 Defining function types
We can use the type keyword to define a function type in the following format:
type calculation func(int.int) int
Copy the code
The above statement defines a Calculation type, which is a function type that takes two parameters of type int and returns a value of type int.
Simply put, all functions that meet this condition are calculation functions, for example, add and sub below are Calculation functions.
func add(x, y int) int {
return x + y
}
func sub(x, y int) int {
return x - y
}
Copy the code
Both Add and sub can be assigned to variables of type Calculation.
var c calculation
c = add
Copy the code
7.6.2 Function Type Variables
We can declare a variable of function type and assign a value to it:
func main(a) {
var c calculation // Declare a calculation variable c
c = add // assign add to c
fmt.Printf("type of c:%T\n", c) // type of c:main.calculation
fmt.Println(c(1.2)) // Call c like add
f := add // Assign function add to variable f1
fmt.Printf("type of f:%T\n", f) // type of f:func(int, int) int
fmt.Println(f(10.20)) // Call f like add
}
Copy the code
7.7 Higher-order functions
Higher-order functions are divided into functions as parameters and functions as return values.
7.7.1 Functions as Parameters
Functions can be arguments:
func add(x, y int) int {
return x + y
}
func calc(x, y int, op func(int.int) int) int {
return op(x, y)
}
func main(a) {
ret2 := calc(10.20, add)
fmt.Println(ret2) / / 30
}
Copy the code
7.7.2 Function as return value
Function can also be used as a return value:
func do(s string) (func(int.int) int.error) {
switch s {
case "+":
return add, nil
case "-":
return sub, nil
default:
err := errors.New("Unrecognized operator")
return nil, err
}
}
Copy the code
7.8 Anonymous Functions and closures
7.8.1 Anonymous Functions
Functions can of course still be returned, but in Go you can no longer define functions inside functions as before, only anonymous functions. An anonymous function is a function that does not have a function name. An anonymous function is defined in the following format:
func(parameters)(Return value){function body}Copy the code
Anonymous functions cannot be called like normal functions because they do not have a function name, so anonymous functions need to be saved to a variable or executed immediately:
func main(a) {
// Save the anonymous function to a variable
add := func(x, y int) {
fmt.Println(x + y)
}
add(10.20) // Call an anonymous function through a variable
// Self-executing functions: Anonymous functions are executed directly after the addition () is defined
func(x, y int) {
fmt.Println(x + y)
}(10.20)}Copy the code
Anonymous functions are mostly used to implement callbacks and closures.
7.8.2 closure
A closure is an entity composed of a function and its associated reference environment. In simple terms, closures = function + reference environment. Let’s start with an example:
func adder(a) func(int) int {
var x int
return func(y int) int {
x += y
return x
}
}
func main(a) {
var f = adder()
fmt.Println(f(10)) / / 10
fmt.Println(f(20)) / / 30
fmt.Println(f(30)) / / 60
f1 := adder()
fmt.Println(f1(40)) / / 40
fmt.Println(f1(50)) / / 90
}
Copy the code
The variable f is a closure when it is a function and refers to the x variable in its outer scope. The variable X also remains valid throughout the life of F. Closure Advanced Example 1:
func adder2(x int) func(int) int {
return func(y int) int {
x += y
return x
}
}
func main(a) {
var f = adder2(10)
fmt.Println(f(10)) / / 20
fmt.Println(f(20)) / / 40
fmt.Println(f(30)) / / 70
f1 := adder2(20)
fmt.Println(f1(40)) / / 60
fmt.Println(f1(50)) / / 110
}
Copy the code
Closure Advanced Example 2:
func makeSuffixFunc(suffix string) func(string) string {
return func(name string) string {
if! strings.HasSuffix(name, suffix) {return name + suffix
}
return name
}
}
func main(a) {
jpgFunc := makeSuffixFunc(".jpg")
txtFunc := makeSuffixFunc(".txt")
fmt.Println(jpgFunc("test")) //test.jpg
fmt.Println(txtFunc("test")) //test.txt
}
Copy the code
Closure Advanced Example 3:
func calc(base int) (func(int) int.func(int) int) {
add := func(i int) int {
base += i
return base
}
sub := func(i int) int {
base -= i
return base
}
return add, sub
}
func main(a) {
f1, f2 := calc(10)
fmt.Println(f1(1), f2(2)) / / 11 September
fmt.Println(f1(3), f2(4)) / / 12 August
fmt.Println(f1(5), f2(6)) / / 13 July
}
Copy the code
Closures aren’t really that complicated, just keep in mind that closures = function + reference context.
7.9 the defer statement
The DEFER statement in the Go language delays the statements that follow it. When the function to which defer belongs is about to return, the deferred statements are executed in reverse order as defined by defer; that is, the statements that were deferred first are executed last, and those that were deferred last are executed first.
Here’s an example:
func main(a) {
fmt.Println("start")
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
fmt.Println("end")}Copy the code
Output result:
start
end
3
2
1
Copy the code
Because of the deferred nature of the defer statement, the defer statement is very handy for handling resource release issues. For example, resource clearing, file closing, unlocking, and recording time.
7.9.1 Defer Execution timing
In the function of Go language, the return statement is not atomic operation at the bottom, it is divided into two steps: assigning value to return value and RET instruction. The defer statement executes after the return value assignment and before the RET directive executes. The details are shown in the figure below:
7.9.2 Defer classic case
Read the code below and write the final print.
func f1(a) int {
x := 5
defer func(a) {
x++
}()
return x
}
func f2(a) (x int) {
defer func(a) {
x++
}()
return 5
}
func f3(a) (y int) {
x := 5
defer func(a) {
x++
}()
return x
}
func f4(a) (x int) {
defer func(x int) {
x++
}(x)
return 5
}
func main(a) {
fmt.Println(f1())
fmt.Println(f2())
fmt.Println(f3())
fmt.Println(f4())
}
Copy the code
7.10 Introduction to built-in Functions
Built-in function | introduce |
---|---|
close | It is used to close channels |
len | For lengths such as string, array, slice, map, channel |
new | Used to allocate memory, mainly used to allocate value types, such as int, struct. It returns a pointer |
make | Used to allocate memory, mainly used to allocate reference types, such as chan, map, slice |
append | Used to append elements to arrays and slices |
Panic and recover | It’s used for error handling |
7.10.1 panic/recover
The Go language currently (Go1.12) has no exception mechanism, but uses panic/ Recover mode to handle errors. Panic can be raised anywhere, but Recover is only valid in the function called by defer. Let’s start with an example:
func funcA(a) {
fmt.Println("func A")}func funcB(a) {
panic("panic in B")}func funcC(a) {
fmt.Println("func C")}func main(a) {
funcA()
funcB()
funcC()
}
Copy the code
Output:
func A
panic: panic in B
goroutine 1 [running]:
main.funcB(...)
.../code/func/main.go:12
main.main()
.../code/func/main.go:20 +0x98
Copy the code
During the running of the program funcB caused panic, resulting in the program crash and abnormal exit. At this point, we can use Recover to restore the program and continue to execute.
func funcA(a) {
fmt.Println("func A")}func funcB(a) {
defer func(a) {
err := recover(a)// If there is a panic error, you can recover it by using recover
iferr ! =nil {
fmt.Println("recover in B")}} ()panic("panic in B")}func funcC(a) {
fmt.Println("func C")}func main(a) {
funcA()
funcB()
funcC()
}
Copy the code
Note:
recover()
Must matchdefer
Use.defer
Be sure to trigger when possiblepanic
Statement before definition.
Go Language basic syntax (2)