[Beginner] What is the difference between passing an slice containing the address pointer of a struct vs a slice containing the struct to a function

xuanbao · 2017-07-02 17:00:06 · 591 次点击    
这是一个分享于 2017-07-02 17:00:06 的资源,其中的信息可能已经有所发展或是发生改变。

Consider the following playground

We see that passing []*Vertex and []Vertex both change the underlying struct in the slice.

Is both []*Vertex and []Vertex storing the vertex's address?


评论:

YEPHENAS:

A slice is a struct consisting of a pointer to an array, a length and a capacity.

// []Vertex
m = {*,len,cap}    // This part gets copied on function call
     |
     |
     +-->[Vertex,Vertex,Vertex,Vertex]  // This part does not get copied

// []*Vertex
k = {*,len,cap}    // This part gets copied on function call
     |
     |
     +-->[*,*,*,*]   // This part does not get copied
          | | | |
          | | | +-->Vertex
          | | +-->Vertex
          | +-->Vertex
          +-->Vertex

Slices are not arrays, they point to arrays. This is an array:

// [4]Vertex
a = [Vertex,Vertex,Vertex,Vertex]    // This part gets copied on function call
a_k_w:

Go is pass by value. So when you pass a type to a function, you are passing the value, which is then copied. When you pass a pointer-type to a function it is also copied. All values are copied. pointer-types are special in that you can use these types to pass state into and out of a function. then the pointer-type can be dereferenced into a type.

so in the example, you have a slice of two different types. one slice holds values of pointer-type *Vertex and the other holds values of type Vertex. You also pass the different slices into functions differently. one you are passing the pointer to a slice, and the other you are passing the slice(which is a struct containing three words: len, cap, pointer).

So to answer the question. No. The []*Vertex slice is holding pointer-type *Vertex and the []Vertex slice is holding type Vertex.

Drop your notion of reference at the portal into the Go universe. You have types and pointer-types, and these types hold values.

Hopefully this playground is a effective visual aid: https://play.golang.org/p/kEYFzTwbwR

it prints a textual representation of the data, the textual representation closely resembles how this data is stored within memory.

tjholowaychuk:

In that scenario it's effectively the same as doing:

a := Vertex{}
a.X = 5

You're not getting a copy each time you assign the field, you're just moving the value 5 to X, whereas this will produce a copy first:

a := vertices[0]
a.X = 5
vertices[0].X
// won't be 5 :D 

Same goes for the assignment in for though, this won't give you v.X == 5's

package main
import "fmt"
type Vertex struct {
    X int
    Y int
}
func main() {
    vs := []Vertex{
        {1, 1},
        {1, 1},
    }
    for _, v := range vs {
        v.X = 5
    }
    fmt.Printf("%#v\n", vs)
}
binaryblade:

maybe this will show the difference

ardanstudios:

Read this series.

https://www.goinggo.net/2017/05/language-mechanics-on-stacks-and-pointers.html


入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

591 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传