指针的定义
指针: 变量的值为156,156值存放的内存空间地址,就是变量b的地址。有变量a的值为b的内存地址空间。这时我们说a指向b。a就变成一个指针。
指针的声明
指针变量的类型为 *T,该指针指向一个 T 类型的变量。
package main import ( "fmt" ) func main() { b := 255 var a *int = &b //定义a为指向变量b的指针。指针int变量类型的指针。这时候a变量存放的是指向b变量内存空间的地址。 fmt.Printf("Type of a is %T\n", a) fmt.Println("address of b is", a) fmt.Println("b values is :",*a) }
& 操作符用于获取变量的地址。* 操作符用于获取这个地址变量存放的地址的那个内存空间的具体值。在以上的例子中就是a指向的地址空间b的地址的内存空间,存储的值156。上面程序的第 9 行我们把 b 的地址赋值给 *int 类型的 a。我们称 a 指向了 b。当我们打印 a 的值时,会打印出 b 的地址。程序将输出:
Type of a is *int address of b is 0x1040a124
指针的解引用
指针的解引用可以获取指针所指向的变量的值。将 a 解引用的语法是 *a。
通过下面的代码,可以看到如何使用解引用。
package main import ( "fmt" ) func main() { b := 255 a := &b fmt.Println("address of b is", a) fmt.Println("value of b is", *a) } 输出: address of b is 0x1040a124 value of b is 255
使用指针来操作地址空间的变量
package main import ( "fmt" ) func main() { b := 255 a := &b //a是一个指针变量。 fmt.Println("address of b is", a) fmt.Println("value of b is", *a) *a++ //*a 就是具体的变量值,可进行递增。 fmt.Println("new value of b is", b) } 输出: address of b is 0x1040a124 value of b is 255 new value of b is 256
指针的特性
- 指针的零值,nil
- 作为值的形式被传递,执行的变量及作用不会改变
- 指针变量,存放的是空间地址,不是具体的值。要修改时,需先解引用。
- 指针变量不能进行运算
指针零值,示例:
package main import ( "fmt" ) func main() { a := 25 var b *int if b == nil { fmt.Println("b is", b) b = &a fmt.Println("b after initialization is", b) } }
向函数传递指针
package main import ( "fmt" ) func change(val *int) { *val = 55 //val变量存放的是一个空间地址。而想修改具体的值,需先解引用。 } func main() { a := 58 fmt.Println("value of a before function call is",a) b := &a change(b) fmt.Println("value of a after function call is", a) } 输出: value of a before function call is 58 value of a after function call is 55
指针的使用场景
基于指针的特性,可以有几种场景下使用指针。
- 函数传递指针、指针类型
函数传递切片
package main import ( "fmt" ) func modify(sls []int) { //接收一个切片。切片内部其实存储的是一个指针变量。 sls[0] = 90 //修改切片值 } func main() { a := [3]int{89, 90, 91} modify(a[:]) //传递切片进去,并修改切片内容,会反馈到a变量上。 fmt.Println(a) }
函数传递map
在golang当中都是值传递,而不是指针传递。 但是当一个变量是指针变量时。进行值传递,也就是把这个指针变量传递出去。这时候接收到这个指针值的变量,也就能够指向原先的值存储空间。
package main import ( "fmt" ) func main(){ a := make(map[string]int) //这里面都是值类型,所以直接传递是可行的。 b := make(map[string]*int) //这里面map对应key值存储的是地址空间。当 funcName(b) //这样传递的是b的具体值。而map里面key对应存储的是地址空间。那么此时在函数内部区修改b中的值。修改同样会反应在函数外部。 }
小结:
- 指针(内存地址):指向内存的那个存储空间。指针地址变量,变量内部存放的是指向另一个变量的地址空间。
- 指针不支持运算。
- 函数接收指针及指针变量,函数的修改会反应在函数外部。
- 函数使用场景:传递切片,传递指针类型。
- &取变量指针地址。*解指针变量地址(取指针变量指向的内存空间)