我一直在浏览Go编程语言以熟悉该语言,该语言的一个特点让我感到疑惑。
在关于Struct Literals的步骤中,他们解释了您可以通过多种方式实例化结构:
type Vertex struct {
X, Y int
}
var (
v1 = Vertex{1, 2} // has type Vertex
v2 = Vertex{X: 1} // Y:0 is implicit
v3 = Vertex{} // X:0 and Y:0
p = &Vertex{1, 2} // has type *Vertex
)
我理解三种第一种方式是如何工作以及它们何时有用是没有问题的,但我无法弄清楚最后一种解决方案p = &Vertex{1, 2}
的任何用例。
实际上,我无法想到任何情况下必须实例化*Vertex
,而不必在代码中使用Vertex
类型的变量:
func modifyingVertexes(myVertex *Vertex) {
myVertex.X = 42;
}
func main() {
myVertex := Vertex{1, 2}
modifyingVertexes(&myVertex)
fmt.Println(myVertex.X)
}
如果可能的话,我可以看到一个用途:
func modifyingVertexes(myVertex *Vertex) {
myVertex.X = 42;
}
func main() {
modifyingVertexes(&Vertex{1, 2})
fmt.Println(???.X) // Accessing the vertex initialized in the modifyingVertexes func call
}
但由于我认为不可能,我真的不知道如何使用它?
谢谢!
答案 0 :(得分:4)
这是一个非常常见的Go习语,返回初始化struct
变量的地址。
package main
import "fmt"
type Vertex struct {
X, Y int
}
func NewVertex(x, y int) *Vertex {
return &Vertex{X: x, Y: y}
}
func main() {
v := NewVertex(1, 2)
fmt.Println(*v)
}
游乐场:https://play.golang.org/p/UGOk7TbjC2a
输出:
{1 2}
这也是隐藏未导出(私人)struct
字段的常用习惯。
package main
import "fmt"
type Vertex struct {
x, y int
}
func NewVertex(x, y int) *Vertex {
return &Vertex{x: x, y: y}
}
func (v *Vertex) Clone() *Vertex {
return &Vertex{x: v.x, y: v.y}
}
func main() {
v := NewVertex(1, 2)
fmt.Println(*v)
w := v.Clone()
fmt.Println(*w)
}
游乐场:https://play.golang.org/p/ScIqOIaYGPn
输出:
{1 2}
{1 2}
在Go中,所有参数都按值传递。使用大structs
指针更有效。如果您希望更改struct
参数的值,则还需要指针。
答案 1 :(得分:0)
考虑两种初始化方式(例如foo{}
和&foo{}
)的另一种方法是通过您希望实现的目标。如果你需要一个永远不会改变的值对象,那么foo{}
就可以了。另一方面,如果您需要稍后更改对象,则最好使用引用。例如:
// using a value object because it will never change
oneHundredDollars := Cash{Amount: 100, Currency: "Dollars"}
// using a reference because the account's balance will change.
a := &Account{Balance: 0}
// changes Balance
a.Deposit(oneHundredDollars)