传递结构和结构的指针有什么区别,它们不都是指针吗?

  • 本文关键字:指针 结构 区别 pointers go
  • 更新时间 :
  • 英文 :


例如

var myStructRef *Vertex
var myStruct Vertex
myStructRef = &Vertex{2, 3}
myStruct = Vertex{2, 3}
fmt.Println(myStructRef)
fmt.Println(myStruct)
changeByReferenceStruct(myStructRef)
changeByValueStruct(myStruct)
fmt.Println(myStructRef)
fmt.Println(myStruct)

func changeByValueStruct(myStruct Vertex) {
myStruct.X = 5
fmt.Println(myStruct)
}

func changeByReferenceStruct(myStruct *Vertex) {
myStruct.X = 7
fmt.Println(myStruct)
}

myStructRef *VertexmyStruct Vertex不是指向结构本身的指针吗?为什么在修改函数中的结构时行为存在差异?

golang在解析参数时是否在changeByValueStruct中创建新结构?

当您将指针作为参数传递时,底层发生的事情是创建该指针的副本并将其传递给基础函数。不应将其与按引用传递混淆。

让我们看一个例子来更好地掌握它:

package main
import (
"fmt"
)
type Point struct {
x int
y int
}
func (p Point) String() string {
return fmt.Sprintf("(%d, %d)", p.x, p.y)
}
func modifyValue(point Point) {
point.x += 10
}
func modifyPointer(point *Point) {
point.x = 5
point.y = 5
}
func modifyReference(point *Point) {
point = &Point{5, 5}
}
func main() {
p := Point{0, 0}
fmt.Println(p) // prints (0, 0)

modifyValue(p)
fmt.Println(p) // prints (0, 0)

modifyPointer(&p)
fmt.Println(p) // prints (5, 5)

p = Point{0, 0}
modifyReference(&p)
fmt.Println(p) // prints (0, 0)
}

modifyValue函数内部发生的情况是,点结构的完全不同的实例被修改,因此调用函数时传递的值不受影响。

在第二个示例中,传递指向结构的指针,以便可以以从外部可见的方式修改结构的字段。

最有趣的一点是由最后一个函数modifyReference提出的。如果您熟悉其他语言中可用的按引用传递范例,则希望能够完全修改引用的对象,但这不会发生。这是因为您正在修改作为参数传递的指针的副本

您可能想知道,如果所有内容都是按值传递的,那么何时应传递指针以及何时传递值。传递值向调用方函数保证传递的结构不会发生任何更改,因此当您需要此行为时,请选择该值。这样做的缺点是会制作整个对象的副本,如果它太大,内存就会成为一个问题。

如果要将大型结构作为参数传递,则使用指针会更好,因为它可以节省空间,但无法保证对象不会发生任何更改。

将结构传递给函数参数会复制值。传递结构的指针则不然。因此,传递结构无法更新字段值。

package main
import (
"fmt"
)
type Foo struct {
value int
}
func PassStruct(foo Foo) {
foo.value = 1
}
func PassStructPointer(foo *Foo) {
foo.value = 1
}
func main() {
var foo Foo
fmt.Printf("before PassStruct: %vn", foo.value)
PassStruct(foo)
fmt.Printf("after PassStruct: %vn", foo.value)
fmt.Printf("before PassStructPointer: %vn", foo.value)
PassStructPointer(&foo)
fmt.Printf("after PassStructPointer: %vn", foo.value)
}

https://play.golang.org/p/AM__JwyaJa

最新更新