10.指针
go
语言是值传递, 例子如下
func main() {
// a := 100
// b := &a // 取a地址,将指针保存到b中
// 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)
x := 10
changeValue(x)
fmt.Println("x:", x)
changeValue2(&x)
fmt.Println("x:", x)
}
func changeValue(x int) {
x = 100
}
func changeValue2(y *int) {
*y = 100
}
/*
x: 10
x: 100
*/
go
语言指针不同于c/c++
, 不能进行偏移和运算,是安全指针
指针:任何程序数据载入内存后,在内存都有他们的地址,这就是指针。
为了保存一个数据在内存中的地址,就需要指针变量。
10.1 基本操作
&:
取地址*:
根据地址取值
Go
语言中的值类型(int、float、bool、string、array、struct
)都有对应的指针类型,如:*int
、*int64
、*string
等
- 指针变量的值是指针地址。
- 对指针变量进行取值
*
操作,可以获得指针变量指向的原变量的值
ptr := &temp
temp
:被取地址的变量, 类型为*T
ptr
:用于接受地址的变量,称作指针类型, 类型为*T
a := 10
b := &a
fmt.Printf("a:%v, ptr a:%p\n", a, &a)
fmt.Printf("b:%v, ptr b:%p\n", b, b)
fmt.Printf("b:%v, ptr b:%p\n", b, &b)
/*
a:10, ptr a:0xc000016088
b:0xc000016088, ptr b:0xc000016088
b:0xc000016088, ptr b:0xc000006028
*/
a := 100
b := &a // 取a地址,将指针保存到b中
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:100
*/
10.2make
, new
分配内存空间
var a *int
// a := new(int)就行了
*a = 1000
fmt.Println(*a)
var b map[string]int
b["xs"] = 1000
fmt.Println(b)
第一段:/*
var a *int只是声明了一个指针变量a但是没有初始化,指针作为引用类型需要初始化后才会拥有内存空间,才可以给它赋值。
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x1 addr=0x0 pc=0x9cc516]
goroutine 1 [running]:
main.main()
D:/Go/learn/2/src/ptr.go:7 +0x16
exit status 2
*/
第二段:/*
panic: assignment to entry in nil map
goroutine 1 [running]:
main.main()
D:/Go/learn/2/src/ptr.go:11 +0x2e
exit status 2
*/
这两段都会报错
第一段:var a *int
只是声明了一个指针变量a但是没有初始化,指针作为引用类型需要初始化后才会拥有内存空间,才可以给它赋值。
对于引用类型的变量,我们在使用的时候不仅要声明它,还要为它分配内存空间,否则值就没办法存储。而对于值类型的声明不需要分配内存空间,是因为它们在声明的时候已经默认分配好了内存空间。
10.2.1new
new函数不太常用,使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值。
a := new(int)
fmt.Printf("%T, %v, %d", a, a, *a)
/*
*int, 0xc000016088, 0
*/
var a *int
// a := new(int)就行了
*a = 1000
fmt.Println(*a)
10.2.2make
make
也是用于内存分配的,区别于new
,它只用于slice、map以及chan
的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。
make(map[string]int, 10)
new, make
区别
- 都是用来做内存分配的。
make
只用于slice、map
以及channel
的初始化,返回的还是引用类型本身;- 而
new
用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。