Files
OpenFlare/.agents/skills/go-functions/references/SIGNATURES.md
T
2026-08-04 11:40:32 +08:00

169 lines
3.7 KiB
Markdown

# 函数签名
格式化 Go 函数签名、避免裸参数以及保持调用点可读性的详细规则。
---
## 单行 vs 多行
当签名能轻松放在一行时保持单行。当必须换行时,将**所有参数放在各自的行上**并加尾随逗号:
**不好**——部分换行使对齐变得脆弱:
```go
func (r *SomeType) SomeLongFunctionName(foo1, foo2, foo3 string,
foo4, foo5, foo6 int) {
foo7 := bar(foo1)
}
```
**好**——完全换行,尾随逗号:
```go
func (r *SomeType) SomeLongFunctionName(
foo1, foo2, foo3 string,
foo4, foo5, foo6 int,
) {
foo7 := bar(foo1)
}
```
### 返回值
当返回值也需要换行时,遵循相同的模式:
```go
func (r *SomeType) LongName(
foo1, foo2, foo3 string,
foo4, foo5, foo6 int,
) (
*Result,
error,
) {
// ...
}
```
对于更简单的情况,命名返回值可以与参数右括号在同一行:
```go
func (r *SomeType) LongName(
foo1, foo2, foo3 string,
) (result *Result, err error) {
// ...
}
```
---
## 缩短调用点
提取局部变量,而不是将函数调用拆分到多行:
```go
// 不好:过长的内联调用
result := foo.Call(
somePackage.ComplexFunction(arg1, arg2),
anotherPackage.Transform(data),
defaultOptions,
)
// 好:提取局部变量以提高清晰度
transformed := anotherPackage.Transform(data)
computed := somePackage.ComplexFunction(arg1, arg2)
result := foo.Call(computed, transformed, defaultOptions)
```
这提高了可读性,并使中间值可用于调试。
---
## 避免裸参数
函数调用中的裸参数会降低可读性。为含义不明确的参数添加 C 风格注释:
```go
// 不好:这些布尔值是什么意思?
printInfo("foo", true, true)
// 好:内联注释说明了意图
printInfo("foo", true /* isLocal */, true /* done */)
```
更好的做法是用自定义类型替换裸 `bool` 参数:
```go
type Region int
const (
UnknownRegion Region = iota
Local
)
type Status int
const (
Pending Status = iota
Done
)
func printInfo(name string, region Region, status Status)
```
### 何时使用每种方法
| 方法 | 时机 |
|------|------|
| C 风格注释 | 快速修复;调用点少;无法修改的第三方 API |
| 自定义类型 | 多个调用点;公开 API;多个 bool/int 参数 |
| 函数选项 | 3 个以上可选参数;参见 [go-functional-options](../../go-functional-options/SKILL.md) |
---
## 分组相关参数
当函数接受多个相同类型的参数时,将它们分组:
```go
// 可接受:将同类型参数分组
func Copy(dst, src string) error
// 可接受:尽管类型相同,但含义不同时分开声明
func Move(source string, destination string) error
```
当参数名称能清楚表明角色时使用分组;当不能清楚表明时使用分开声明。
---
## 方法接收者的位置
接收者放在函数名之前,格式类似于参数:
```go
// 短接收者——放在同一行
func (s *Server) Start(ctx context.Context) error { ... }
// 长接收者类型——如果整行过长则考虑换行
func (h *ComplicatedHandler) ServeHTTP(
w http.ResponseWriter,
r *http.Request,
) { ... }
```
参见 [go-naming](../../go-naming/SKILL.md) 了解接收者命名约定(简短的一到两个字母缩写)。
---
## 快速参考
| 主题 | 规则 |
|------|------|
| 单行 | 能放下时保持一行 |
| 多行 | 所有参数各占一行,尾随逗号 |
| 返回值换行 | 与参数相同的模式 |
| 调用点 | 提取局部变量而不是拆分调用 |
| 裸 bool | 添加 `/* name */` 注释或使用自定义类型 |
| 分组参数 | 当名称能清楚表明角色时将同类型分组 |
| 接收者 | 在函数名之前;简短缩写 |