Go的指针
Go的指针
指针变量
:保存指针地址
Go语言中的指针不能进行偏移和运算
两个符号:&
(取地址)和*
(根据地址取值)
指针地址和指针类型
每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置
Go语言中的值类型(int、float、bool、string、array、struct)都有对应的指针类型
取变量指针
ptr := &v // v的类型为T
- v:代表被取地址的变量,类型为 T
- ptr:用于接收地址的变量,类型为*T,称为T的指针类型,*代表指针
func main() {
a := 10
b := &a
fmt.Printf("a: %d, ptr: %p\n", a, &a)
fmt.Printf("b: %p, type od b: %T\n", b, b)
fmt.Println(&b)
}
// a: 10, ptr: 0xc000014080
// b: 0xc000014080, type od b: *int
// 0xc00000c028
指针取值
新变量对普通变量使用&操作符取地址后会获得这个普通变量的地址
新变量保存的是地址,新变量是一个指针
*新变量 可以取到新变量这个指针所指向的值
func main() {
a := 10
b := &a
fmt.Printf("type of b: %T\n", b)
c := *b
fmt.Printf("type of c: %T\n", c)
fmt.Printf("value of c: %v\n", c)
}
// type of b: *int
// type of c: int
// value of c: 10
取地址操作符&
和取值操作符*
是一对互补操作符
&
取出地址,*
根据地址取出地址指向的值
变量、指针地址、指针变量、取地址、取值 :
- 取地址(&)操作,让新变量变成指针变量
- 指针变量的值是指针地址
- 对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值
指针传值
func modify1(x int) {
x := 100
}
func modify2(x *int) {
*x = 100
}
func main() {
a := 10
modify1(a)
fmt.Println(a) // 10
modify2(&a)
fmt.Println(a) // 100
}
new和make
错误事例
func main() {
var a *int
*a = 100
fmt.Println(*a)
var b map[string]int
b["hello"] = 100
fmt.Peintln(b)
}
上面的代码会引发panic
var a *int
只是声明了一个指针变量a但是没有初始化
指针作为引用类型需要初始化后才会拥有内存空间,才可以给它赋值
-
Go语言中对于引用类型的变量,我们在使用的时候不仅要声明它,还要为它分配内存空间,否则我们的值就没办法存储
-
对于值类型的声明不需要分配内存空间,是因为它们在声明的时候已经默认分配好了内存空间
-
Go语言中new和make是内建的两个函数,主要用来分配内存
new
func new(Type) *Type
- Type表示类型,new函数只接受一个参数,这个参数是一个类型
- *Type表示类型指针,new函数返回一个指向该类型内存地址的指针
new函数不太常用,使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值
func main() {
a := new(int)
b := new(bool)
fmt.Printf("%T\n", a)
fmt.Printf("%T\n", b)
fmt.Println(*a)
fmt.Println(*b)
}
// *int
// *bool
// 0
// false
var声明指针变量后,需要用new初始化
func main() {
var a *int
a = new(int)
*a = 10
fmt.Println(*a)
}
make
make只用于slice、map以及chan
的内存创建,而且它返回的类型就是这三个类型本身
func main() {
var b map[string]int // 声明b是一个map变量
b = make(map[string]int, 10) // 初始化map变量
b["age"] = 25 // 赋值
fmt.Println(b) // map[age:25]
}
new和make的区别
- 都是用来分配内存的
- make只用于
slice、map以及chan
的内存创建,而且它返回的类型就是这三个类型本身 - 而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针