1、Golang指针

在介绍Golang指针隐式间接引用前,先简单说下Go 语言的指针 (Pointer),一个指针可以指向任何一个值的内存地址 它指向那个值的内存地址,在 32 位机器上占用 4 个字节,在 64 位机器上占用 8 个字节,并且与它所指向的值的大小无关。大致上理解如下:

  • 变量名前的 & 符号,是取变量的内存地址,不是取值;
  • 数据类型前的 * 符号,代表要储存的是对应数据类型的内存地址,不是存值;
  • 变量名前的 * 符号,代表从内存地址中取值 (Dereferencing)。

使用一个指针引用一个值被称为间接引用。

var x int = 42
var p *int = &x
fmt.Println(*p) // 输出:42

2、new函数

在 Go 语言中,new 函数用于动态地分配内存,返回一个指向新分配的零值的指针。它的语法如下:

func new(Type) *Type

其中,Type 表示要分配的内存的类型,new 函数返回一个指向 Type 类型的新分配的零值的指针。但是需要注意的是,new 函数只分配内存,并返回指向新分配的零值的指针,而不会初始化该内存。

注意 1:用new(structName):这个方法得到的是*structName类型,即类的指针类型;用structName{init para}:这个方法得到的是structName类型,即类的实例类型,不是指针。

注意 2:new函数更多细节介绍请参见《Go语言new( )函数》这篇博文。

3、Golang指针隐式间接引用

*p.fieldp.field

3.1 结构体类型指针隐式间接引用

p(*p).XXp.X
package main

import (
    "fmt"
)

type Student struct {
    name   string
    age    int
    weight float32
    score  []int
}

func main(){
   pp := new(Student) //使用 new 关键字创建一个指针
   *pp = Student{"qishuangming", 23, 65.0, []int{2, 3, 6}} 
   fmt.Printf("stu pp have %d subjects
", len((*pp).score)) //按照我们对指针的了解,对Student结构体对象pp显示赋值的话需要使用解引用语法进行赋值,但是实际编码时都会省去*,写法如下行所示。
   fmt.Printf("stu pp have %d subjects
", len(pp.score)) //编译器会自动将指针解引用,并访问结构体中的对应字段,这个过程被称为隐式间接引用。
}

3.2 数组类型指针隐式间接引用

同样指向数组的指针可以隐式解引用数组中的元素。

var arr [3]int
p := &arr
p[0] = 1 // 等价于 (*p)[0] = 1

3.3 切片类型指针隐式间接引用

切片实际上是对底层数组的封装,因此指向切片的指针可以隐式解引用切片中的元素。

s := []int{1, 2, 3}
p := &s
p[0] = 4 // 等价于 (*p)[0] = 4
m := map[string]int{"a": 1, "b": 2}
fmt.Println(m["a"]) // 隐式解引用
type Add func(a, b int) int

func main() {
	var add Add
	add = func(a, b int) int {
		return a + b
	}
	println(add) //0x10cf168

	sum := add(1, 2) // 隐式解引用
	fmt.Println(sum)
}
var i int
p := &i
*p = 1 // 显式解引用指针来修改指针所指向的值
fmt.Println(i) // 输出 1

4、总结

*p.fieldp.field