10

我正在学习 Go,我对何时使用指针有点困惑。具体来说,struct从函数返回 a 时,什么时候返回结构实例本身合适,什么时候返回指向结构的指针合适?

示例代码:

type Car struct {
  make string
  model string
}

func Whatever() {
  var car Car

  car := Car{"honda", "civic"}

  // ...

  return car
}

在哪些情况下我想要返回指针,而我不想返回?有没有好的经验法则?

4

3 回答 3

18

您需要记住两件事,性能和 API。

汽车是如何使用的?它是一个有状态的对象吗?它是一个大结构吗?不幸的是,当我不知道汽车是什么时,我无法回答。说实话,最好的方法是看看别人做了什么并复制他们。最终,你会对这种事情产生一种感觉。我现在将描述标准库中的三个示例,并解释为什么我认为他们使用了他们所做的。

  1. hash/crc32crc32.NewIEEE()函数返回一个指针类型(实际上是一个接口,但底层类型是一个指针)。散列函数的实例具有状态。当您将信息写入哈希时,它会汇总数据,因此当您调用该Sum()方法时,它将为您提供该实例的状态。

  2. time: 该time.Date函数返回一个Time结构。为什么?时间就是时间。它没有状态。它就像一个整数,您可以在其中比较它们,对它们进行数学运算等。API 设计者决定对时间的修改不会改变当前的时间,而是创建一个新的时间。作为图书馆的用户,如果我想要一个月后的时间,我会想要一个新的时间对象,而不是更改我拥有的当前对象。一次也只有3个字长。换句话说,它很小,使用指针不会提高性能。

  3. math/big: big.NewInt()是一个有趣的。我们几乎可以同意,当您修改 a 时big.Int,您通常会想要一个新的。Abig.Int没有内部状态,为什么它是一个指针呢?答案就是性能。程序员意识到大整数是……大。每次进行数学运算时不断分配可能不切实际。因此,他们决定使用指针并允许程序员决定何时分配新空间。

我回答你的问题了吗?可能不是。这是一个设计决策,您需要根据具体情况进行计算。当我设计自己的库时,我使用标准库作为指南。这实际上都归结为判断以及您期望客户端代码如何使用您的类型。

于 2012-06-12T04:26:32.593 回答
2

非常遗憾的是,在特定情况下可能会出现异常:

  • 当它真的很小(不超过几个字)时返回一个值。
  • 当复制开销会严重损害性能(大小是很多字)时,返回一个指针。
于 2012-06-11T20:35:57.910 回答
2

通常,当您想模仿面向对象的风格时,您有一个存储状态的“对象”和可以改变对象的“方法”,那么您将有一个“构造函数”函数返回一个指向结构的指针(将其视为其他 OO 语言中的“对象引用”)。Mutator 方法必须是指向结构类型的方法而不是结构类型本身,以便更改“对象”的字段,因此使用指向结构而不是结构的指针很方便值本身,因此所有“方法”都将在其方法集中。

例如,在 Java 中模仿这样的事情:

class Car {
  String make;
  String model;
  public Car(String myMake) { make = myMake; }
  public setMake(String newMake) { make = newMake; }
}

在 Go 中你经常会看到这样的东西:

type Car struct {
  make string
  model string
}
func NewCar(myMake string) *Car {
  return &Car{myMake, ""}
}
func (self *Car) setMake(newMake string) {
  self.make = newMake
}
于 2012-06-11T23:44:21.473 回答