在Go,CamelCase或Semi-CamelCase中以哪种方式命名函数?


79

我想在Go中编写一个函数,以将文档插入MongoDB数据库的集合中。以哪种方式命名函数更好,

  • writeToMongoDB 要么
  • WriteToMongoD

第二个是CamelCase,而我看到有人使用第一个的样式,因此我不确定哪个更合适。谢谢。


2
他们有不同的用途:golang.org/ref/spec#Exported_identifiers
JimB

谢谢。在文件A中另一个程序中,该函数以第一种方式命名,文件B中的另一个程序从文件A中调用该函数。文件A和B都位于同一目录中。根据链接,似乎该函数必须以第二种方式定义,以便程序在另一个文件中使用,对吗?
蒂姆(Tim)

是的,如果文件A的软件包的名称为packageA,则文件B可以使用packageA.WriteToMongoD(必须使用packageA作为限定符)访问该函数。
Tanmay Garg,2016年

这是否有助于回答您的问题?stackoverflow.com/a/64300628/12817546
汤姆L

Answers:


115

句法

在Go中,这不是样式问题,而是语法问题。

导出的名称(即,可以从定义名称的包以外的其他程序包使用的标识符)以大写字母开头。因此,如果您的方法是公共API的一部分,则应编写为:

WriteToDB

但是,如果它是内部帮助器方法,则应编写为:

writeToDB

与使用关键字定义导出性(externpublic等)相比,以这种方式进行操作的好处在于,使其成为名称的一部分可以确保在使用标识符的任何地方都可以知道是否导出了标识符,而不必查找它的位置已定义(以查看定义是否包含关键字)。

另请参阅: 规范中的导出标识符

i18n

因为Go是UTF-8编码的,并且支持标识符名称中具有字母或数字属性的任何Unicode字符,所以某些不区分大小写的语言环境的人可能无法创建导出的方法(默认为未导出)。在这种情况下(双关语是故意的),通常在标识符之前加上前缀X以指示导出性。例如:X日本語

另请参阅: Unicode标识符有什么作用?从常见问题解答。

风格

就一般样式而言,应始终使用驼峰式大小写(如前所述,首字母除外)。这包括常量,函数和其他标识符。因此,例如(导出的)常量列表可能看起来像:

const (
    StateConnected = iota
    StateError
    StateDone

    internalStateMask = 0x2 
)

此外,缩写总是以相同的大小写来编写,因此您可以编写以下内容之一:

dbWrite
writeDB

代替writeDbDbWrite


好答案+1。首选的Go术语是MixedCaps或mixedCaps而不是CamelCase。请参阅golang.org/doc/effective_go.html#mixed-caps
汤姆L

28

在Go中,约定使用混合上限。来自文档:https : //golang.org/doc/effective_go.html#mixed-caps

最后,Go中的约定是使用MixedCaps或mixedCaps而不是下划线来编写多字名称。

请注意,以大写字母开头的文件级别名称在软件包级别导出:https : //golang.org/doc/effective_go.html#Getters

同样,惯例是在所有大写字母上写首字母缩写词。所以下面很好:

writeToMongoDB // unexported, only visible within the package

要么

WriteToMongoDB // exported

并不是:

writeToMongoDb

只是学习golang而被困了好几天。终于解决了!
AzyCrw4282

18

名字

名称在Go语言中与其他语言一样重要。它们甚至具有语义效果:包外部名称的可见性取决于其首字符是否为大写。因此,值得花一些时间讨论Go程序中的命名约定。

包装名称

导入软件包时,软件包名称将成为内容的访问者。后

import“ bytes”导入包可以谈论bytes.Buffer。如果每个使用该软件包的人都可以使用相同的名称来引用其内容,这将很有帮助,这意味着该软件包的名称应该很好:简短,简洁,令人回味。按照惯例,软件包使用小写的单字名称。不需要下划线或大写字母。为了简便起见,Err是错误的,因为每个使用您的软件包的人都会输入该名称。而且不必担心先验冲突。包名称仅是导入的默认名称。它不必在所有源代码中都是唯一的,并且在发生冲突的极少数情况下,导入包可以选择其他名称以在本地使用。在任何情况下,混淆都是很少的,因为导入中的文件名决定了所使用的软件包。

另一个约定是,程序包名称是其源目录的基本名称。src / encoding / base64中的程序包被导入为“ encoding / base64”,但名称为base64,而不是encoding_base64,也不是encodingBase64。

程序包的导入者将使用该名称来引用其内容,因此,程序包中导出的名称可以使用该事实来避免卡顿。(不要使用import表示法,这样可以简化必须在测试包之外运行的测试,但应避免这样做。)例如,bufio包中的缓冲读取器类型称为Reader,而不是BufReader,因为用户将其视为bufio.Reader,这是一个简洁明了的名称。此外,由于导入的实体始终使用其包名称来寻址,因此bufio.Reader不会与io.Reader冲突。类似地,用于创建ring.Ring新实例的函数(Ring是Go中构造函数的定义)通常被称为NewRing,但是由于Ring是软件包唯一导出的类型,并且由于该软件包被称为ring,因此' 称为“新”,该包的客户端将其称为ring.New。使用包结构可以帮助您选择好名字。

另一个简短的例子是一次。一次。Do(setup)读得很好,并且不会因编写一次而提高。DoOrWaitUntilDone(setup)。长名不会自动使事情更具可读性。有用的文档注释通常比加长的名称更有价值

吸气剂

Go不会自动为getter和setter提供支持。自己提供getter和setter并没有错,这样做通常是适当的,但是将Get用作getter的名称既不是惯用的,也没有必要。如果您有一个名为owner(小写,未导出)的字段,则getter方法应称为Owner(大写,导出),而不是GetOwner。使用大写名称进行导出提供了挂钩,以将字段与方法区分开。如果需要的话,一个setter函数可能会被称为SetOwner。这两个名字在实践中都读得很好:

owner := obj.Owner()
if owner != user {
    obj.SetOwner(user)
}

接口名称

按照惯例,一种方法的接口使用方法名称加上-er后缀或类似的修饰名来构造代理名词:Reader,Writer,Formatter,CloseNotifier等

有许多这样的名称,兑现它们和它们捕获的函数名称很有用。读,写,关闭,刷新,字符串等具有规范的签名和含义。为避免混淆,除非您的方法具有相同的签名和含义,否则请不要给它们使用任何名称。相反,如果您的类型实现的方法的含义与熟知类型上的方法的含义相同,则为其赋予相同的名称和签名;调用您的字符串转换器方法String而不是ToString

混合帽

最后,Go中的约定是使用MixedCaps或mixedCaps而不是使用下划线来编写多字名称

参考:有效执行


12

在Golang中,任何标识符(以大写字母开头(例如,CamelCase)开头)的变量(或函数)都可公开(可访问)到程序中的所有其他软件包,而那些以小写字母开头(例如,camelCase)不能被任何软件包访问,除非在其中声明了该软件包。

如果您打算在另一个程序包中使用变量(或函数),则应使用CamelCase,否则您可以放心使用camelCase。


1
好答案+1。首选的Go术语是MixedCaps或mixedCaps而不是CamelCase。请参阅golang.org/doc/effective_go.html#mixed-caps
汤姆L
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.