Golang 命名规范大全

一、文件系统规范

1.1 文件命名规范

定义
Go 源文件的命名需要遵循特定的格式约定,以保证项目的一致性和可读性。

详细解释

  1. 全小写规则:文件名必须全部使用小写字母,这是Go社区的普遍约定

    • 正确:user_service.go
    • 错误:UserService.go
  2. 单词分隔:多个单词之间使用下划线_连接,不使用驼峰式

    • 正确:http_handler.go
    • 错误:httpHandler.go
  3. 避免特殊字符:除了下划线外,不应包含其他特殊字符或空格

    • 正确:data_processor.go
    • 错误:data-processor.go
  4. 测试文件:测试文件必须使用_test.go后缀

    • 正确:string_util_test.go
    • 错误:string_util.test.go
  5. 构建约束文件:需要构建标签的文件使用_os_arch.go格式

    • 示例:database_linux_amd64.go

理由

  • 保持跨平台兼容性(不同操作系统对大小写敏感度不同)
  • 提高代码搜索效率(统一格式便于查找)
  • 与Go工具链良好配合(特别是测试文件识别)

二、目录结构规范

2.1 项目目录结构

定义
Go项目的目录组织方式应该遵循标准布局模式。

详细解释

/project-root
/cmd # 主程序入口目录
/app1 # 单个可执行程序
main.go
/app2
main.go
/internal # 私有代码(禁止外部导入)
/auth
auth.go
/pkg # 可公开的库代码
/lib1
lib.go
/api # API协议定义
swagger.json
/web # 网页资源
static/
templates/

关键规则

  1. cmd目录:

    • 每个子目录代表一个独立可执行程序
    • 目录名应与可执行文件名称一致
  2. internal目录:

    • 该目录下的代码只能被本项目的其他代码导入
    • Go编译器会强制实施此规则
  3. pkg目录:

    • 存放可供其他项目导入的公共库
    • 应该设计清晰的API边界

最佳实践

  • 保持目录层级扁平(通常不超过3层)
  • 按功能而非类型组织目录(如/user而非/models+/controllers
  • 避免过度细分目录(单个文件可以包含多个相关类型)

三、包设计规范

3.1 包命名规则

定义
Go包的命名需要遵循特定的语义规则。

详细解释

  1. 基本规则

    • 全部小写字母
    • 不使用下划线或驼峰
    • 使用单数形式
    • 简短但有描述性
    类型 好例子 坏例子
    工具包 stringutil stringsutil
    接口包 provider providers
    功能包 time timeutils
  2. 特殊约定

    • 避免通用名称(如commonutil
    • 测试包使用_test后缀
    • 内部包可以使用internal前缀
  3. 域名反转
    对于公开仓库,使用域名反转格式:

    package github.com/user/project/pkg

设计原则

  1. 高内聚:一个包应该只解决一个特定问题
  2. 低耦合:包之间的依赖应该最小化
  3. 显式依赖:所有依赖都应该在import中明确声明

四、代码组织规范

4.1 代码布局规则

定义
Go源文件内部的代码组织方式。

详细解释

  1. 标准结构
// 包注释(对整个包的描述)
package httputil

// 导入分组(标准库/第三方/本地)
import (
"fmt"
"net/http"

"github.com/pkg/errors"
)

// 常量组
const (
DefaultTimeout = 30 * time.Second
MaxRetries = 3
)

// 变量组
var (
registry = make(map[string]Handler)
mutex sync.RWMutex
)

// 类型定义
type Client struct {
// ...
}

// 方法实现
func (c *Client) Get(url string) ([]byte, error) {
// ...
}

// 函数定义
func NewClient() *Client {
// ...
}
  1. 排序规则

    • 从最重要到最不重要
    • 从公开到私有
    • 从一般到特殊
  2. 大小限制

    • 单个文件建议不超过1000行
    • 单个函数建议不超过100行

五、接口设计规范

5.1 接口定义规则

定义
Go接口的设计哲学和最佳实践。

详细解释

  1. 基本形式
// 单方法接口(通常以-er结尾)
type Reader interface {
Read(p []byte) (n int, err error)
}

// 多方法接口
type HTTPClient interface {
Get(url string) ([]byte, error)
Post(url string, data []byte) ([]byte, error)
Do(req *http.Request) (*http.Response, error)
}
  1. 设计原则
    • 小而美:接口应该尽可能小
    • 解耦合:接口应该定义在使用方
    • 组合优于继承
type ReadWriter interface {
Reader
Writer
}
  1. 接口验证
// 编译时接口实现检查
var _ io.Reader = (*FileReader)(nil)

// 运行时类型断言
if writer, ok := v.(io.Writer); ok {
// 使用writer
}

六、错误处理规范

6.1 错误定义规则

定义
Go中错误处理的标准方式。

详细解释

  1. 错误类型
// 哨兵错误
var ErrNotFound = errors.New("not found")

// 错误类型
type ParseError struct {
Line int
Column int
Message string
}

func (e *ParseError) Error() string {
return fmt.Sprintf("%d:%d: %s", e.Line, e.Column, e.Message)
}
  1. 错误处理
// 简单错误
if err != nil {
return err
}

// 错误包装
if err != nil {
return fmt.Errorf("get user failed: %w", err)
}

// 错误判断
if errors.Is(err, ErrNotFound) {
// 处理特定错误
}

var pe *ParseError
if errors.As(err, &pe) {
// 处理ParseError
}

七、并发编程规范

7.1 Goroutine管理

定义
Go并发编程的最佳实践。

详细解释

  1. 基本模式
// 带错误处理的goroutine
go func() {
defer wg.Done()
if err := doWork(); err != nil {
errCh <- err
}
}()
  1. 资源清理
// 使用context控制生命周期
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

go worker(ctx)
  1. 通道规则
// 命名建议
jobsCh := make(chan Job, 10) // 带缓冲
done := make(chan struct{}) // 信号通道

// 方向限定
func worker(jobs <-chan Job, results chan<- Result) {
// ...
}

八、测试规范

8.1 测试编写规则

定义
Go测试的标准编写方式。

详细解释

  1. 表格驱动测试
func TestParse(t *testing.T) {
tests := []struct {
name string
input string
want string
wantErr bool
}{
{
name: "simple case",
input: "a=b",
want: "b",
},
// ...
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Parse(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf(...)
}
if got != tt.want {
t.Errorf(...)
}
})
}
}
  1. 测试辅助函数
func setupTestDB(t *testing.T) *sql.DB {
db, err := sql.Open("sqlite3", ":memory:")
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { db.Close() })
return db
}

九、文档规范

9.1 注释规则

定义
Go代码文档的标准格式。

详细解释

  1. 包注释
// Package strings implements simple functions to manipulate UTF-8 encoded strings.
package strings
  1. 导出元素注释
// Join concatenates the elements of its first argument to create a single string.
// The separator string sep is placed between elements in the resulting string.
func Join(elems []string, sep string) string
  1. 示例代码
func ExampleJoin() {
s := []string{"foo", "bar", "baz"}
fmt.Println(strings.Join(s, ", "))
// Output: foo, bar, baz
}

十、性能优化规范

10.1 性能编码规则

定义
Go性能敏感代码的编写准则。

详细解释

  1. 内存分配
// 切片预分配
names := make([]string, 0, 100)

// 重用缓冲区
var buf bytes.Buffer
for i := 0; i < 100; i++ {
buf.Reset()
// 使用buf
}
  1. 并发模式
// worker池模式
jobs := make(chan Job, 100)
results := make(chan Result, 100)

// 启动workers
for w := 0; w < 10; w++ {
go worker(jobs, results)
}

总结

Go语言的这些规范源于以下几个核心理念:

  1. 简单性:通过约定减少决策负担
  2. 一致性:统一风格提高可读性
  3. 实用性:规范服务于实际开发需求
  4. 可维护性:长期项目维护的便利性

记住:规范不是教条,当有充分理由时,可以适当变通。但团队内部应该保持统一的标准。