在go中构建一个简单的对象时,这些选项之间的区别是什么?
func NewGender(value string) Gender {
return Gender{strings.TrimSpace(value)}
}
func NewGender(value string) *Gender {
return &Gender{strings.TrimSpace(value)}
}
这是一个非常广泛的问题,它在很大程度上取决于API的其余部分。所以这里有一些你在选择时可能需要考虑的事情(没有特定的顺序):
-
不必要的指针会给GC带来更多的工作。通过返回指针(一个单词)而不是结构体(从0到多个单词),您可能会赢得一些时间,但其中一些时间可能稍后会被GC扫描所消耗。
-
指针也可以表示事物的存在或不存在,尽管通常最好使用逗号-ok来表示,否则会返回错误。
-
说到错误,如果您返回带有错误的
nil
,则错误被忽略的可能性较小(因为nil指针解引用将导致panic)。然而,我不认为那些忽略错误的人是你真正应该考虑的问题。 -
如果你需要某种形式的跟踪(例如,检查构造函数创建的所有实例的可能性),你必须返回一个指针,以便检查器可以看到对值的所有更改。
-
如果大多数类型的方法都有一个指针接收器,或者API中的大多数函数接受指向该类型的指针而不是值,那么返回指针更符合人体工程学。
返回的第一项是一个值,第二项是一个指针。指针的工作方式很像C或c++中的指针,只是它指向的值会像c#或Java一样被垃圾收集。Go在这两种范式之间提供了某种折衷。指针是显式的和公开的,但是它仍然被垃圾收集。以下是一些比较明显的区别:
1)如果你将值传递给一个方法或者它是接收者(这经常令人困惑),你将无法修改它的值,它将是一个"按值传递",就像在其他语言中你修改副本一样。是的,即使方法func (g Gender) ChangeGender()
也不会改变调用它的对象的性别。https://play.golang.org/
2)只能调用为该类型定义的方法。例如,如果你有g *Gender
,你想调用上面的ChangeGender
方法,你将无法不解引用你的指针,就像在C/c++中一样。
3)按值传递的替代方法是按引用传递,你可能知道它是如何工作的,但如果你不知道,我将解释。如果你有一个方法func (g *Gender) ModifyGender()
和一个实例g := &Gender{}
,那么当调用ModifyGender
时,一个操作系统字大小的指针将被作为参数压入堆栈,而不是值本身,方法将使用该地址修改那里的内存,当控制返回给调用者时持久化更改。这可以极大地提高性能,如果你的方法工作的对象有很大的内存占用。
我不打算谈论性能。这应该给您足够的信息来考虑它如何在您的应用程序中工作。
正如@evanmcdonnal所说,选择与如何使用结构体更相关。
-
如果你的结构是信息只有,你不打算改变它以后,保持它简单,并返回一个值(如自定义错误结构),如果你的结构是真的很大,但你不打算改变它使用指针(如RGB矩阵)
-
如果你计划在你的程序工作流程中改变你的结构,使用指针。