使用Go命名惯例对标识符进行命名

2024-08-12 19:17:14 浏览数 (2)

计算机科学中只有两件难事:缓存失效和命名。——Phil Karlton,Netscape架构师

命名是编程语言的要求,但是好的命名却是为了提高程序的可读性和可维护性。好的命名是什么样子的呢?Go语言的贡献者和布道师Dave Cheney给出了一个说法:“一个好笑话,如果你必须解释它,那就不好笑了。好的命名也类似。”无论哪门编程语言,良好的命名都应该遵循一些通用的原则,但就像之前提到的“语言影响思维”的假说那样,不同的编程语言会有一些个性化的命名惯例。

Go的设计哲学之一就是追求简单,它在命名上一样秉承着简单的总体原则。

要想做好Go标识符的命名(包括对包的命名),至少要遵循两个原则:简单且一致;利用上下文辅助命名。

7.1 简单且一致

  1. 包 对于Go中的包(package),一般建议以小写形式的单个单词命名在Go中,包名可以不唯一。 Go语言建议,包名应尽量与包导入路径(import path)的最后一个路径分段保持一致:比如:包导入路径golang.org/x/text/encoding的最后路径分段是encoding,该路径下包名就应该为encoding。 此外,我们在给包命名的时候,不仅要考虑包自身的名字,还要兼顾该包导出的标识符(如变量、常量、类型、函数等)的命名。由于对这些包导出标识符的引用必须以包名为前缀,因此对包导出标识符命名时,在名字中不要再包含包名,比如: strings.Reader good strings.StringReader bad bytes.Buffer good bytes.ByteBuffer bad
  2. 变量、类型、函数和方法 一个Go工程中包的数量是有限的,变量、类型、函数和方法的命名占据了命名工作的较大比重。 在Go中变量分为包级别的变量和局部变量(函数或方法内的变量)。函数或方法的参数、返回值都可以被视为局部变量。 Go语言官方要求标识符命名采用驼峰命名法(CamelCase),以变量名为例,如果变量名由一个以上的词组合构成,那么这些词之间紧密相连,不使用任何连接符(如下划线)。驼峰命名法有两种形式:一种是第一个词的首字母小写,后面每个词的首字母大写,叫作“小骆峰拼写法”(lowerCamelCase),这也是在Go中最常见的标识符命名法;而第一个词的首字母以及后面每个词的首字母都大写,叫作“大驼峰拼写法”(UpperCamelCase),又称“帕斯卡拼写法”(PascalCase)。由于首字母大写的标识符在Go语言中被视作包导出标识符,因此只有在涉及包导出的情况下才会用到大驼峰拼写法。不过如果缩略词的首字母是大写的,那么其他字母也要保持全部大写,比如HTTP(Hypertext Transfer Protocol)、CBC(Cipher Block Chaining)等。 一般来说,Go标识符仍以单个单词作为命名首选。从Go标准库代码的不完全统计结果来看,不同类别标识符的命名呈现出以下特征:循环和条件变量多采用单个字母命名(具体见上面的统计数据);函数/方法的参数和返回值变量以单个单词或单个字母为主;由于方法在调用时会绑定类型信息,因此方法的命名以单个单词为主;函数多以多单词的复合词进行命名;类型多以多单词的复合词进行命名。除了上述特征,还有一些在命名时常用的惯例。
    1. 变量名字中不要带有类型信息
      1. userSlice []*User bad
      2. users []*User good
    2. 保持简短命名变量含义上的一致性 Go语言中有大量单字母、单个词或缩写命名的简短命名变量。 如:i,k,v,t,b中在go语言中大量使用
    3. 常量 在Go语言中,常量在命名方式上与变量并无较大差别,并不要求全部大写。只是考虑其含义的准确传递,常量多使用多单词组合的方式命名。
    4. 接口 在Go语言中,对于接口类型优先以单个单词命名。对于拥有唯一方法(method)或通过多个拥有唯一方法的接口组合而成的接口,Go语言的惯例是用“方法名 er”命名。如:writer,reader,closer go语言推荐尽量定义小接口,并通过接口组合的方式构建程序。

7.2 利用上下文辅助命名

Go在给标识符命名时还要考虑上下文环境的惯例,即在不影响可读性的前提下,兼顾一致性原则,尽可能地用短小的名字命名标识符。

例如在for循环中用i,v取代index和value。

代码语言:javascript复制
 // bad
 func RuneCount(buffer []byte) int {
   runeCount := 0
   for index := 0; index < len(buffer); index   {
     if buffer[index] == 0 {
       index  
     }
     runeCount  
   }
   return runeCount
 }
 ​
 // good
 func RuneCount2(buffer []byte) int {
   count := 0
   for i := 0; i < len(buffer); i   {
     if buffer[i] == 0 {
       i  
     }
     count  
   }
   return count
 }
 ​

7.3 总结

Go语言追求简单一致且利用上下文辅助名字信息传达的命名惯例。这种命名方式可以隐藏不必要的关系。

0 人点赞