google-go-style

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Google Go Style — Skill

Google Go 风格指南 — 技能摘要

Derived from the Google Go Style Guide, © Google LLC, licensed CC-BY 3.0. This skill is a derivative digest, not a verbatim reproduction.
Codifies the Google Go Style Guide (canonical + normative + best-practices) into actionable rules.
The full guide is large. This file holds only what should be in your head on every Go change. For deeper rules, load the matching
references/*.md
. For unusual situations, WebFetch the source — the guide is normative.
改编自Google Go 风格指南,© Google LLC,采用CC-BY 3.0许可。本技能摘要是衍生精简版,并非逐字复制。
Google Go 风格指南(规范准则+最佳实践)转化为可执行的规则。
完整指南内容庞大,本文仅涵盖每次修改Go代码时需牢记的核心规则。如需更详细的规则,请查看对应的
references/*.md
文件。遇到特殊情况时,请直接查阅官方指南——它是权威依据。

Quick Rules

快速规则

Apply on every line of Go you write or review.
编写或评审每一行Go代码时都应遵循以下规则。

Naming

命名规范

  • No
    Get
    prefix on getters.
    User()
    , not
    GetUser()
    . Exception: the underlying concept is "get" (HTTP GET).
  • Don't repeat the package name in identifiers.
    bytes.Buffer
    , not
    bytes.BytesBuffer
    .
    widget.New
    , not
    widget.NewWidget
    .
  • Receiver names: 1–2 letters, abbreviation of the type, consistent across all methods. Never
    this
    ,
    self
    ,
    me
    , or
    _
    (unless unused).
    func (c *Config)
    , not
    func (config *Config)
    .
  • Initialisms keep one case.
    URL
    ,
    ID
    ,
    HTTP
    ,
    DB
    . Exported:
    UserID
    ,
    ServeHTTP
    . Unexported:
    userID
    ,
    urlPath
    . Never
    Url
    ,
    Id
    ,
    Http
    .
  • Test doubles end in
    Stub
    /
    Fake
    /
    Spy
    /
    Mock
    (or describe behaviour:
    AlwaysCharges
    ,
    AlwaysDeclines
    ).
  • No
    util
    /
    common
    /
    helper
    /
    model
    package names.
    They invite import renames at every call site. Name by what the package provides.
  • No underscores in identifiers (except
    *_test.go
    test/benchmark/example names, and packages imported only by generated code).
  • Local variable scope ↔ name length.
    i
    ,
    c
    ,
    db
    for tight loops;
    userCount
    ,
    pollInterval
    for file scope. Don't drop letters to save typing (
    Sandbox
    , not
    Sbx
    ).
  • Getter 不要加
    Get
    前缀
    。应使用
    User()
    ,而非
    GetUser()
    。例外情况:底层概念本身就是“获取”(如HTTP GET)。
  • 标识符中不要重复包名。例如
    bytes.Buffer
    ,而非
    bytes.BytesBuffer
    widget.New
    ,而非
    widget.NewWidget
  • 接收器名称:1-2个字母,为类型的缩写,且在所有方法中保持一致。绝不要使用
    this
    self
    me
    _
    (除非未被使用)。例如
    func (c *Config)
    ,而非
    func (config *Config)
  • 首字母缩写词保持统一大小写。例如
    URL
    ID
    HTTP
    DB
    。导出标识符:
    UserID
    ServeHTTP
    ;非导出标识符:
    userID
    urlPath
    。绝不要使用
    Url
    Id
    Http
  • 测试替身以
    Stub
    /
    Fake
    /
    Spy
    /
    Mock
    结尾
    (或描述其行为:
    AlwaysCharges
    AlwaysDeclines
    )。
  • 不要使用
    util
    /
    common
    /
    helper
    /
    model
    作为包名
    。这类包名会导致调用时频繁重命名导入。应根据包提供的功能来命名。
  • 标识符中不要使用下划线(仅
    *_test.go
    测试/基准测试/示例文件的名称,以及仅被生成代码导入的包除外)。
  • 局部变量的作用域与名称长度对应。循环中使用
    i
    c
    db
    等短名称;文件级作用域使用
    userCount
    pollInterval
    等长名称。不要为了节省输入而省略字母(如
    Sandbox
    ,而非
    Sbx
    )。

Errors

错误处理

  • fmt.Errorf("doing X: %w", err)
    — wrap with
    %w
    at the end, so the chain prints newest→oldest as
    outer: middle: inner
    .
  • %w
    only when callers need
    errors.Is
    /
    errors.As
    on the underlying error. Otherwise use
    %v
    .
  • %w
    at the start
    is for sentinel wrappers only:
    fmt.Errorf("%w: invalid header", ErrParse)
    . Category first, details after.
  • Sentinel name:
    ErrFoo
    at package level:
    var ErrNotFound = errors.New("not found")
    .
  • Don't duplicate context the underlying error already carries.
    os.Open
    errors already include the path —
    fmt.Errorf("could not open settings.txt: %v", err)
    is wrong; use a higher-level annotation:
    fmt.Errorf("launch codes unavailable: %v", err)
    .
  • Don't add bare "failed: %v" wrappers. They add no information; just
    return err
    .
  • Either log it or return it — not both. Pick one. Letting the caller log avoids spam.
  • Error strings: lowercase, no trailing punctuation, no
    \n
    .
    fmt.Errorf("something bad happened")
    , not
    "Something bad happened."
    .
  • Cross-process boundaries (gRPC/RPC): use canonical codes via
    status.Errorf(codes.X, ...)
    rather than wrapping internal errors raw with
    %w
    .
  • error
    is the last return value.
    A function taking
    context.Context
    should usually return
    error
    .
For more, see
references/errors.md
.
  • fmt.Errorf("执行X: %w", err)
    — 在末尾使用
    %w
    进行包装,这样错误链会按从新到旧的顺序打印为
    outer: middle: inner
  • 仅当调用者需要使用
    errors.Is
    /
    errors.As
    检查底层错误时,才使用
    %w
    。否则使用
    %v
  • %w
    放在开头仅用于哨兵错误包装
    fmt.Errorf("%w: 无效头部", ErrParse)
    。先分类,后加细节。
  • 哨兵错误命名:包级别的
    ErrFoo
    var ErrNotFound = errors.New("not found")
  • 不要重复底层错误已携带的上下文信息
    os.Open
    的错误已包含路径——
    fmt.Errorf("无法打开settings.txt: %v", err)
    是错误的;应使用更高层级的注解:
    fmt.Errorf("启动代码不可用: %v", err)
  • 不要添加无意义的“failed: %v”包装。这类包装没有任何信息,直接
    return err
    即可。
  • 要么记录日志,要么返回错误——不要同时做。选择其一,让调用者记录日志可避免重复输出。
  • 错误字符串:小写,无结尾标点,无
    \ 
    。例如
    fmt.Errorf("something bad happened")
    ,而非
    "Something bad happened."
  • 跨进程边界(gRPC/RPC):使用标准错误码,通过
    status.Errorf(codes.X, ...)
    实现,而非直接用
    %w
    包装内部错误。
  • error
    是最后一个返回值
    。接收
    context.Context
    的函数通常应返回
    error
如需更多细节,请查看
references/errors.md

Panics

Panic 使用规范

  • Don't panic for normal error handling. Return
    error
    and multiple return values.
  • log.Fatal
    over
    panic
    for terminal conditions in
    main
    /
    init
    . Fatal does not run deferred functions; that's the point.
  • Panics never cross package boundaries in public APIs. Convert to
    error
    at the API edge with a top-level
    defer recover()
    that re-panics on unknown payloads.
  • MustX
    is for package-level vars and tests only.
    MustParse
    ,
    template.Must
    . Not for runtime user input.
  • Don't
    recover()
    to suppress crashes.
    Corrupted state propagates further; better is monitoring + crash + fix.
  • panic("unreachable")
    after
    log.Fatalf
    is the idiom — the compiler doesn't know
    Fatal
    doesn't return.
For more, see
references/panics.md
.
  • 正常错误处理不要使用panic。应返回
    error
    和多返回值。
  • 终端场景使用
    log.Fatal
    而非
    panic
    ,如
    main
    /
    init
    中的致命条件。
    Fatal
    不会执行延迟函数,这正是其设计目的。
  • 公共API中panic绝不能跨包传播。在API边界处通过顶层
    defer recover()
    将其转换为
    error
    ,并对未知错误重新触发panic。
  • MustX
    仅用于包级变量和测试
    。例如
    MustParse
    template.Must
    。不要用于运行时用户输入。
  • 不要通过
    recover()
    抑制崩溃
    。损坏的状态会进一步扩散,更好的方式是监控+崩溃+修复。
  • log.Fatalf
    后使用
    panic("unreachable")
    是标准写法
    ——编译器不知道
    Fatal
    不会返回。
如需更多细节,请查看
references/panics.md

Tests

测试规范

  • No assertion libraries / helpers (
    assert.Equal
    ,
    require.NotNil
    ). Use
    if got != want { t.Errorf(...) }
    . For complex types:
    cmp.Equal
    /
    cmp.Diff
    from
    go-cmp
    .
  • t.Error
    over
    t.Fatal
    by default — keep going, report all failures in one run.
    t.Fatal
    only when continuing is meaningless (setup failed, cascading errors would mislead).
  • Inside
    t.Run
    subtests: use
    t.Fatal
    to skip just that case. Outside subtests in a table loop:
    t.Error
    +
    continue
    .
  • NEVER call
    t.Fatal
    (
    FailNow
    ,
    Fatalf
    ,
    SkipNow
    ) from a goroutine other than the test's own.
    Use
    t.Error
    from worker goroutines;
    t.Fatal
    only after
    wg.Wait()
    from the main goroutine.
  • Table-driven tests use named struct fields, not positional:
    {name: "empty", input: "", want: ""}
    .
  • Test helpers that fail setup call
    t.Helper()
    +
    t.Fatalf
    .
    This makes the failure point to the test line, not the helper line.
  • Failure message format:
    YourFunc(%v) = %v, want %v
    — function name, inputs, got, want, in that order.
For more, see
references/tests.md
.
  • 不要使用断言库/辅助函数(如
    assert.Equal
    require.NotNil
    )。使用
    if got != want { t.Errorf(...) }
    。对于复杂类型:使用
    go-cmp
    包中的
    cmp.Equal
    /
    cmp.Diff
  • 默认使用
    t.Error
    而非
    t.Fatal
    ——继续执行,一次运行报告所有失败。仅当继续执行无意义时(如初始化失败、级联错误会误导结果)才使用
    t.Fatal
  • t.Run
    子测试中:使用
    t.Fatal
    ——仅跳过当前测试用例。在表循环的子测试外部:使用
    t.Error
    +
    continue
  • 绝不要从测试主goroutine以外的goroutine调用
    t.Fatal
    FailNow
    Fatalf
    SkipNow
    。工作goroutine中使用
    t.Error
    ;仅在主goroutine中
    wg.Wait()
    之后使用
    t.Fatal
  • 表驱动测试使用命名结构体字段,而非位置参数:
    {name: "empty", input: "", want: ""}
  • 初始化失败的测试辅助函数应调用
    t.Helper()
    +
    t.Fatalf
    。这样失败信息会指向测试代码行,而非辅助函数行。
  • 失败消息格式:
    YourFunc(%v) = %v, want %v
    ——按函数名、输入、实际结果、预期结果的顺序排列。
如需更多细节,请查看
references/tests.md

Variables and strings

变量与字符串

  • :=
    for non-zero init,
    var x T
    for zero values.
    i := 42
    , but
    var coords Point
    (not
    coords := Point{}
    ).
  • var t []string
    , not
    t := []string{}
    for empty slices. Empty slice and nil slice behave the same for
    len
    ,
    cap
    ,
    range
    ,
    append
    .
  • new(T)
    vs
    &T{}
    : both are fine for zero values;
    new
    reads as "zero value placeholder",
    &T{}
    is more common when fields are filled.
  • Never
    ==
    on
    nil
    for slices.
    Use
    len(s) == 0
    . APIs must not distinguish nil from empty.
  • Strings:
    +
    for 2–3 short literals;
    fmt.Sprintf
    for formatting;
    strings.Builder
    in loops;
    text/template
    for templates.
  • Pre-size with
    make([]T, 0, n)
    /
    make(map[K]V, n)
    only when
    n
    is known and the code is performance-sensitive. Default to zero-init.
  • No shadowing in nested scopes.
    if *x { ctx, cancel := ...; }
    shadows
    ctx
    outside the
    if
    . Use
    ctx, cancel = ...
    with
    =
    and
    var cancel func()
    declared above.
For more, see
references/strings-and-vars.md
.
  • 非零值初始化使用
    :=
    ,零值使用
    var x T
    。例如
    i := 42
    ,但
    var coords Point
    (而非
    coords := Point{}
    )。
  • 空切片使用
    var t []string
    ,而非
    t := []string{}
    。空切片和nil切片在
    len
    cap
    range
    append
    中的行为一致。
  • new(T)
    vs
    &T{}
    :零值初始化时两者均可;
    new
    可理解为“零值占位符”,填充字段时
    &T{}
    更常用。
  • 切片不要用
    ==
    判断是否为nil
    。使用
    len(s) == 0
    。API不应区分nil和空切片。
  • 字符串拼接:2-3个短字面量使用
    +
    ;格式化使用
    fmt.Sprintf
    ;循环中使用
    strings.Builder
    ;模板使用
    text/template
  • 仅当已知大小且代码对性能敏感时,才预分配空间
    make([]T, 0, n)
    /
    make(map[K]V, n)
    。默认使用零值初始化。
  • 嵌套作用域中不要发生变量遮蔽。例如
    if *x { ctx, cancel := ...; }
    会遮蔽外部的
    ctx
    。应在上方声明
    var cancel func()
    ,然后使用
    ctx, cancel = ...
如需更多细节,请查看
references/strings-and-vars.md

API design

API设计

  • context.Context
    is the first parameter.
    func F(ctx context.Context, ...) error
    . Even in test helpers.
  • Never store
    context.Context
    in a struct.
    Pass it through every method that needs it.
  • No global mutable state. Pass dependencies through constructors / function parameters (DI).
  • Take interfaces, return concrete types. The consumer of an interface defines it, not the implementer.
  • Channel direction in signatures.
    <-chan T
    for receive-only,
    chan<- T
    for send-only.
  • Many parameters → option struct (call site reads as labelled fields). 3+ optional / API expected to grow → option struct. Don't put
    context.Context
    in option structs.
  • Variadic functional options (
    ...Option
    )
    only when most callers pass nothing, options need parameters, or third parties define options.
  • Avoid
    *string
    ,
    *io.Reader
    parameters
    "to save bytes". Pass values; use pointers for large structs and protobuf messages.
For more, see
references/api-design.md
.
  • context.Context
    作为第一个参数
    func F(ctx context.Context, ...) error
    。即使是测试辅助函数也应遵循。
  • 绝不要将
    context.Context
    存储在结构体中
    。在每个需要它的方法中传递。
  • 不要使用全局可变状态。通过构造函数/函数参数传递依赖(依赖注入)。
  • 接收接口类型,返回具体类型。接口由消费者定义,而非实现者。
  • 签名中指定通道方向
    <-chan T
    表示仅接收,
    chan<- T
    表示仅发送。
  • 参数过多时使用选项结构体(调用时可通过标签字段阅读)。3个以上可选参数或API预计会扩展时,使用选项结构体。不要将
    context.Context
    放入选项结构体。
  • 可变参数选项(
    ...Option
    )仅适用于以下场景
    :大多数调用者无需传参、选项需要参数、第三方需要定义选项。
  • 避免使用
    *string
    *io.Reader
    参数
    来“节省字节”。传递值;大型结构体和protobuf消息使用指针。
如需更多细节,请查看
references/api-design.md

Documentation

文档规范

  • Doc comments are full sentences starting with the symbol's name.
    // Encode writes the JSON encoding of req to w.
  • Document WHY, not WHAT. The code already says what.
  • Document significant sentinel errors and error types the function returns.
  • Document cleanup contracts (
    Close
    ,
    Stop
    , deferred resources).
  • Document concurrency-safety only when non-obvious (read-only methods are assumed safe; mutating ones are assumed unsafe — say so when that doesn't hold).
  • Don't document that
    ctx.Done
    cancels the function
    — that's the contract of
    context.Context
    .
For more, see
references/documentation.md
.
  • 文档注释是完整句子,以符号名称开头
    // Encode writes the JSON encoding of req to w.
    (翻译:// Encode 将req的JSON编码写入w。)
  • 记录原因,而非内容。代码本身已经说明了内容。
  • 记录函数返回的重要哨兵错误和错误类型
  • 记录清理约定(如
    Close
    Stop
    、延迟释放的资源)。
  • 仅当并发安全性不明显时才记录(只读方法默认安全;修改方法默认不安全——不符合此情况时需说明)。
  • 无需记录
    ctx.Done
    会取消函数
    ——这是
    context.Context
    的约定。
如需更多细节,请查看
references/documentation.md

Package layout

包布局

  • internal/
    for packages not part of the public API.
  • Avoid
    util
    /
    common
    /
    helper
    .
    Name by domain.
  • Imports grouped: stdlib / third-party / proto / blank-side-effect. Blank imports only in
    main
    or tests.
  • No
    import .
    ever
    (in Google codebase).
  • Proto imports get a
    pb
    suffix
    :
    foopb "path/to/foo_go_proto"
    .
For more, see
references/package-layout.md
.
  • internal/
    用于不属于公共API的包
  • 避免使用
    util
    /
    common
    /
    helper
    作为包名
    。按领域命名。
  • 导入分组:标准库/第三方/protobuf/空白导入(仅为副作用)。空白导入仅用于
    main
    或测试。
  • 绝不要使用
    import .
    (在Google代码库中)。
  • Protobuf导入添加
    pb
    后缀
    foopb "path/to/foo_go_proto"
如需更多细节,请查看
references/package-layout.md

Decision Matrices

决策矩阵

%v
vs
%w
when wrapping an error

包装错误时选择
%v
还是
%w

SituationChooseWhy
Caller will
errors.Is
/
errors.As
to inspect the chain
%w
Preserves type/sentinel through the chain
Crossing an external boundary (RPC, IPC, storage); caller wants canonical codes
%v
(or
status.Errorf
)
Don't leak internal error types over the wire
Logging or human-display only; no programmatic inspection
%v
%w
adds chain semantics nobody uses
Same error is logged here AND returned upward
%v
Wrapping a logged-then-returned error confuses the chain
Sentinel categorisation first (
ErrParse
-style)
%w
at start:
"%w: detail"
Reader sees the category first
Adding context around a wrapped error (the common case)
%w
at end:
"context: %w"
Chain prints newest→oldest naturally:
outer: middle: inner
Underlying error already carries this infonothing —
return err
Wrapping without adding info is noise
Just propagating without analysisnothing —
return err
Don't wrap for the sake of wrapping
场景选择原因
调用者需要使用
errors.Is
/
errors.As
检查错误链
%w
保留错误链中的类型/哨兵错误
跨外部边界(RPC、IPC、存储);调用者需要标准错误码
%v
(或
status.Errorf
避免内部错误类型泄露到外部
仅用于日志或人类展示;无需程序检查
%v
%w
添加的链式语义无人使用
同一错误在此处记录日志并向上返回
%v
包装已记录的返回错误会混淆错误链
哨兵错误分类优先(如
ErrParse
风格)
%w
放在开头
"%w: 细节"
读者可先看到分类
为包装错误添加上下文(常见场景)
%w
放在末尾
"上下文: %w"
错误链自然按从新到旧打印:
outer: middle: inner
底层错误已包含此信息不处理——
return err
无意义的包装只会增加噪音
仅传播错误不做分析不处理——
return err
不要为了包装而包装

Function arguments: positional vs option struct vs variadic options

函数参数:位置参数vs选项结构体vs可变参数选项

SituationChooseWhy
≤ 3 parameters, all required, all distinct typesPositional argsSmallest mechanism
Many parameters, most callers set most of themOption struct (last param)Self-documenting field names; grows without breaking call sites
Many parameters, most callers set noneVariadic options (
...Option
)
Zero overhead at simple call sites
Options need failure validationVariadic options returning
error
Can't validate in struct construction
Third-party packages must define optionsVariadic options with exported
Option
type
Struct fields can't be extended
Same option set used by multiple functionsOption structReuse + share + write helpers on the struct
context.Context
First positional arg, never in option structConvention
场景选择原因
≤3个参数,均为必填,类型各不相同位置参数实现最简单
参数众多,大多数调用者会设置大部分参数选项结构体(最后一个参数)字段名自文档化;扩展时不会破坏调用方
参数众多,大多数调用者无需传参可变参数选项(
...Option
简单调用场景无额外开销
选项需要失败验证返回
error
的可变参数选项
结构体构造时无法验证
第三方包需要定义选项导出
Option
类型的可变参数选项
结构体字段无法扩展
多个函数使用同一选项集选项结构体可复用、共享并为结构体编写辅助函数
context.Context
第一个位置参数,绝不要放入选项结构体遵循约定

panic
vs
log.Fatal
vs
error
return

panic
vs
log.Fatal
vs 返回
error

SituationChooseWhy
Library detects normal failure
error
return
Caller decides
Library detects an "impossible" invariant violation
error
return or
log.Fatal
Caller can't recover anyway
Bad flag/config in
main
/
init
log.Exit
(no stack)
Stack trace useless; user wants the message
Internal package consistency check that has been verified by tests
log.Fatal
More reliable than
panic
(no defer deadlock risk)
Parser internals that always have a matching
recover
at the API edge
panic
of a private type
Plumbing errors through deep recursion is noise
Package-level var initializer needs a value derived from a fallible call
MustX
(panics)
Init-time only;
init
cannot return errors
HTTP handler crashes mid-requestnever
recover()
to mask it
State is corrupted; let the process crash and restart
场景选择原因
库检测到正常失败返回
error
由调用者决定处理方式
库检测到“不可能”的不变量违反返回
error
log.Fatal
调用者无法恢复
main
/
init
中的错误标志/配置
log.Exit
(无堆栈信息)
堆栈跟踪无用;用户只需错误消息
内部包一致性检查(已通过测试验证)
log.Fatal
panic
更可靠(无延迟函数死锁风险)
解析器内部(API边界有对应的
recover
触发私有类型的
panic
深层递归中传递错误会产生冗余信息
包级变量初始化需要从可能失败的调用中获取值
MustX
(触发panic)
仅在初始化时使用;
init
无法返回错误
HTTP请求处理中崩溃绝不要
recover()
掩盖
状态已损坏;让进程崩溃并重启

t.Error
vs
t.Fatal
vs
t.Errorf
+
continue

t.Error
vs
t.Fatal
vs
t.Errorf
+
continue

SituationChoose
Multiple independent assertions in one
Test*
, all should run
t.Error
/
t.Errorf
for each
Setup failure — rest of test cannot proceed
t.Fatal
/
t.Fatalf
First failure makes subsequent assertions misleading (e.g. encoded ≠ expected, can't decode meaningfully)
t.Fatalf
then continue with
t.Errorf
Table loop without subtests, this case is broken
t.Errorf
+
continue
Inside
t.Run(...)
subtest, this case is broken
t.Fatal
(skips this subtest only)
Worker goroutine inside a test
t.Errorf
only (NEVER
t.Fatal
)
Test helper called from main test goroutine
t.Helper()
+
t.Fatalf
is fine
场景选择
单个
Test*
中有多个独立断言,需全部执行
每个断言使用
t.Error
/
t.Errorf
初始化失败——测试剩余部分无法继续
t.Fatal
/
t.Fatalf
首次失败会导致后续断言产生误导(如编码结果≠预期,解码无意义)
t.Fatalf
后继续使用
t.Errorf
无测试子用例的表循环,当前用例失败
t.Errorf
+
continue
t.Run(...)
子测试中,当前用例失败
t.Fatal
(仅跳过当前子测试)
测试中的工作goroutine仅使用
t.Errorf
绝不要
t.Fatal
测试主goroutine调用的辅助函数
t.Helper()
+
t.Fatalf
是可行的

Variable declaration form

变量声明形式

SituationChooseExample
Initializing with a known non-zero value
:=
i := 42
Need a zero value, ready for use
var x T
var coords Point
,
var s []string
Need a
*T
to a zero value
new(T)
or
&T{}
msg := new(pb.Bar)
Need a
*T
to a value with fields
&T{...}
c := &Config{Port: 8080}
Empty slice for return / accumulation
var s []T
not
s := []T{}
Empty map (must be initialized to write)
make(map[K]V)
or
map[K]V{}
nil map can be read but not written
Pre-sized slice/map (perf-sensitive, size known)
make([]T, 0, n)
/
make(map[K]V, n)
Don't over-pre-allocate
场景选择示例
用已知非零值初始化
:=
i := 42
需要可直接使用的零值
var x T
var coords Point
var s []string
需要指向零值的
*T
new(T)
&T{}
msg := new(pb.Bar)
需要指向带字段值的
*T
&T{...}
c := &Config{Port: 8080}
用于返回/累加的空切片
var s []T
而非
s := []T{}
空map(必须初始化才能写入)
make(map[K]V)
map[K]V{}
nil map可读但不可写
预分配空间的切片/map(对性能敏感,已知大小)
make([]T, 0, n)
/
make(map[K]V, n)
不要过度预分配

Reference Files

参考文件

Load on demand:
  • references/errors.md
    — detailed error structure, wrapping rules, sentinels, RPC boundaries,
    errors.Is/As
    .
  • references/naming.md
    — receivers, initialisms, repetition, test doubles, util-package antipattern, shadowing.
  • references/api-design.md
    — option struct vs variadic options, channel direction, DI, interfaces, generics.
  • references/tests.md
    — Test funcs vs helpers, table-driven, subtests, goroutines, acceptance testing,
    cmp
    .
  • references/panics.md
    — when allowed (invariants, parsers with recover,
    init
    ), when forbidden,
    log.Fatal
    vs
    log.Exit
    .
  • references/documentation.md
    — godoc conventions, what to document, what to skip, contexts, errors, cleanup.
  • references/package-layout.md
    — package size, file structure, imports,
    internal/
    , side-effect imports.
  • references/strings-and-vars.md
    — concatenation choices, zero values, size hints,
    new
    vs
    &T{}
    , shadowing.
按需查看:
  • references/errors.md
    — 详细的错误结构、包装规则、哨兵错误、RPC边界、
    errors.Is/As
  • references/naming.md
    — 接收器、首字母缩写词、重复命名、测试替身、工具包反模式、变量遮蔽。
  • references/api-design.md
    — 选项结构体vs可变参数选项、通道方向、依赖注入、接口、泛型。
  • references/tests.md
    — 测试函数vs辅助函数、表驱动测试、子测试、goroutine、验收测试、
    cmp
    包。
  • references/panics.md
    — 允许使用的场景(不变量、带recover的解析器、
    init
    )、禁止使用的场景、
    log.Fatal
    vs
    log.Exit
  • references/documentation.md
    — godoc约定、需记录的内容、可忽略的内容、上下文、错误、清理。
  • references/package-layout.md
    — 包大小、文件结构、导入、
    internal/
    、副作用导入。
  • references/strings-and-vars.md
    — 拼接选择、零值、大小提示、
    new
    vs
    &T{}
    、变量遮蔽。

Authoritative Sources

权威来源

When in doubt, especially for unusual situations, WebFetch the source section before writing the code. The Google Go Style Guide is the normative authority — this skill is a digest, not a replacement.
For Go fundamentals not covered here, read Effective Go.
如有疑问,尤其是遇到特殊情况时,编写代码前请查阅官方指南。Google Go 风格指南是权威依据——本技能摘要是精简版,不能替代官方指南。
如需了解本文未涵盖的Go基础知识,请阅读Effective Go。",