🏆个人专栏
🤺 leetcode
🧗 Leetcode Prime
🏇 Golang20天教程
🚴♂️ Java问题收集园地
🌴 成长感悟
欢迎大家观看,不执着于追求顶峰,只享受探索过程
Golang 开发实战day11 - 按值传递
在Go语言的世界里,变量就像一个个精灵球,存储着各种各样的数据。而赋值就像将数据从一个宝箱(精灵球)传递到另一个宝箱(精灵球)的过程。但是,你知道吗?Go语言中的赋值操作其实暗藏着玄机,它可以分为按值传递和按引用传递两种方式。今天,就让我们一起走进Go语言的赋值世界,揭秘按值传递的秘密!
按值传递:复制数据,开启独立旅程
当我们使用按值传递时,就像大家最熟悉的硬盘备份一样,将老硬盘中的资源复制一份,然后将复制传递给大容量的新硬盘中。这不言而喻了吧,原来的硬盘资源完好无损,而新大容量硬盘中也拥有了相同的资源,但它们是两个完全独立的东西。
1. 变量分组
A 组 | B 组 |
---|---|
Strings | Slices |
Ints | Maps |
Floats | Slices |
Booleans | |
Arrays | |
Structs |
这些结构都是我们需要了解的,理解并掌握这两组类型的差异以及它们的工作方式对于我们今后工作还是比较重要的。其中Structs是比较特别的结构体,需要后期我们重点了解。下面是一些示例
2. 示例代码
func updateName(x string) {
x = "大雄"
}
func main() {
// 组A : strings, ints, bools, floats, arrays, structs
name := "小叮当"
updateName(name)
fmt.Println(name)
}
Output:
代码中我声名一个name的变量,它是字符串类型。之后创建了一个updateName方法,可以传入string类型的x,以便我们之后进行调用。但是我们看到输出内容,“小叮当”并没有被覆盖掉。
这是为什么呢?每次我们将一个值或一个变量传递到函数中的时候,都会创建一个变量的副本。所以updateName()中的name,并不是最开始的name;所以在update中更新的也只是副本的name,并不是我们原始的name值。是不是有些晕?没关系,那就在自己的编辑器里跑一遍就会理解了!
3. 计算机中的存储
当然,这里更是为了方便大家理解,给出了上图说话
这里说明原始的name在内存中的0x0002位置,而传递到方法中的副本x位置则是在0x0003位置。所以才导致不会改变原始值。
那么如何改进让它进行修改呢?
func updateName(x string) string {
x = "大雄"
return x
}
func main() {
// 组A : strings, ints, bools, floats, arrays, structs
name := "小叮当"
name = updateName(name)
fmt.Println(name)
}
Output:
这里我们可以看到原始数据已被覆盖了!
接下来我们以组B来作为示例
func updateMenu(y map[string] float64) {
y["巧克力派"] = 8
}
func main() {
// 组 B -> slices, maps, functions
menu := map[string] float64{
"拿铁": 9.9,
"汉堡": 13.9,
}
updateMenu(menu)
fmt.Println(menu)
}
Output:
不同于string的单独项目,这里menu是一个map,由于最初没有巧克力派,所以在调用UpdateMenu后,map中加入了巧克力派的信息。
4. 按值传递的优点:
- 安全性高:由于不会影响源变量,因此可以避免意外修改源数据。
- 易于理解:赋值操作直观易懂,不会引起混淆。
5 按值传递的缺点:
- 效率低:对于大型数据结构,按值传递可能会导致大量的内存复制,降低运行效率。
6. 总结:
按值传递是一种安全、易于理解的赋值方式,适用于传递基本类型数据和小型数据结构。但对于大型数据结构,按值传递可能会导致效率低下,因此建议使用按引用传递的方式。
请记住,赋值操作看似简单,但背后却蕴含着Go语言的赋值机制。理解按值传递和按引用传递的差异,可以帮助你更有效地编写Go语言代码。