【go学习】地址符&与指针*的差别

背景

项目中开始用Go,最近写了一下Demo,发现语法还是非常好用,大部分比Java还是简洁很多,也有一些很细节的约定。比如:

  • 字母大小写控制是全包还是本包内访问
  • 变量定义了就一定要使用,否则就会编译不通过等等

更好的就是方法可以返回多个值,这个跟Java比较就是减少很多的封装。因为Go的线程模型特点,用来写一些需要高并发、高性能的项目还是非常好的。所以,趁这个机会也好好的深入了解下。现在也是把PythonPHPGo等都学习一遍,每种语言都有它的优缺点,其实都还挺不错的。

针对于Go语言里:&*的区别,什么时候该用什么做一个总结。

指针

我们经常会听到别人说Go是值传递,某某某是引用传递,某某某是指针传递,等等各种各样的说法。

那么首先他们的区别是什么呢?什么是指针?指针其实也是一个变量,只不过这个变量里面存的不是intfloatstruct,而是一个地址address,然后在这个address上所存储的数据可以通过指针来被阅读到。

OK,指针变量存储的是一个地址,地址从哪里来的?那就得问一个变量的地址怎么取得呢?在变量前面加上一个&符号就行。

好的,指针变量存储了这个地址了,那这个地址所存储的值怎么被阅读到呢?也就是指针所指向的值怎么拿到呢?在指针变量前面加上一个*符号就行。

怎么修改指针所指向的数据呢?在前面加上*符号之后再赋一个新的值就可以了。

我们来看一个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import "fmt"

func main() {
a := "vernonchen"
b := &a

fmt.Println("a的值", a)
fmt.Println("a的地址", b)
fmt.Println("b的值", b)
fmt.Println("b的指针指向", *b)

*b = "not vernonchen"
fmt.Println("修改后,b的指针指向", *b)
}

执行输出的结果是

1
2
3
4
5
a的值 vernonchen
a的地址 0xc00008e1e0 // 使用的是b
b的值 0xc00008e1e0
b的指针指向 vernonchen //使用的是指针
修改后,b的指针指向 not vernonchen // 重新指向新的值

指针的作用

为什么要有指针这个东西?它有什么关键性的作用呢?

我们来看下面这段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import "fmt"

type User struct {
userName string
}

func modify(user User) {
user.userName = "vernonchen2222"
}

func modifyWithPoint(user *User) {
user.userName = "vernonchen3333"
}

func main() {

user := User{userName: "vernonchen"}

fmt.Println("userName = ", user.userName)

modify(user)

fmt.Println("userName = ", user.userName)

modifyWithPoint(&user)

fmt.Println("userName = ", user.userName)
}

执行完后,输出的结果:

1
2
3
userName =  vernonchen
userName = vernonchen // 没有被替换
userName = vernonchen3333 // 被替换

所以指针的作用:

  1. 指针不但可以帮助函数内部修改外部变量的值,还可以帮助我们在任何地方修改其所指向数据的值;

  2. 传递指针参数可以节省拷贝大结构体的内存开销;

总结

  • 指针也是变量,只不过存储的是地址
  • 通过指针可以去修改其指向数据的值
  • 指针可以帮助我们在任何地方修改其所指向数据的值
  • 传递指针参数可以节省拷贝大结构体的内存开销

参考地址

如果大家喜欢我的文章,可以关注个人订阅号。欢迎随时留言、交流。如果想加入微信群的话一起讨论的话,请加管理员微信号:chengcheng222e,他会拉你们进群。

简栈文化服务订阅号