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) 格式中没有假的大写字母。这不适用于日志记录,日志记录是隐式的面向行的,不会在其他消息中组合。

相关文章
|
3月前
|
程序员 Go API
|
2天前
|
安全 网络协议 Go
Go语言网络编程
【10月更文挑战第28天】Go语言网络编程
88 65
|
2天前
|
网络协议 安全 Go
Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
【10月更文挑战第28天】Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
22 13
|
2天前
|
网络协议 安全 Go
Go语言的网络编程基础
【10月更文挑战第28天】Go语言的网络编程基础
16 8
|
1天前
|
Go
go语言的复数常量
【10月更文挑战第21天】
12 6
|
1天前
|
Go
go语言的浮点型常量
【10月更文挑战第21天】
8 4
|
1天前
|
编译器 Go
go语言的整型常量
【10月更文挑战第21天】
6 3
|
2天前
|
Go
go语言编译时常量表达式
【10月更文挑战第20天】
10 3
|
1天前
|
Serverless Go
Go语言中的并发编程:从入门到精通
本文将深入探讨Go语言中并发编程的核心概念和实践,包括goroutine、channel以及sync包等。通过实例演示如何利用这些工具实现高效的并发处理,同时避免常见的陷阱和错误。
|
2天前
|
安全 Go 开发者
代码之美:Go语言并发编程的优雅实现与案例分析
【10月更文挑战第28天】Go语言自2009年发布以来,凭借简洁的语法、高效的性能和原生的并发支持,赢得了众多开发者的青睐。本文通过两个案例,分别展示了如何使用goroutine和channel实现并发下载网页和构建并发Web服务器,深入探讨了Go语言并发编程的优雅实现。
8 2