英文:
Why do some values get updated in a func and others don't?
问题
比较这两个例子:
(来自:https://goinbigdata.com/golang-pass-by-pointer-vs-pass-by-value/)
package main
import "fmt"
type Person struct {
firstName string
lastName string
}
func changeName(p Person) {
p.firstName = "Bob"
}
func main() {
person := Person {
firstName: "Alice",
lastName: "Dow",
}
changeName(person)
fmt.Println(person)
}
上面的代码返回 {Alice Dow}
,所以结构体没有改变。
现在看这个例子:
package main
import "fmt"
func main() {
slice := []string{"a", "b", "c"}
fmt.Println(slice)
updateSlice(slice)
fmt.Println(slice)
}
func updateSlice(slice []string) []string {
slice[0] = "x"
return slice
}
输出结果是:
[a b c]
[x b c]
所以函数 updateSlice
改变了切片。
有人能解释一下这两个例子的区别吗?
英文:
Compare these two examples
(from: https://goinbigdata.com/golang-pass-by-pointer-vs-pass-by-value/)
package main
import "fmt"
type Person struct {
firstName string
lastName string
}
func changeName(p Person) {
p.firstName = "Bob"
}
func main() {
person := Person {
firstName: "Alice",
lastName: "Dow",
}
changeName(person)
fmt.Println(person)
}
The code above returns {Alice Dow}
so the struct is not changed.
Now in this example
package main
import "fmt"
func main() {
slice := []string{"a", "b", "c"}
fmt.Println(slice)
updateSlice(slice)
fmt.Println(slice)
}
func updateSlice(slice []string) []string {
slice[0] = "x"
return slice
}
the output is
[a b c]
[x b c]
so the slice was changed by the func updateSlice
.
Would someone explain the difference?
答案1
得分: 1
切片是对底层数组的引用。因此,当你将切片传递给函数时,实际上是传递了对底层数组的引用。
在第一个代码片段中,当你调用changeName(person)
时,Go 会创建一个 person 结构体的副本并将其传递给changeName
函数。
func main() {
person := Person {
firstName: "Alice",
lastName: "Dow",
}
changeName(person) //Go 会传递 person 结构体的副本
fmt.Println(person)
}
在 Go 中,切片只是对底层数组的引用;切片不是数组。在第二个示例中,updateSlice(slice)
也是按值传递。它创建了slice
的副本。然而,在这种情况下,Go 创建的是对数组的引用的副本。这意味着,“slice 的副本”和“slice”都指向同一个底层数组。
func main() {
slice := []string{"a", "b", "c"}
fmt.Println(slice)
//这里仍然是按值传递,但传递的值是一个引用
//即复制的值仍然指向同一个底层数组
updateSlice(slice)
fmt.Println(slice)
}
如果你想比较一下 Go 中的切片与其他语言(如 JavaScript 或 Ruby)中的切片函数的工作方式,请不要这样做(我在学习 Go 时犯过这个错误,所以提一下)。
为了更加明确,当你执行slice[0] = "x"
时,你并没有修改切片本身;你修改的是切片所引用的底层数组。
英文:
A slice is a reference to an underlying array. So, when you pass a slice to a function, you are essentially passing a reference to the underlying array.
In the first code snippet, when you call changeName(person)
, Go will create a copy of the person struct and pass it to the changeName
function.
func main() {
person := Person {
firstName: "Alice",
lastName: "Dow",
}
changeName(person) //Go will pass a copy of the person struct
fmt.Println(person)
}
A slice in Go is just a reference to an underlying array; a slice is not an array. In the second example, updateSlice(slice)
also passes by value. It creates a copy of slice
. However, in this case, Go is creating a copy of a reference to an array. That means, that the "copy of slice" and "slice" are both pointing to the same underlying array.
func main() {
slice := []string{"a", "b", "c"}
fmt.Println(slice)
//Go is still passing by value here, but the value passed is a reference
// i.e. the copied value still points to the same underlying array
updateSlice(slice)
fmt.Println(slice)
}
Just in case you are trying to compare how a slice
function in other languages like Javascript or Ruby work to a Slice in Go, don't (mentioning this because I did that when I was learning Go).
To add a little more clarification, when you do slice[0] = "x"
, you are not modifying the slice; you are modifying the underlying array that slice
is referencing.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论