The pointer of Go language (pointer) detailed explanation

Many people may think that pointers are the same as cursors in spark, especially the values ​​in the array are taken according to the subscripts. In fact, they are not. Here, the pointers in the Go language represent: a pointer variable points to a The memory address of the value. Similar to variables and constants, you need to declare pointers before using them.
The pointer declaration format is as follows:

var var_name *var-type

var-type is the pointer type, var_name is the name of the pointer variable, and * is used to specify that the variable is used as a pointer.

The following is a valid pointer declaration:

var a *int        // 指向整型
var b *float32    // 指向浮点型 

Pointer can be divided into two core concepts in Go language:

  • The type pointer allows modification of the data of this pointer type. The pointer can be used directly to transfer data without copying the data. The type pointer cannot be offset and operated.
  • A slice consists of the original pointer to the starting element, the number of elements, and the capacity.

Benefiting from such constraints and splits, the pointer type variables of the Go language have the characteristics of efficient pointer access without pointer offset, thus avoiding the problem of illegally modifying key data. At the same time, garbage collection is also easier to retrieve and reclaim pointers that will not be offset.

Slices have more powerful features than raw pointers and are more secure. When the slice is out of bounds, it will report a crash during runtime and hit the stack, while the original pointer will only crash.

To understand pointers, you need to know several concepts: pointer address, pointer type, and pointer value.

Pointer address and pointer type

A pointer variable can point to the memory address of any value. The memory address of the value it points to occupies 4 or 8 bytes on 32 and 64-bit machines respectively, and the size of the occupied bytes has nothing to do with the size of the value pointed to.

When a pointer is defined and not assigned to any variable, its default value is nil. Pointer variables are usually abbreviated as ptr.

Each variable has an address at runtime, and this address represents the location of the variable in memory. In Go language, add the & operator (prefix) in front of the variable name to get the memory address of the variable (address operation), the format is as follows:

ptr := &a

Among them, a represents the name of the variable whose address is taken, and the address of variable a is received using variable ptr. The type of ptr is *T, which is called the pointer type of T, and * represents the pointer.
Pointer use process:

  • Define pointer variables.
  • Assign a value to the pointer variable.
  • Access the value of the address pointed to in the pointer variable.

Add * (prefix) in front of the pointer type to get the content pointed to by the pointer.

package main

import "fmt"

func main() {
    
    

   var a int= 20  /* 声明实际变量 */
   var ip *int        /* 声明指针变量 */

   ip = &a  /* 指针变量的存储地址 */

   fmt.Printf("a 变量的地址: %x\n", &a  )

   /* 指针变量的存储地址 */

   fmt.Printf("ip 变量储存的指针地址: %x\n", ip )


   /* 使用指针访问值 */

   fmt.Printf("*ip 变量的值: %d\n", *ip )

}

Results of the:

a 变量的地址: 20818a220
ip 变量储存的指针地址: 20818a220
*ip 变量的值: 20

Every variable has an address, and the value of the pointer is the address.

Null pointer

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

The nil pointer is also called a null pointer.

Conceptually, nil is the same as null, None, nil, and NULL in other languages. They all refer to zero or empty values.

Example:

package main

import "fmt"


func main() {
    
    

   var  ptr *int

   fmt.Printf("ptr 的值为 : %x\n", ptr )

}

Results of the:

ptr 的值为 : 0

Null pointer judgment:

if(ptr != nil)     /* ptr 不是空指针 */
if(ptr == nil)    /* ptr 是空指针 */

Get the value pointed to by the pointer from the pointer

After using the & operator to take the address of the ordinary variable and get the pointer of the variable, you can use the * operator on the pointer, which is the pointer value:

package main

import  "fmt"
 
func main() {
    
       

     // 准备一个字符串类型    
     var str = "Malibu Point 10880, 90265"   
 
     // 对字符串取地址, ptr类型为*string    
     ptr := &srt  
  
     // 打印ptr的类型   
     fmt.Printf("ptr type: %T\n", ptr)   
   
     // 打印ptr的指针地址,地址每次运行都会发生变化   
     fmt.Printf("address: %p\n", ptr)   
      
      // 对指针进行取值操作,变量 value 的类型为 string   
      value := *ptr   
       
      // 取值后的类型    
      fmt.Printf("value type: %T\n", value)   
         
      // 指针取值后就是指向变量的值  
      fmt.Printf("value: %s\n", value)
}

operation result:

ptr type: *string

address: 0xc0420401b0

value type: string

value: Malibu Point 10880, 90265

Analysis:

The address operator & and the value operator * are a pair of complementary operators, & takes out the address, and * takes out the value pointed to by the address according to the address.

The relationship and characteristics of variables, pointer addresses, pointer variables, access addresses, and values ​​are as follows:

  • Use the & operator to take the address of the variable to get the pointer variable of this variable.
  • The value of the pointer variable is the pointer address.
  • Use the * operator to get the value of the pointer variable to get the value of the original variable pointed to by the pointer variable.

Use pointer to modify value

Not only can the value be accessed through the pointer, but the value can also be modified.

The pointer can also be used for value exchange, the code is as follows:

package main

import "fmt"

// 交换函数
func swap(a, b *int) {
    
       
 
    // 取a指针的值, 赋给临时变量t    
    t := *a    
    
    // 取b指针的值, 赋给a指针指向的变量    
    *a = *b    
 
    // 将a指针的值赋给b指针指向的变量    
    *b = t
}


 func main() {
    
    
   
    // 准备两个变量, 赋值1和2   
    x, y := 1, 2    
 
    // 交换变量值    
    swap(&x, &y)    
  
    // 输出变量值    
    fmt.Println(x, y)      //结果 2  1
  
}

Analysis:

  • Define an exchange function, the parameters are a, b, the type is *int pointer type.
  • Take the value of pointer a and assign the value to variable t, which is of type int at this time.
  • Take the pointer value of b and assign it to the variable pointed to by pointer a. Note that the meaning of *a at this time is not to take the value of a pointer, but to "a variable pointed to".
  • Assign the value of t to the variable pointed to by pointer b.
  • Prepare two variables x and y, assign the values ​​1 and 2, respectively, and the type is int.
  • Take the addresses of x and y as parameters and pass them to the swap() function to call.
  • When the exchange is complete, the values ​​of x and y are output.

When the * operator is used as an rvalue, the meaning is to take the value of the pointer. When it is used as an lvalue, that is, when it is placed on the left side of the assignment operator, it represents the variable pointed to by a pointer. In fact, to sum up, the fundamental meaning of the * operator is to manipulate the variable pointed to by the pointer.

When the operation is on the right value, the value of the pointed variable is taken, and when the operation is on the left value, the value is set to the pointed variable.

If the exchange operation in the swap() function is a pointer value, it will be another situation:

package main

import "fmt"

func swap(a, b *int) {
    
      
   b, a = a, b
  
}

func main() {
    
        

   x, y := 1, 2    
   
   swap(&x, &y)    
  
   fmt.Println(x, y)    //结果 1   2  
}

The results showed that the exchange was unsuccessful. The swap() function in the above code exchanges the addresses of a and b. After the exchange, the variable values ​​of a and b are indeed exchanged. But the two variables associated with a and b are not actually related.

Use pointer variables to obtain command line input information

The built-in flag package of Go language implements the parsing of command line parameters.

The following code defines some command-line instructions and corresponding variables in advance, and enters the corresponding parameters at runtime, after parsing the flag package, the command-line data can be obtained.

package main

// 导入系统包

import (    
   "flag"    
   "fmt"
)

// 定义命令行参数
var mode = flag.String("mode", "", "process mode")

func main() {
    
        

   // 解析命令行参数   
   flag.Parse()    

   // 输出命令行参数    
   fmt.Println(*mode)
 }

Put this code in the file named main.go, and then run this file:

go run main.go --mode=fast

Results of the:

fast

Analysis:

Define the command line parameters, through flag.String, define a mode variable, the type of this variable is *string. The following three parameters are as follows:

  • Parameter name: Use this name when entering parameters on the command line.
  • The default value of the parameter value: corresponding to the variable type of the function used by flag, String corresponds to character string, Int corresponds to integer, Bool corresponds to Boolean, etc.
  • Parameter description: When using -help, it will appear in the description.

Parse the command line parameters and write the result into the variable mode.

Output command line parameters and print the variable pointed to by the mode pointer.

Since a command line parameter named mode has been registered with flag.String before, the bottom layer of flag knows how to parse the command line and assign the value to the mode*string pointer. After Parse is called, there is no need to get the value from flag, but Get the final value through the mode pointer registered by yourself. The code running process is shown in the figure below:

Insert picture description here

Another way to create pointers-new() function

Go language also provides another way to create pointer variables, the format is as follows:

new(类型)

Example:

str := new(string)
*str = "hello"
fmt.Println(*str)

The new() function can create a pointer of the corresponding type. The creation process will allocate memory and the created pointer points to the default value.

Guess you like

Origin blog.csdn.net/zp17834994071/article/details/108647871