Go构造函数中的返回值与指针

returning value vs pointer in Go constructor

在用 go 构建一个简单的对象时,这些替代方案之间有什么区别?

func NewGender(value string) Gender {
    return Gender{strings.TrimSpace(value)}
}

func NewGender(value string) *Gender {
    return &Gender{strings.TrimSpace(value)}
}

这个问题非常宽泛,在很大程度上取决于您 API 的其余部分。因此,以下是您在选择其中一项时可能需要考虑的一些事项(排名不分先后):

  • 不必要的指针会导致 GC 的工作量增加。您可能会通过 returning 一个指针(一个词)而不是一个结构(零到多个词)来赢得一些时间,但其中一些时间可能稍后会被 GC 扫描消耗掉。

  • 指针也可以表示事物的存在或不存在,尽管通常最好使用逗号-ok 成语,否则 return 错误。

  • 说到错误,如果你return nil有一个错误,这个错误被忽略的几率会小一些(因为nil指针解引用会导致panic) .再说一次,我不认为忽略错误的人是你真正应该考虑的事情。

  • 如果您需要某种形式的跟踪(例如,检查您的构造函数曾经创建的所有实例的可能性),您必须 return 一个指针,以便所有更改检查员可以看到该值。

  • 如果大多数类型的方法都有指针接收器,或者 API 中的大多数函数接受指向类型的指针而不是值,那么 return 更符合人体工学指针.

返回的第一项是值,第二项是指针。指针的工作方式与 C 或 C++ 中的指针非常相似,只是它指向的值会像 C# 或 Java 中那样被垃圾回收。 Go 在这两种范式之间提供了某种折衷。该指针是显式和公开的,但它仍然是垃圾收集器。这里有一些明显的区别;

1) 如果你将值传递给一个方法或者它是接收者(这常常令人困惑)你将无法修改它的值,它将是一个 'pass by value' 就像在其他语言中一样您正在修改副本的位置。是的,即使 func (g Gender) ChangeGender() 方法也不会改变您调用它的对象的性别。 https://play.golang.org/

2) 只能调用为该类型定义的方法。例如,如果你有 g *Gender 并且你想调用上面的 ChangeGender 方法,你将无法不取消引用你的指针,就像在 C/C++ 中一样。反之亦然。

3) 按值传递的替代方法是通过引用,您可能知道它是如何工作的,但如果您不知道,我会解释一下。如果你有一个方法 func (g *Gender) ModifyGender() 和一个实例 g := &Gender{} 那么当调用 ModifyGender 时,OS 字长的指针将作为参数而不是value 本身和方法将使用该地址修改那里的内存,并在控制 returns 给调用者时持久化更改。如果您的方法适用于占用大量内存的对象,这可以极大地提高性能。

我不会谈论性能。这应该为您提供足够的信息来考虑它在您的应用程序中的工作方式。