模块课程(1/5)
命名约定和风格
Go 具有 强大 和 不可协商 的命名和样式约定:官方格式化程序 gofmt (及其超集 goimports)决定缩进、间距和导入顺序。讨论风格被认为是偏离主题的:您运行 gofmt -w 并继续。这可以释放能量来解决更有趣的问题。
可见性:大写或小写
没有 public/private 关键字。 名称的第一个字母决定可见性:
- 大写 → 导出到包外(
User、Login、MaxRetries)。 - 小写 → 包私有(
user、parseLine、defaultTimeout)。
这适用于:类型、函数、方法、变量、常量、结构字段。
type User struct {
Name string // exported
email string // private to the package
}“私有”结构字段不由 encoding/json 序列化(请参阅模块 8),并且无法从 pkg_test 中的测试访问它。
CamelCase,绝不是snake_case
多单词名称中没有下划线:
- ✅
HTTPClient、userName、parseRequest-❌Http_Client、user_name、parse_request
首字母缩略词全部大写(或者全部小写,如果在私有范围内):
- ✅
URL、ID、HTML、JSON、parseURL、userID - ❌
Url、Id、Html、Json、parseUrl、userId
type APIResponse struct {
UserID int
HTMLURL string
}短范围的短名称
Go 风格倾向于在狭窄的范围内简洁但同样清晰:
// idiomatic
for i, v := range items { ... }
for k, v := range m { ... }
if err := f(); err != nil { ... }
func (s *Server) Serve(w http.ResponseWriter, r *http.Request) { ... }已建立的约定:
i, j, k用于循环索引。v用于值,k用于键。r表示*Request/io.Reader,w表示Writer/ResponseWriter。err表示错误。ctx代表context.Context。- 方法接收者:整个类型中 1-2 个一致的字母(
s *Server、u *User)。切勿使用this或self。
范围越广,名称必须越具有描述性:本地 count 很好,但导出的 Count 变量应该告诉您它的含义。
接口上没有“I”前缀,没有“Impl”后缀
// idiomatic
type Reader interface { ... }
type fileReader struct { ... } // concrete implementation
// not idiomatic
type IReader interface { ... }
type ReaderImpl struct { ... }小接口通常采用 -er 后缀:Reader、Writer、Stringer、Closer。它呼应了他们描述一种行为(理想情况下是单一方法)的事实。
包名
包有单个名称,简短,全部小写,无下划线:
- ✅
bytes、http、os、userauth-❌userAuth、user_auth、UserAuth
包名称是其符号的使用前缀:bytes.Buffer、http.Client。所以 user.User 是多余的:最好重命名类型(user.Account)或包。
gofmt 没有争议
gofmt 强制执行:
- 使用制表符(不是空格)缩进。
- 将
{与签名放在同一行。 - 以空行分隔的分组导入;
goimports还添加了缺失的导入。 - 操作员周围的空间。
始终在提交之前运行:
go fmt ./...
goimports -w .
go vet ./...Linters(staticcheck、golangci-lint)添加额外的规则(未使用的变量、阴影、无用的比较,...)。
练习
HTTPClient 中的 Http_Client 结构(即 URL 中的 Url)的名称将在缩写中出现。
3 次尝试后可用的解决方案
可见性反转:用户名 esportato (maiuscolo) 和密码 privato (minuscolo)。
3 次尝试后可用的解决方案
Go 中“服务器 HTTP”的问题是什么?
type ??? struct {}