// 好的命名
package http
package json
package user
// 不好的命名
package httpClient
package user_service
// 公开变量
var MaxSize int
var DefaultTimeout = 30 * time.Second
// 私有变量
var maxSize int
var defaultTimeout = 30 * time.Second
// 简短命名(局部变量)
for i := 0; i < 10; i++ { }
for _, v := range slice { }
// 公开函数
func GetUser(id int) (*User, error)
func CalculateTotal(items []Item) int
func NewUserService() *UserService
// 私有函数
func getUserByID(id int) (*User, error)
func calculateTotal(items []Item) int
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type Closer interface {
Close() error
}
// 公开常量
const (
StatusOK = 200
StatusError = 500
)
// 私有常量
const (
defaultPort = 8080
maxRetryCount = 3
)
# 格式化代码
gofmt -w main.go
# 格式化整个项目
gofmt -w .
// 使用 Tab 缩进
func main() {
if true {
fmt.Println("Hello")
}
}
// 运算符两侧加空格
result := a + b
if x > 0 {
// ...
}
// 逗号后加空格
func add(a, b int) int {
return a + b
}
import (
// 标准库
"fmt"
"os"
// 第三方库
"github.com/gin-gonic/gin"
"gorm.io/gorm"
// 本地包
"myproject/internal/user"
"myproject/pkg/utils"
)
// Package user 提供用户管理功能。
//
// 该包包含用户的 CRUD 操作、认证和授权功能。
// 使用 NewService 创建服务实例。
//
// 示例:
//
// service := user.NewService(db)
// user, err := service.GetByID(1)
package user
// GetByID 根据用户 ID 获取用户信息。
//
// 参数:
// - id: 用户 ID
//
// 返回:
// - *User: 用户信息
// - error: 错误信息,用户不存在时返回 ErrNotFound
//
// 示例:
//
// user, err := service.GetByID(1)
// if err != nil {
// log.Fatal(err)
// }
func (s *Service) GetByID(id int) (*User, error) {
// ...
}
// User 表示系统用户。
type User struct {
ID int // 用户 ID
Username string // 用户名
Email string // 邮箱地址
Status int // 状态:1-正常,0-禁用
}
// TODO(username): 添加缓存支持
// FIXME(username): 修复并发问题
// NOTE: 这里使用了特殊算法
// 哨兵错误
var ErrNotFound = errors.New("记录不存在")
// 自定义错误类型
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("验证错误 [%s]: %s", e.Field, e.Message)
}
// 好的做法:及早返回
func Process(data string) error {
if data == "" {
return errors.New("数据不能为空")
}
result, err := parse(data)
if err != nil {
return fmt.Errorf("解析失败: %w", err)
}
return save(result)
}
// 不好的做法:嵌套太深
func ProcessBad(data string) error {
if data != "" {
result, err := parse(data)
if err == nil {
err = save(result)
if err == nil {
return nil
} else {
return err
}
} else {
return err
}
} else {
return errors.New("数据不能为空")
}
}
myproject/
├── cmd/ # 主应用程序
│ ├── api/
│ │ └── main.go
│ └── cli/
│ └── main.go
├── internal/ # 私有代码
│ ├── handler/
│ ├── service/
│ ├── repository/
│ └── model/
├── pkg/ # 公开代码
│ └── utils/
├── api/ # API 定义
│ └── proto/
├── configs/ # 配置文件
├── docs/ # 文档
├── scripts/ # 脚本
├── test/ # 测试
├── go.mod
├── go.sum
├── Makefile
└── README.md
mylib/
├── cache.go
├── cache_test.go
├── options.go
├── internal/
│ └── store/
├── examples/
├── go.mod
├── go.sum
├── LICENSE
└── README.md
// 好的做法:小接口
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
// 不好的做法:大接口
type ReadWriter interface {
Read(p []byte) (n int, err error)
Write(p []byte) (n int, err error)
Close() error
Flush() error
}
// 单方法接口以 "er" 结尾
type Reader interface { Read(...) }
type Writer interface { Write(...) }
type Closer interface { Close(...) }
// 组合接口
type ReadWriter interface {
Reader
Writer
}
// 好的做法:传递 Context
func Process(ctx context.Context, data string) {
go func() {
select {
case <-ctx.Done():
return
default:
// 处理逻辑
}
}()
}
// 不好的做法:无法控制
func ProcessBad(data string) {
go func() {
// 无法停止
}()
}
// 好的做法:发送方关闭
func producer(ch chan<- int) {
defer close(ch)
for i := 0; i < 10; i++ {
ch <- i
}
}
// 接收方检查关闭
func consumer(ch <-chan int) {
for v := range ch {
fmt.Println(v)
}
}
// user_test.go
package user
import "testing"
func TestGetByID(t *testing.T) {
tests := []struct {
name string
id int
want *User
wantErr bool
}{
{"正常", 1, &User{ID: 1}, false},
{"不存在", 999, nil, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := GetByID(tt.id)
if (err != nil) != tt.wantErr {
t.Errorf("GetByID() error = %v, wantErr %v", err, tt.wantErr)
}
// ...
})
}
}
func BenchmarkGetByID(b *testing.B) {
for i := 0; i < b.N; i++ {
GetByID(1)
}
}
gofmt 格式化go vet 检查go.mod# 格式化
gofmt -w .
# 静态检查
go vet ./...
# 测试
go test ./...
# 竞态检测
go test -race ./...
# 代码检查
golangci-lint run
本章介绍了 Go 语言的编码规范:
遵循规范能让你写出更专业、更易维护的 Go 代码。在下一章中,我们将学习常用标准库。