mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-28 05:46:36 +08:00
93 lines
2.6 KiB
Markdown
93 lines
2.6 KiB
Markdown
# Must 函数
|
||
|
||
> **来源**:Uber 风格指南, Go 标准库约定
|
||
|
||
`Must` 函数包装一个可能失败的函数,在出错时 panic。**仅**在程序初始化阶段使用,因为失败意味着程序无法运行。
|
||
|
||
## 标准库示例
|
||
|
||
```go
|
||
// regexp.MustCompile 在模式无效时 panic
|
||
var validID = regexp.MustCompile(`^[a-z][a-z0-9-]{0,62}$`)
|
||
|
||
// template.Must 在模板解析失败时 panic
|
||
var tmpl = template.Must(template.ParseFiles("index.html"))
|
||
```
|
||
|
||
这些是安全的,因为它们在包初始化时运行——如果失败,程序无法正确运行。
|
||
|
||
## 何时使用 Must
|
||
|
||
```
|
||
这是在程序初始化期间调用的吗(包级 var、init、main 设置)?
|
||
├─ 是 → 失败是否不可恢复(配置、正则、模板)?
|
||
│ ├─ 是 → 使用 Must 是合适的
|
||
│ └─ 否 → 改为返回 error
|
||
└─ 否 → 绝不使用 Must——返回 error
|
||
```
|
||
|
||
### 适当的使用场景
|
||
|
||
- **包级 `var`**:编译正则表达式、解析模板、加载必需的配置
|
||
- **`init()` 或 `main()` 早期**:设置程序运行所必需的资源
|
||
- **测试辅助函数**:测试中优先使用 `t.Fatal`,但 Must 在测试 fixture 中是可以接受的
|
||
|
||
### 绝不使用 Must 的场景
|
||
|
||
- 运行时请求处理
|
||
- 用户提供的输入
|
||
- 可能合理失败的网络或文件操作
|
||
- 程序启动后调用的任何代码
|
||
|
||
## 编写 Must 函数
|
||
|
||
遵循命名约定 `MustX`,其中 `X` 是可能失败的函数名:
|
||
|
||
```go
|
||
func MustParseConfig(path string) *Config {
|
||
cfg, err := ParseConfig(path)
|
||
if err != nil {
|
||
panic(fmt.Sprintf("parsing config %s: %v", path, err))
|
||
}
|
||
return cfg
|
||
}
|
||
```
|
||
|
||
### 指南
|
||
|
||
- **命名**:`Must` 前缀 + 可能失败的函数名(例如 `MustParse`、`MustNew`、`MustCompile`)
|
||
- **Panic 消息**:包含输入和错误信息以便调试
|
||
- **文档**:始终记录函数在出错时会 panic
|
||
|
||
```go
|
||
// MustParseConfig 解析路径处的配置文件。
|
||
// 如果文件无法读取或包含无效配置,则会 panic。
|
||
func MustParseConfig(path string) *Config { ... }
|
||
```
|
||
|
||
### 泛型 Must 辅助函数
|
||
|
||
对于一次性使用,泛型 Must 辅助函数可以避免样板代码:
|
||
|
||
```go
|
||
func Must[T any](v T, err error) T {
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
return v
|
||
}
|
||
|
||
// 在包级别使用
|
||
var cfg = Must(ParseConfig("app.yaml"))
|
||
```
|
||
|
||
## 与 Panic/Recover 的关系
|
||
|
||
Must 函数是对 `panic` 的受控使用。它们应该:
|
||
|
||
- 仅在初始化期间运行(因此不需要 recover)
|
||
- 产生清晰、可操作的 panic 消息
|
||
- 绝不在可以返回 error 的场景中使用
|
||
|
||
完整的 panic/recover 模式请参见 [PANIC-RECOVER.md](PANIC-RECOVER.md)。
|