go code review(上)

简介: go code review(上)

Gofmt

保存代码时一定要使用 gofmt 来格式化,所以最好在自己常用的 IDE 上面配置好对应的工具链,以下三个工具链是我常用的:

  • gofmt
  • goimport
  • golangci-lint(可选)

Comment Sentences

参考 https://golang.org/doc/effective_go.html#commentary

注释应该是完整的句子,即使这看起来有点多余。这种方法使它们在提取到 godoc 文档时可以很好地格式化。注释应该以被描述事物的名称开头,以句号结尾:

// Request represents a request to run a command.
type Request struct { ...
// Encode writes the JSON encoding of req to w.
func Encode(w io.Writer, req *Request) { ...

Contexts

context.Context 类型的值为 API 和进程沟通携带安全凭据、跟踪信息、截止日期和取消信号。Go程序沿着从传入 rpc 和 HTTP 请求到传出请求的整个函数调用链显式地传递上下文。


context.Context 参数通常在方法的第一个参数中使用:

func F(ctx context.Context, /* other arguments */) {}

不是特定于请求的函数可以使用 Context.Background(),但即使您认为不需要传递 Context,也会出错。默认情况下是传递一个 Context;只有当您有充分的理由说明另一种方法是错误的时,才直接使用 context.Background()


不要向结构体类型添加 Context 成员,相反,为需要传递 context 的类型上的每个方法添加一个 context 参数。唯一的例外是那些签名必须与标准库或第三方库中的接口匹配的方法。


不要在函数签名中创建自定义的 context 类型或使用 context 以外的接口。


如果你有应用程序数据要传递,把它放在返回参数、返回的对象,全局变量,或者 context 的值中。


context 是不可变的,所以将相同的 context 传递给相同的 deadline、cancellation signal、credentials、parent trace 等的多个调用也是可以的。

Copying(慎用)

为了避免意外的别名,从另一个包复制结构时要小心。


例如,bytes.Buffer 类型包含一个字节切片。如果复制 Buffer,则复制中的切片可能会在原始数组中使用别名,从而导致后续的方法调用产生惊人的效果。


通常,如果 T 类型的值的方法与指针类型 *T 相关联,则不要复制它。

Crypto Rand

不要使用包 math/rand 来生成密钥,即使是一次性密钥。如果没有种子,生成器是完全可预测的。以 time.Nanoseconds() 为种子,只存在少量的熵。


相反,使用 crypto/rand 的 Reader,如果你需要文本,打印为十六进制或base64:

import (
  "crypto/rand"
  // "encoding/base64"
  // "encoding/hex"
  "fmt"
)
func Key() string {
  buf := make([]byte, 16)
  _, err := rand.Read(buf)
  if err != nil {
    panic(err)  // out of randomness, should never happen
  }
  return fmt.Sprintf("%x", buf)
  // or hex.EncodeToString(buf)
  // or base64.StdEncoding.EncodeToString(buf)
}

Declaring Empty Slices

当定义一个空切片时,首选:

var t []string

其次:

t := []string{}

前者声明一个 nil 切片,而后者是非 nil 但长度为零。它们在功能上是等价的——它们的 lencap 都是0——但是nil切片是首选的方式。


注意,在有限的情况下,非 nil 但零长度的切片是首选的,例如编码 JSON 对象时( nil 切片编码为 null,而 []string{} 编码为 JSON数组[])。


在设计接口时,避免区分 空切片非空切片零长度切片,因为这可能会导致微妙的编程错误。

如果是知道切片的长度,则最好在声明时也将 len 以及 cap 也定义上:

t := make([]string, 10, 10)

GopherCon 2016: Francesc Campoy - Understanding nil

Doc Comments

所有顶级的、导出的名称都应该有文档注释,非普通的未导出类型或函数声明也应该有。

Effective Go

Don't Panic

不要在正常的错误处理中使用 panic。使用错误和多个返回值。

Effective Go

Error Strings

错误字符串不应该大写(除非以专有名词或首字母缩写开头)或以标点符号结尾,因为它们通常是在其他上下文之后打印的。


也就是说,使用 fmt.Errorf(“something bad”) 而不是 fmt.Errorf("Something bad"),所以 log.Printf("Reading %s: %v", filename, err) 格式中没有假的大写字母。这不适用于日志记录,日志记录是隐式的面向行的,不会在其他消息中组合。

相关文章
|
5月前
|
程序员 Go API
|
11天前
|
存储 监控 算法
员工上网行为监控中的Go语言算法:布隆过滤器的应用
在信息化高速发展的时代,企业上网行为监管至关重要。布隆过滤器作为一种高效、节省空间的概率性数据结构,适用于大规模URL查询与匹配,是实现精准上网行为管理的理想选择。本文探讨了布隆过滤器的原理及其优缺点,并展示了如何使用Go语言实现该算法,以提升企业网络管理效率和安全性。尽管存在误报等局限性,但合理配置下,布隆过滤器为企业提供了经济有效的解决方案。
52 8
员工上网行为监控中的Go语言算法:布隆过滤器的应用
|
1月前
|
存储 Go 索引
go语言中数组和切片
go语言中数组和切片
41 7
|
1月前
|
Go 开发工具
百炼-千问模型通过openai接口构建assistant 等 go语言
由于阿里百炼平台通义千问大模型没有完善的go语言兼容openapi示例,并且官方答复assistant是不兼容openapi sdk的。 实际使用中发现是能够支持的,所以自己写了一个demo test示例,给大家做一个参考。
|
1月前
|
程序员 Go
go语言中结构体(Struct)
go语言中结构体(Struct)
102 71
|
30天前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
106 67
|
1月前
|
Go 索引
go语言for遍历数组或切片
go语言for遍历数组或切片
101 62
|
6天前
|
算法 安全 Go
Go 语言中实现 RSA 加解密、签名验证算法
随着互联网的发展,安全需求日益增长。非对称加密算法RSA成为密码学中的重要代表。本文介绍如何使用Go语言和[forgoer/openssl](https://github.com/forgoer/openssl)库简化RSA加解密操作,包括秘钥生成、加解密及签名验证。该库还支持AES、DES等常用算法,安装简便,代码示例清晰易懂。
33 12
|
1月前
|
存储 Go
go语言中映射
go语言中映射
38 11
|
1月前
|
Go
go语言for遍历映射(map)
go语言for遍历映射(map)
37 12