Learn what
What is a pointer?
What is a pointer type?
How to use and create pointer type variables?
How to get values from pointer variables?
How do I pass pointers?
What is a pointer
What is a memory address first? The point of popularity is that the number of data storage locations on computer is just like our ID number.
The pointer is the so-called memory address. The memory address is stored in the pointer variable.
Illustration: the left half of the figure is a string data, and the right half is a pointer variable, which stores the address of the string data. The address in the figure is purely fictitious.
Pointer type
The pointer type is to add an asterisk before any type. The format is as follows:
*BaseType
BaseType represents any type.
Example:
*Int represents the pointer type of a variable of type int.
*String represents the pointer type of a variable of type string.
type People struct { Name string Age int }
- *People represents the pointer type of a variable of type people.
How to create pointer variables
Now create a variable of * int pointer type. The format is as follows:
var p *int
p is a pointer type variable. The variable has not been initialized. Now initialize the variable.
var num int = 11 p = &num
Use the & sign to obtain the address of the variable num and assign it to the pointer variable p.
Output pointer variable information as follows:
fmt.Println(p) // output 0xc00000a088
The description at the beginning of 0x is hexadecimal, which is the memory address of the variable num.
Null pointer
Null pointer means that the pointer variable has no assignment, and this spatiotemporal pointer variable is equal to nil.
var empty *int fmt.Println(empty == nil) // output true
nil is similar to null in other languages. In Go language, it can only be compared with pointer type and interface type, and can only assign values to pointer type variables and interface type variables.
Dereferencing Pointers
After declaring a pointer variable, what should I do if I want to get a value from the pointer variable? The value of the pointer is often called dereference. The format is as follows:
var num int = 11 var p *int p = &num // Value fmt.Println(*p) // output 11
*p means to take the value from the variable num pointed to by the pointer. When taking the value, add a * sign in front of the pointer variable.
If the pointer variable is a null pointer, the compiler will report an error when taking a value from it.
panic: runtime error: invalid memory address or nil pointer dereference
structural morphology
If the pointer variable is a structure pointer type, there is no need to add * in front of the pointer variable when obtaining the field in the structure or calling the method.
p := &People{ Name: "Old seedling", Age: 18, } fmt.Pringln(p) fmt.Println(p.Name) or fmt.Println((*p).Name) // output &{Laomiao 18} Old seedling
Summary:
The structure pointer does not output an address
You do not need to add when calling fields or methods of a structure*
method
stay Last article The concept of pointer receiver has been touched on in. Let's briefly explain this. Please take a look at it in detail Custom types and structures - Methods.
If you want to modify the field in the structure through the method, you can set the receiver to the pointer type.
// type/struct.go // ... func (p *People) SetName(name string) { p.Name = name } func main() { people := People{ Name: "Old seedling", } people.SetName("Chic brother") fmt.Println(people.Name) } // output Chic brother
The receiver p of the SetName method is the pointer type. The Name field is modified, and the data of the people variable is also changed.
Pointer passing
In Go language, most types are value passing, that is, when passing values through functions, modifications in functions cannot affect the outside. If you want to change, use the pointer type.
// pointer/function.go // ... func UpdateNum(num *int) { *num = 2 } func main() { n := 1 UpdateNum(&n) fmt.Println(n) } // output 2
The UpdateNum function accepts an * int pointer type. The formal parameter num pointer type points to the argument variable n. therefore, the modification of num affects the value of variable n.
Individual types in Go language are reference types themselves. You can modify the value inside the function without using a pointer to affect the outside.
1. map and channel
These two are reference types, and there is no need to use pointers when passing. The channel will be explained with examples in subsequent articles.
// pointer/map.go // ... func SetCountry(countries map[string]string) { countries["china"] = "China" } func main() { c := make(map[string]string) SetCountry(c) fmt.Println(c) } // output map[china:China]
This code initializes a map type, and then modifies its value through the SetCountry function.
2. Slice
In understanding Built in set - Slicing After this article, you should understand that the underlying reference of the slice is an array. The reference of the underlying array will not be changed when the slice is passed, but the array reference will be changed after the slice is appended.
// pointer/slice.go //... func AppendAnimals(animals []string) { animals = append(animals, "tiger", "elephant") } func main() { input := []string{"monkey"} AppendAnimals(input) fmt.Println(input) } // output [monkey]
The AppendAnimals function appends elements to the slice, but the value of the external variable input is not affected, because the underlying array will be copied and the reference will be changed after the append operation.
If you want to affect the input variable in the function, use the pointer to solve it.
// pointer/slice.go //... func AppendAnimalsPointer(animals *[]string) { *animals = append(*animals, "tiger", "elephant") } func main() { input := []string{"monkey"} AppendAnimalsPointer(&input) fmt.Println(input) } // output [Monkey tiger elephant]
If only the contents of the slice are modified when passing the slice, that is, no elements are appended, the original slice data will be affected because the reference of the underlying array has not changed.
// pointer/slice.go //... func UpdateAnimals(animals []string) { for i := range animals { animals[i] = "rabbit" } } func main() { updateInput := []string{"tiger", "elephant"} UpdateAnimals(updateInput) fmt.Println(updateInput) } // output [Rabbit rabbit]
The UpdateAnimals function modifies the slice content. Through the output, you can see that the updateInput variable data has changed.
summary
Pointers can save the cost of replication, but the impact of dereference and garbage collection should be considered at the same time, so don't use pointers as the first choice for performance optimization.