在变量中不使用指向结构体字面值的指针时,进行Go Tour。

huangapple go评论85阅读模式
英文:

go tour when to not use pointer to struct literal in a variable

问题

根据Go tour page 28page 53,它们展示了一个指向结构体字面量的指针变量。为什么这不是默认行为呢?我对C不熟悉,所以很难理解。我只能想到一种情况,即当结构体字面量是唯一的,并且在程序的其余部分不会使用它时,可能不使用指针更有利,并且希望尽快进行垃圾回收。我甚至不确定像Go这样的现代语言是否以这种方式工作。

我的问题是,什么时候应该将指向结构体字面量的指针赋给变量,什么时候应该直接赋给结构体字面量本身?

谢谢。

英文:

Per the Go tour page 28 and page 53

They show a variable that is a pointer to a struct literal. Why is this not the default behavior? I'm unfamiliar with C, so it's hard to wrap my head around it. The only time I can see when it might not be more beneficial to use a pointer is when the struct literal is unique, and won't be in use for the rest program and so you would want it to be garbage collected as soon as possible. I'm not even sure if a modern language like Go even works that way.

My question is this. When should I assign a pointer to a struct literal to a variable, and when should I assign the struct literal itself?

Thanks.

答案1

得分: 14

使用指针而不仅仅是结构体字面量在以下情况下很有帮助:

  • 结构体很大并且你要传递它
  • 你想要共享它,也就是说所有的修改都会影响到你的结构体,而不是影响到一个副本

在其他情况下,直接使用结构体字面量也是可以的。对于一个小的结构体,你可以将这个问题看作是使用int还是*int的问题:大多数情况下,使用int就可以了,但有时候你会传递一个指针,这样接收者就可以修改你的整数变量。

在Go教程的练习中,Vertex结构体很小,并且与任何数字具有相同的语义。在我看来,直接将其作为结构体使用,并在#53中像这样定义Scaled函数也是可以的:

func (v Vertex) Scaled(f float64) Vertex {
	v.X = v.X * f
	v.Y = v.Y * f
	return v
}

因为使用

v2 := v1.Scaled(5)

会创建一个新的顶点,就像

var f2 float32 = f1 * 5

会创建一个新的float一样。

这与标准的Time结构体的处理方式类似(在这里定义),通常将其保存在Time类型的变量中,而不是*Time类型的变量中。

但并没有明确的规则,根据使用情况,我也可以同时保留ScaleScaled两个方法。

英文:

Using a pointer instead of just a struct literal is helpful when

  • the struct is big and you pass it around
  • you want to share it, that is that all modifications affect your struct instead of affecting a copy

In other cases, it's fine to simply use the struct literal. For a small struct, you can think about the question just as using an int or an *int : most of the times the int is fine but sometimes you pass a pointer so that the receiver can modify your int variable.

In the Go tour exercises you link to, the Vertex struct is small and has about the same semantic than any number. In my opinion it would have been fine to use it as struct directly and to define the Scaled function in #53 like this :

func (v Vertex) Scaled(f float64) Vertex {
	v.X = v.X * f
	v.Y = v.Y * f
	return v
}

because having

v2 := v1.Scaled(5)

would create a new vertex just like

var f2 float32 = f1 * 5

creates a new float.

This is similar to how is handled the standard Time struct (defined here), which is usually kept in variables of type Time and not *Time.

But there is no definite rule and, depending on the use, I could very well have kept both Scale and Scaled.

答案2

得分: 2

你可能是对的,大多数情况下你需要指针,但是就我个人而言,我发现需要显式指针的需求令人耳目一新。这样就没有了intMyStruct之间的区别。它们的行为方式相同。

如果将此与实现了你所建议的内容的C#语言进行比较,我发现以下代码的语义令人困惑:

static void SomeFunction(Point p)
{
    p.x = 1;
}
static void Main()
{
    Point p = new Point();
    SomeFunction(p);
    // p.x是什么?
}

这取决于Point是被定义为class还是struct

英文:

You're probably right that most of the time you want pointers, but personally I find the need for an explicit pointer refreshing. It makes it so there's no difference between int and MyStruct. They behave the same way.

If you compare this to C# - a language which implements what you are suggesting - I find it confusing that the semantics of this:

static void SomeFunction(Point p)
{
    p.x = 1;
}
static void Main()
{
    Point p = new Point();
    SomeFunction(p);
    // what is p.x?
}

Depend on whether or not Point is defined as a class or a struct.

huangapple
  • 本文由 发表于 2012年12月7日 18:00:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/13760793.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定