Golang pointer

5.6 pointer

5.6.1 What is a pointer

  • A pointer is a variable, used to store the memory address of another variable
func main() {
    // 指针地址,指针类型,指针取值
    // &取地址,*根据地址取值
    a := 10
    b := &a
    fmt.Println(*b)

    //指针类型 *int *unit *float *string *array *struct 等
    
    // 指针的定义
    // var 变量名 指针类型
    var p1 *int  //定义空指针
    p1 = &1
}

5.6.2 Array pointers and pointer arrays

  • Array pointer: is a pointer used to store the memory address of the array
func main() {
    arr := [4] int{1, 2, 3, 4}
    fmt.Println(arr)
  
    // 定义一个数组指针
    var p1 *[4] int
    fmt.Println(p1)  // nil 空指针
    fmt.Ptintf("%T\n", p1)  // *[4] int
    
    p1 = &arr1
    fmt.Println(p1)
    fmt.Printf("%p\n", p1)
    fmt.Printf("%p\n", &p1)
    
    // 通过数组指针操作数组
    (*p1)[0] = 100
    // 可以简写为
    // p1[0] = 200
    fmt.Println(arr)  // [100 2 3 4]
}
  • Pointer array: is an array with elements as pointers
func main() {
    a := 1
    b := 2
    c := 3
    d := 4
    arr1 := [4] int{a, b, c, d}
    arr2 := [4] *int{&a, &b, &c, &4}
    fmt.Println(arr1)
    fmt.Println(arr2)
    
    // 操作数组与指针数组的区别
    //arr1[0] = 100
    //fmt.Println(a)
    //fmt.Println(arr1, &arr1[0])  // 值类型,将a,b,c,d的值拷贝过来放到数组中,修改的是数组空间内的数据,与a,b,c,d没有关系
    //fmt.Println(arr2)
    
    *arr2[0] = 1000
    fmt.Println(a)
    fmt.Println(arr1, &arr1[0])
    fmt.Println(arr2, *arr2[0])       // 通过指针数组中的内存地址,修改了a,b,c,d的值,类似于Python列表
    
    b = 2000
    fmt.Println(b)
    fmt.Println(arr1, &arr1[1])
    fmt.Println(arr2, *arr2[1])
}

to sum up:

Array is a value type, copy the value into the memory, the two are independent of each other, and do not affect each other. After the array is modified, the value in the array memory changes, it will not affect the copied source data, the source data changes, nor Affects the array

The slice in Go is a reference to the original array. The two are related to each other. After the value of the slice element is modified, the underlying array associated with it will also be affected. Similarly, changes in the underlying array will also affect the value of the slice.

Lists in Python are reference types. Based on pointer arrays, after modifying variable elements (variable types and immutable types), the referenced source data will also be affected ---

  • Difference between slices in Go and lists in Python
    • Go's slices have members of the same type, and Python lists and tuples do not limit the type.
    • Both languages ​​have [a: b] this kind of slicing operation, and the meaning is similar, but the two parameters of a and b of go cannot be negative numbers, and python can be negative numbers, which is equivalent to counting from the end to the front.
    • Both languages ​​have [a: b: c] this slicing operation, but the meaning is completely different. Go's c means capacity ; and python's c means step size .
    • Python slicing produces new objects , and operations on members of the new object do not affect the old object; go slicing produces references to a portion of the old object , and operations on its members affect the old object.
    • Differences in the underlying implementation
      • Go's slice, the bottom layer is a triple, a pointer, a length, a capacity. The pointer points to a continuous piece of memory, the length is the number of existing members, and the capacity is the maximum number of members. When slicing, it generally does not apply for new memory, but moves the original pointer, and then forms a slice type value with the new length and capacity and returns. That is to say, the slicing operation of go usually shares the memory with the slice that generated the slice. Not only the slices, but also the slices of strings and arrays, usually sharing memory. Of course, there are also anomalies, that is, the capacity provided when slicing is too large, at this time, new memory will be applied for and copied; or the append will exceed the capacity for slicing, so will it. At this time, the new slice will not share memory with the old slice. (If the capacity you provide when slicing / creating is less than the length, it will panic)
      • The list of Python is actually an array of pointers. Of course, there will be some vacancies in the lower layer, but basically it is an array. Slicing them will create a new array, note that it is to create a new array! The list of Python does not have the concept of capacity. This actually reflects the difference between scripting language and compiled language. Although both languages ​​have similar slicing operations; the main goal of python is convenience; the main goal of go is fast (and make up for the shortcomings of discarding pointer operations).

5.6.3 Function pointers and pointer functions

// 函数指针
// Go中函数默认就是一个指针类型,不需要*
func main() {
    var a func()
    a = func1
    a()
}
func func1() {
    fmt.Println("这是func1()")
}

// 指针函数
// 返回值为指针的函数
func main() {
    // arr1是数组,值传递,将func1中返回的arr的值拷贝到arr1中,当func1调用结束,arr被销毁
    arr1 := func1()
    fmt.Printf("arr1的类型:%T,内存地址:%p,值:%v\n",arr1, &arr1, arr1)
    
    // arr2是指针类型,值传递,将func2中返回的arr的内存地址保存到arr2中,arr不会随着func2的结束而销毁(和闭包一样改变了变量的生命周期?)
    arr2 := func2()
    fmt.Printf("arr2的类型:%T,内存地址:%p,值:%v\n",arr2, &arr2, arr2)
}

// 这是普通函数
func func1() {
    arr := [4] int{1, 2, 3, 4}
    return arr
}

// 这是指针函数
func func2() *[4] int {
    arr := [4] int{1, 2, 3, 4}
    return &arr
}        

5.6.4 Pointers as parameters

func main() {
    /*
    指针作为参数
    参数:值传递和引用传递
    
    总结:值传递,拷贝一份,不会影响原数据,但消耗内存
         引用传递通过指针操作数据,会改变原数据,但节省内存(拷贝的数据可能很大)
    */
    n := 10
    // 值传递,func1改变不会影响n,a随着func1结束而被销毁
    func1(n)
    fmt.Println(n)

    // 引用传递,将n的内存地址拷贝到a中,通过*a更改了n,a也会随着func2的结束而被销毁,但n已经改变
    func2(&n)
    fmt.Println(n)
}

func func1(a int) {
    a = 100
    fmt.Println(a)
}

func func1(a *int) {
    *a = 100
    fmt.Println(*a)

Guess you like

Origin www.cnblogs.com/zj420255586/p/12755163.html