go语言指针 原文参考:https://www.liwenzhou.com/posts/Go/07_pointer/
//指针
func main() {
a := 10
b := &a //这里b是一个int类型,存放的地址是一个16进制数字//b变量的内存地址中存的是a的指针
fmt.Printf("a:%d,prt:%p\n", a, &a) //这里%d打印的是a的值,%p打印的是a变量的值对应的内存地址,a==>10==>&a 这其中有上下层关系.
fmt.Printf("b:%p,type:%T\n", b, b) //%p打印的是b内存地址中存的a的内存地址,打印b的类型.
fmt.Println(&b) //这里打印变量b的指针,
}
输出结果:
C:\Users\34826\AppData\Local\Temp\___go_build_code_oldboy_com_studygolang_05lesson5_lesson1.exe #gosetup
a:10,prt:0xc0000a2058
b:0xc0000a2058,type:*int
0xc0000cc018
指针取值
//指针取值
func main() {
a := 10
b := &a //这里&a是一个十六进制的int类型值
fmt.Printf("type of b:%T\n", b) //这里b对应的是一个&a那么表示b是一个指针类型,int类型的指针
c := *b //这里将取值后的b赋值给c,那么c就是一个int类型
fmt.Printf("type of c:%T\n", c) //这里打印c的类型为int
fmt.Printf("value of c:%v\n", c) //c的值是10,取出的是b内存地址中存的a的内存地址.a内存地址对应的值是10.那么最终取值就是10,(反正他喵的记住*代表取值就对了.取出来的不是内存地址.是值
}
输出结果
C:\Users\34826\AppData\Local\Temp\___go_build_code_oldboy_com_studygolang_05lesson5_lesson1.exe #gosetup
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) //go语言传值是通过副本进行传递的.呢么当副本传递进函数之后处理过后的值跟之前定义变量的值是不冲突的.这俩不是一个东西.好比传值的时候拷贝了一个进去,
modify2(&a)//这里传值是传递的指针类型.表示将a变量的值的内存地址传递进了函数中.然后函数接受的也是指针类型,那么在处理完成后a的值就由原来的10,变成了100.
fmt.Println(a)
//输出结果
C:\Users\34826\AppData\Local\Temp\___go_build_code_oldboy_com_studygolang_05lesson5_lesson1.exe #gosetup
10
100
new和make的用法1
//先看一个错误的例子
func main() {
var a *int //这里声明了a是一个*int类型,也就是说a是一个指针类型
*a = 100 //这里的用法就是错误的.*a是用来取内存地址中存的指针的值的,而不能直接将*a进行赋值
fmt.Println(*a) //这里打印的是a内存地址中存的值.很明显是不行的
var b map[string]int //这里尚未初始化map,所以内存中并未分配内存地址.
b["沙河娜扎"] = 100 //所以这里的复制是不正确的.
fmt.Println(b) //打印也是失败的.
}
输出错误结果
D:\Go\bin\go.exe build -o C:\Users\34826\AppData\Local\Temp\___go_build_main_go.exe D:/Go/Go/src/code.oldboy.com/studygolang/05lesson5/lesson1/main.go #gosetup
C:\Users\34826\AppData\Local\Temp\___go_build_main_go.exe #gosetup
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x1 addr=0x0 pc=0xb655aa]
goroutine 1 [running]:
main.main()
D:/Go/Go/src/code.oldboy.com/studygolang/05lesson5/lesson1/main.go:983 +
0x2a
-----------------------------------------------------
//正确过程
func main() {
var a *int //同样a 是一个int类型的指针,只能存指针类型.
c := 100
a = &c //将c变量的内存地址存入到预先声明好的a内存地址中.
fmt.Println(*a) //打印a输出正确.
var b = make(map[string]int) //这里map进行初始化完成,在内存中分配了内存空间,所以后续才可以进行键值对写入操作
b["沙河娜扎"] = 100 //这里直接写入键值对.
fmt.Println(b) //打印成功
输出结果如下
C:\Users\34826\AppData\Local\Temp\___go_build_main_go.exe #gosetup
100
map[沙河娜扎:100]
}
new函数的使用
func main() {
a := new(int) //a初始化成一个*int类型,是一个指针
b := new(bool) //同理b初始化成一个bool类型,也是一个指针.
fmt.Printf("%T\n", a) // *int
fmt.Printf("%T\n", b) // *bool
fmt.Println(*a) // 这里取到的值是0.int类型默认的值就是0(记住啦* 是他娘的取值用的.)
fmt.Println(*b) // false 同理bool默认值是false (取值,取的是new函数指针定义号类型的零值)
var c *int //这里只声明一个c 为一个int类型的指针,并未初始化,那么就不会在内存中分配空间
c = new(int) //这里将c 初始化成一个指针类型.
*c = 10 //取值c的内存地址,然后将10赋值给这个内存地址
fmt.Println(*c) //取值c并打印
}
输出结果
C:\Users\34826\AppData\Local\Temp\___go_build_code_oldboy_com_studygolang_05lesson5_lesson1.exe #gosetup
*int
*bool
0
false
10
其实new函数用的比较少.
说明:
- 二者都是用来做内存分配的。
- make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
- 而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。