Go代码规范(Code Review)

总结几个开发过程中经常会犯的代码规范错误

参考链接:https://learnku.com/go/wikis/48375

注释语句

// Request 表示运行命令的请求。
type Request struct { ... // Encode 将 req 的 JSON 编码写入 w 。
func Encode(w io.Writer, req *Request) { ...

上下文

大部分使用上下文的函数都要将其作为第一个参数

func F(ctx context.Context, /* 其他参数 */) {}

不建议把上下文作为成员添加到结构类型中

// 不建议写法
type MyContext struct {
ctx context.Context
}

Crypto Rand

不要使用 math/rand 来生成密钥,即使是一次性密钥。在没有种子(seed)的情况下,生成器是完全可以被预测的。请使用 crypto/rand 的 Reader 作为替代

func Key() string {
buf := make([]byte, 16)
_, err := rand.Read(buf)
if err != nil {
panic(err) // 出于随机性,永远都不会发生
}
return fmt.Sprintf("%x", buf)
// or hex.EncodeToString(buf)
// or base64.StdEncoding.EncodeToString(buf)
} func main() {
fmt.Println(Key())
}
//输出
//4799b801e7866209593cfaedb03cf8da

声明空的切片

当声明一个空 slice 时,倾向于用

var t []string

而不是

t := []string{}

前者声明了一个 nil slice 值,而后者声明了一个非 nil 但是零长度的 slice。两者在功能上等同,len 和 cap 均为零,而 nil slice 是首选的风格。

请注意,在部分场景下,首选非 nil 但零长度的切片,例如编码 JSON 对象时(nil 切片编码为 null,而则 []string{} 可以正确编码为 JSON array [])。

包注释

/*
Package template implements data-driven templates for generating textual
output such as HTML.
....
*/
package template

如果包很简单,包注释可以很简短。

// Package math provides basic constants and mathematical functions.
package math

包名

对包中名称的所有引用都将使用包名完成,因此可以从标识符中省略该名称。 例如,如果你正在使用 chubby 包,则不需键入 ChubbyFile ,因为客户端会将其写为 chubby.ChubbyFile。 相反,命名为 File 的这种方式,客户端会将它写为 chubby.File 。 避免使用像 utilcommonmiscapitypesinterfaces 这样无意义的包名。

不要Panic

错误信息

即使用 fmt.Errorf("something bad") 而不要使用 fmt.Errorf("Something bad")

包的导入

避免包重命名导入,防止名称冲突;好的包名称不需要重命名。如果发生命名冲突,则更倾向于重命名最接近本地的包或特定于项目的包。

包导入按组进行组织,组与组之间有空行。标准库包始终位于第一组中。

package main

import (
"fmt"
"hash/adler32"
"os" "appengine/foo"
"appengine/user" "github.com/foo/bar"
"rsc.io/goversion/version"
)

包的匿名导入

import _ "pkg" 这种导入语句,最好只存在于main.go文件中

Dot 导入

package foo_test

import (
. "foo"
)

不要在程序中使用 import .。它将使程序更难阅读

内联错误

不规范写法

// 查找返回键的值,如果没有键的映射,则返回空字符串。
func Lookup(key string) string

规范写法

// 查找并返回键的值,如果没有键的映射,则ok = false。
func Lookup(key string) (value string, ok bool)

并有利于写出更健壮和可读性更强的代码:

value, ok := Lookup(key)
if !ok {
return fmt.Errorf("no value for %q", key)
}
return Parse(value)

缩进错误处理

要缩进错误处理逻辑,不要缩进常规代码。这样可以改进代码的可读性,读者可以快速地浏览逻辑主干。例如,不要写:

if x, err := f(); err != nil {
// 错误处理
return
} else {
// 使用变量 x
}

相反,应该这样写:

x, err := f()
if err != nil {
// 错误处理
return
}
// 使用变量 x

这样写的好处可以增加可读性

首字母缩写

名称中的单词是首字母或首字母缩略词(例如 "URL" 或 "NATO" )需要具有相同的大小写规则。例如,"URL" 应显示为 "URL" 或 "url" (如 "urlPony" 或 "URLPony" ),而不是 "Url"。举个例子:ServeHTTP 不是 ServeHttp。对于具有多个初始化 “单词” 的标识符,也应当显示为 "xmlHTTPRequest" 或 "XMLHTTPRequest"。

当 "ID" 是 "identifier" 的缩写时,此规则也适用于 "ID" ,因此请写 "appID" 而不是 "appId"。

protocol buffer 生成的代码是个例外,对人和对机器的要求不能一样,人编写的代码要比机器编写的代码保持更高的标准。

接口

总的来说,Go 的接口要包含在使用方的包里,不应该包含在实现方的包里。实现方只需要返回具体类型(通常是指针或结构体),这样一来可以将新方法添加到实现中,而不需要扩展重构。

不要在 API 的实现者端定义 "for mocking" 接口;反而是要定义公开的 API,用真实的实现进行测试。

不要先定义接口再用它。脱离真实的使用场景,我们都不能确定一个接口是否有存在的价值,更别提设计接口的方法了

建议写法,把接口和接口具体的实现类分开两个go文件

package consumer  // consumer_func.go

type Thinger interface { Thing() bool }

func Foo(t Thinger) string { … }
package consumer //consumer.go

type defaultThinger struct{ … }
func (t defaultThinger) Thing() bool { … } func NewThinger() Thinger { return defaultThinger{ … } }

不规范写法

package producer

type Thinger struct{ … }
func (t Thinger) Thing() bool { … } func NewThinger() Thinger { return Thinger{ … } }

方法接收者命名

方法接收者的名称应该反映其身份;通常,其类型的一个或两个字母缩写就足够了(例如用 "c" 或 "cl" 表示 "client" )。不要使用通用名称,例如 "me","this" 或 "self",这是面向对象语言的典型标识符,这些标识符赋予该方法特殊的含义。

方法接收者类型

要是把握不准,就用指针。

变量名称

Go 中的变量名称尽可能短为妙,言简意赅,尤其是对于那些处于有限空间中的局部变量更是如此。例如: 用 c 而不是 lineCount; 用 i 而不是 sliceIndex

基本准则:当变量首次被使用时离声明的位置越远,变量名称必须更具描述性。对于方法接收者的名称来说,一个或者两个字母就足够了。普通变量比如 loop indicesreaders 的名称用一个字母(i , r)指代就可以。

当然,对于一些逻辑比较复杂的逻辑,或者非常规事物,或者全局变量则需使用更具描述性的名字。

Go代码规范梳理的更多相关文章

  1. Scrum立会报告+燃尽图(十一月十五日总第二十三次):代码规范与技术交流

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2384 项目地址:https://git.coding.net/zhang ...

  2. iOS代码规范(OC和Swift)

    下面说下iOS的代码规范问题,如果大家觉得还不错,可以直接用到项目中,有不同意见 可以在下面讨论下. 相信很多人工作中最烦的就是代码不规范,命名不规范,曾经见过一个VC里有3个按钮被命名为button ...

  3. 谈谈PHP代码规范

    [转] http://www.syyong.com/php/Talk-about-PHP-code-specification.html 我向往这样一个php世界,里面没有代码规范之争.你我都一样,都 ...

  4. 2016 正确 sublime安装PHPcs PHPcodesniffer代码规范提示插件,修正网上部分不详细描述

    对你有助请点赞,请顶,不好请踩------送人玫瑰,手留余香!-------------------14:37 2016/3/212016 正确 sublime安装PHPcs PHPcodesniff ...

  5. C#与Java对比学习:类型判断、类与接口继承、代码规范与编码习惯、常量定义

    类型判断符号: C#:object a;  if(a is int) { }  用 is 符号判断 Java:object a; if(a instanceof Integer) { } 用 inst ...

  6. 作业三: 代码规范、代码复审、PSP

    分) 对于是否需要有代码规范,请考虑下列论点并反驳/支持: 这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. 我是个艺术家,手艺人,我有自己的规范和原则. 规范不能 ...

  7. 转!!Java代码规范、格式化和checkstyle检查配置文档

    为便于规范各位开发人员代码.提高代码质量,研发中心需要启动代码评审机制.为了加快代码评审的速度,减少不必要的时间,可以加入一些代码评审的静态检查工具,另外需要为研发中心配置统一的编码模板和代码格式化模 ...

  8. C#代码规范

    C#代码规范  一.文件命名 1 文件名 文件名统一使用帕斯卡命名法,以C#类名命名,拓展名小写. 示例: GameManager.cs 2 文件注释 每个文件头须包含注释说明,文件头位置指的是文件最 ...

  9. 【转】Java代码规范

    [转]Java代码规范 http://blog.csdn.net/huaishu/article/details/26725539

随机推荐

  1. java中的线程是如何工作的。

    来自对此文章的编辑. https://mp.weixin.qq.com/s?biz=MzA5NDg3MjAwMQ==&mid=2457103451&idx=1&sn=ba302 ...

  2. SpringMVC 解析(二)DispatcherServlet

    在我的关于Tomcat容器介绍的文章中,介绍了Tomcat容器的工作原理,我们知道Tomcat容器在收到请求之后,会把请求处理为Request/Response对象,交给Servlet实例处理.对于S ...

  3. 不使用pvc的方式在K8S中部署apisix-gateway

    不使用pvc的方式在K8S中部署apisix-gateway 简介 我的apisix使用etcd作为数据存储服务器,官方的使用pvc方式或者docker-compose的方式,对于新手不太友好,本篇是 ...

  4. 部分文件的MIMEType

    类型 文件拓展名 MIMEType 图片 png image/png bmp\dib image/bmp jpe\jpeg\jpg image/jpeg gif image/gif 多媒体 mp3 a ...

  5. php include,require,include_once,require_once 的区别

    include(),require(),include_once(),require_once()作用都是包含并运行指定文件,但是使用场景又有很大区别. 1.include()和require()的区 ...

  6. 区段统计 mysql 语句 case when then end as

    EXPLAIN SELECT COUNT(*),CASEWHEN device_width > 729 THEN '>729'WHEN device_width BETWEEN '720' ...

  7. GFS 分布式文件系统

    GFS 分布式文件系统 1.GlusterFS概述 : GlusterFS简介  a) GlusterFS是一-个开源的分布式文件系统. 由存储服务器.客户端以及NFS/Samba存储网关(可选,根据 ...

  8. k8s之PV、PVC

    目录 一.PVC和PV 1.1 PV概念 1.2 PVC概念 1.3 PV与PVC之间的关系 1.4 两种PV的提供方式 二.基于nfs创建静态PV资源和PVC资源 2.1 配置nfs存储(192.1 ...

  9. 四路4 GSPS@ 12 bit,四路12 GSPS@16 位4T4R 射频芯片AD9988

    一.产品概述 AD9988 是一款高度集成的套件,是北京太速最新研发的,具有四个 16 位.12 GSPS 最大采样率.RF 数模转换器 (DAC) 内核,以及四个 12 位.4 GSPS 速率.RF ...

  10. Solution -「Gym 102979E」Expected Distance

    \(\mathcal{Description}\)   Link.   用给定的 \(\{a_{n-1}\},\{c_n\}\) 生成一棵含有 \(n\) 个点的树,其中 \(u\) 连向 \([1, ...