写一段有着Golang风格的代码
首先
這篇文章還不完善。我認為Golang風格的程式碼就像文化一樣,所以我希望能夠吸收不同方向的意見,使這篇文章更豐富。謝謝。
在这段看似典型的代码之前
我会总结一下全语言通用的规则。对于想学习优雅代码的人来说,我的推荐是《可读代码》这本书。不仅如此,作为工程师,我绝对希望你能读一读它。
高可读性的代码
在阅读时需要记住的事情很少。
-
- シンプルに作られている
-
- 変数のスコープはできるだけ小さく
- ネストは浅く、関数は短く
这个意图很容易理解。
-
- 適切なコメントが添えてある
- 設計の背景などがドキュメントにまとまっている
再现性易于获得
-
- ライブラリのバージョン管理がきっちりされている
-
- ビルドやテストがMakefileやスクリプトで再現できる
- 適度に抽象化されていてテストが外部依存してない
像是Go的程式码。
静态解析工具
如果不使用静态分析工具,基本上无法通过拉取请求。
註釋掉
留言必须以被描述事物的名称开始,并以句点结尾。
// 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) { ...
原文:I’m planning to go out for dinner tonight.
Chinese Paraphrase: 我打算今晚出去吃晚饭。
在API和流程的一系列流程中,我们需要使用上下文(Context)来管理需要保留的值。具体来说,这些值包括安全证书信息、跟踪信息、截止日期和取消信号等。几乎所有使用Context的函数都将其作为第一个参数。
func F(ctx context.Context, /* other arguments */) {}
切片
var t []string
t := []string{}
上面返回空切片,下面返回非空切片。无论是cap还是len都为零,但上面的空切片是首选样式。然而,在编码JSON对象时,将优先使用非空切片。此外,在设计接口时,请不要区分空切片和非空的长度为零的切片,因为这可能导致轻微的编程错误。
随机数生成器
请在生成密钥的时候不要使用这个包,因为它会产生可预测的值而没有种子。相反,请使用 crypto/rand 包的读取器,并使用十六进制或 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)
}
不要使用”panic”
请不要在常规错误处理中使用panic。应该使用错误和多返回值。
关于错误字符串
错误字符串通常根据上下文输出,请不要将其转换为大写。但是,如果它们以专有名词或首字母开头,应该使用大写字母。
//これはよくない
fmt.Errorf("Something bad")
//通常はこのようにフォーマットされて出力されます。
fmt.Errorf("something bad")
log.Printf("Reading %s: %v", filename, err)
关于错误处理
当函数的返回值是错误时,必须确保接收并进行处理。只有在真正发生异常的情况下,才应使用panic。另外,在发生错误时,请先编写错误处理代码。
关于包含if语句的错误处理。
//これはよくない例
if x, err := f(); err != nil {
// error handling
return
} else {
// use x
}
//こっちがよい例
x, err := f()
if err != nil {
// error handling
return
}
// use x
有关”import”的事项
除非为了避免命名冲突,否则请不要更改导入的名称。如果要避免冲突,请使用项目特定的名称。
关于变量和函数
在中文中,通常会给ID、HTTP、URL等命名使用大写字母。例如,不会将”URL”命名为”Url”,而是保留为”URL”。关于用户ID,也会使用”userID”类似的命名方式。另外,golang的命名风格是驼峰式。
此外,与其他编程语言不同的是,golang不喜欢过长的名称,并且允许一定程度的缩写。
另外,由于golang的作用域很严格,请在使用变量之前进行声明。
接口
请不要在接口中定义不打算使用的函数。
如果要传递值
除了大型结构体和可能会变大的切片外,请不要将参数设为指针类型。
方法的接收者
只要保持一致性,並且名稱簡短且反映其身份即可。如果是客戶端,使用「c」或「cl」即可。方法的參數必須包含說明性的元素,但接收者的角色明確,所以簡潔性最受歡迎。
此外,請不要使用具有特殊意義的面向對象編程語言的典型識別符,如「me」、「this」、「self」等常見名稱。
接收器的类型
在使用指针接收器的决策标准上
-
- レシーバがmap、func、またはchanの場合、それらへのポインターを使用しないでください。レシーバーがスライスであり、メソッドがスライスの再スライスまたは再割り当てを行わない場合、そのポインターを使用しないでください。
-
- メソッドがレシーバーを変更する必要がある場合、レシーバーはポインターでなければなりません。
-
- レシーバがsync.Mutexまたは同様の同期フィールドを含む構造体である場合、受信者はコピーを避けるためにポインターでなければなりません。
-
- レシーバーが大きな構造体または配列の場合、ポインターレシーバーの方が効率的です。
-
- レシーバーが構造体、配列、またはスライスであり、その要素のいずれかが変化している可能性のある場合は、ポインターレシーバーを優先します。
-
- 受信者が小さな配列または構造体の場合や可変フィールドとポインターがない場合、またはintやstringなどの単純な基本型である場合、ポインタレシーバは必要ないです。
- 疑わしい場合はポインタレシーバを使います。
获取者
我们应该将其命名为Xxx,而不是GetXxx。
参考网站
进行代码审查评论