指针
概念
- Go语言的指针和C语言一样也是用来保存地址的变量
var p *int
普通指针
package main
import "fmt"
func main() {
var num int = 666
var p *int = &num // 定义指针p 保存num的内存地址
fmt.Println("&num = ",&num) // &num = 0xc042060080
fmt.Println(" p = ",p) //p = 0xc042060080
// *p = 666 和C语言一样可以通过*P 去访问和修改 储存的空间
(*p) = 888
fmt.Println("num = ",num) // num =888
}
指向数组的指针
注意点
- GO语言中只有数据类型一样 才能赋值
- go语言中&数组名 和数组首元素保存的地址是一样,但是数据类型是不一样,所以Go语言中指向数组的指针只能通过
&数组名
来创建指针
- 可以通过指针来间接操作数组
- 指向数组的指针不支持+1操作
package main
import "fmt"
func main() {
var arr [3]int = [3]int{1,2,3}
//获取数组的地址
fmt.Printf("%p\n",arr) // arr = %!p([3]int=[1 2 3])
fmt.Printf("%p\n",&arr) // &arr= 0xc04200e360
fmt.Printf("%p\n",&arr[0]) // &arr[0] = 0xc04200e360
// 获取数组的数据类型
fmt.Printf("%T\n",&arr) // &arr = *[3]int
fmt.Printf("%T\n",&arr[0]) // &arr[0] = *int
// 所以只能创建*[3]int 的指针类型来保存数组的地址 切只能通过&arr来赋值
var pArr *[3]int = &arr
fmt.Println((*pArr)) // *parr = [1 2 3]
}
指向切片的指针
- 切片的底层是一个结构体,这个结构体有一个属性时指针类型
package main
import "fmt"
func main() {
var sce []int = []int{1,2,3}
fmt.Printf("%p\n",sce) // sce = 0xc04205e0c0
fmt.Printf("%p\n",&sce) // &sce = 0xc04205a3e0
fmt.Printf("%T\n",sce) // sce = []int
fmt.Printf("%T\n",&sce) // &sce = *[]int
}
- 如果打印sce 得到的是结构体中指向数组的那个指针保存的地址
- 如果打印&sce的,得到的是这个切片结构体自己本身的内存地址
- sce的数据类型是 [ ]int
- &sce的数据类型是 *int[ ] , 所以创建指向切片的指针,需要通过&sce来创建
package main
import "fmt"
func main() {
var sce []int = []int{1,2,3}
fmt.Printf("%p\n",sce) // sce = 0xc04205e0c0
fmt.Printf("%p\n",&sce) // &sce = 0xc04205a3e0
var p *[]int = &sce
fmt.Printf("%p\n",p) // p = 0xc04205a3e0
fmt.Printf("%p\n",*p) // *p = 0xc04205e0c0
//结论 p = &sce *p = sce
(*p)[1] = 666
fmt.Println("sce = ",sce) // sce = [1 666 3]
}
结论
- P == &sce 访问结构体, *P==sce 访问指针指向的数组
指向字典的指针
package main
import "fmt"
func main() {
var dict map[int]int = map[int]int{0: 7, 1: 9, 2: 14}
//创建指向字典的指针
var p *map[int]int
p = &dict
(*p)[0] = 99 // 通过指针修改字典第1个key所对应的值
fmt.Println("dict = ", dict) // dict = map[0:99 1:9 2:14]
}
- 注意点
指向切片的指针也只能通过 (*P) 来访问和修改切片
指向结构体的指针
package main
import "fmt"
func main() {
type Person struct{
name string
age int
Characteristic string
}
// 创建结构体变量
var footballSart Person = Person{"小罗",32,"技术"}
//创建指向结构体的指针
var p *Person = &footballSart
p.name = "范佩西"
p.age = 33
(*p).Characteristic = "射门"
fmt.Println("footballStar = ",footballSart) //footballStar = {范佩西 33 射门}
}
- 指向结构体的指针可以通过p和*p来访问和修改结构体的属性
指针作为函数的参数和返回值
package main
import "fmt"
func main() {
num := 123
fmt.Println("打印前num = ",num) // num = 123
change(&num)
fmt.Println("打印后num = ",num) // num = 666
}
func change(value *int){
*value = 666
}
- 返回值
如果指针作为返回值,指向的是一个局部变量的话 不建议这样写 因为运行完局部变量就释放了