What do “value semantics’” and “pointer semantics” mean in Go?

て烟熏妆下的殇ゞ 提交于 2019-12-22 08:52:27

问题


What is the meaning of Value semantics and Pointer semantics in Go? In this course, the author used to mention many times about above terms when explaining internals of arrays and slices which I couldn't understand it completely.


回答1:


When you call a function or a method and you pass parameters to it, a copy is made from the values, and the function can only access these copies.

This means if the function attempts to modify / change the copies, it will not change the original value.

For example:

func main() {
    i := 1
    fmt.Println("double:", double(i))
    fmt.Println("original i:", i)
}

func double(i int) int {
    i *= 2
    return i
}

This outputs (try it on the Go Playground):

double: 2
original i: 1

Even though double() modifies its i parameter, the variable (whose value was passed) at the caller did not change.

For it to change, we would need to change the signature to expect a pointer, pass a pointer, and modify the pointed value:

func main() {
    i := 1
    fmt.Println("double:", doublep(&i))
    fmt.Println("original i:", i)
}

func doublep(i *int) int {
    *i *= 2
    return *i
}

This outputs (try it on the Go Playground):

double: 2
original i: 2

So if we pass something, we're expecting the original value not to change if the passed value is modified, unless we pass a pointer to it.

Pointer semantics means that even though we pass something "by value", the callee can still modify the "original" value, just as if we would have passed a pointer to it.

For example:

func main() {
    is := []int{1, 2}
    fmt.Println("double:", doubles(is))
    fmt.Println("original is:", is)
}

func doubles(is []int) []int {
    for i := range is {
        is[i] *= 2
    }
    return is
}

This outputs (try it on the Go Playground):

double: [2 4]
original is: [2 4]

Even though we did not pass a pointer (is is not a pointer), the calle modified its elements, and the value of the original slice also changed.

We say that even though in Go everything is passed by value, passing slices have pointer semantics, because if the callee modifies the elements, it will be reflected in the original.

Reasoning

Everything in Go is passed by value, slices too. But slices are–under the hood–struct-like data structures that hold a pointer to an underlying array that holds the actual elements. And when you pass a slice, a copy is made, but only this slice header will be copied (this is the slice value). The copy will hold the same pointer, pointing to the same backing array. The backing array is not copied. So when the callee modifies the elements of the slice, the elements of the backing array are modified, which is the same as the backing array of the original slice.

Read more about it here: Are golang slices pass by value?

There are many types that have pass by pointer semantics, such as slices, maps, channels.

It is worth noting that–unlike slices–arrays are not in the line, an array value means all its values, and passing an array makes a copy of all its elements.



来源:https://stackoverflow.com/questions/51264339/what-do-value-semantics-and-pointer-semantics-mean-in-go

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!