wavelet init

This commit is contained in:
ryan
2026-06-18 15:24:48 +08:00
parent d6a7011885
commit 99738bbc17
714 changed files with 139987 additions and 0 deletions
@@ -0,0 +1,95 @@
# 格式化参考
## gofmt 是必须的
所有 Go 源文件 **必须** 符合 `gofmt` 的输出。没有例外。
```bash
# 格式化一个文件
gofmt -w myfile.go
# 格式化目录下所有文件
gofmt -w .
```
其他格式化工具:
| 工具 | 用途 |
|------|------|
| `gofmt` | 标准格式化工具(必须使用) |
| `goimports` | gofmt + import 管理 |
| `gofumpt` | gofmt 的更严格超集 |
---
## 括号
Go 比 C 和 Java 需要更少的括号。控制结构(`if`、`for`、`switch`)的语法中不需要括号。运算符优先级层次更短更清晰,所以 `x<<8 + y<<16` 的含义就如空格所暗示的那样 — 不像其他语言。
---
## MixedCaps(驼峰命名)
Go 使用 `MixedCaps` 或 `mixedCaps`,从不使用下划线:
```go
// 好
MaxLength // 导出常量
maxLength // 非导出常量
userID // 变量
// 不好
MAX_LENGTH // 不使用 snake_case
max_length // 不使用下划线
```
例外:
- 测试函数名可以使用下划线:`TestFoo_Bar`
- 与 OS/cgo 交互的生成代码
---
## 行长度
Go 中 **没有严格的行长度限制**,但避免过长的行。Uber 建议软限制为 99 个字符。
指导原则:
- 如果一行感觉太长,**重构** 而非仅仅换行
- 不要在缩进变化之前换行(函数声明、条件语句)
- 不要将长字符串(URL)拆分成多行
- 换行时,将所有参数放在各自的行上
- 如果已经尽可能短了,就让它保持长行
**按语义换行,而非按长度**:
不要仅仅为了保持短行而添加换行符,当长行更具可读性时(例如,重复性的行)。因为你所写的内容而换行,而非因为行长度。
长行通常与长名称相关。如果你发现行太长,考虑名称是否可以更短。去掉长名称往往比换行更有帮助。
这个建议同样适用于函数长度 — 没有"函数永远不超过 N 行"的规则,但确实存在太长的情况。解决方案是改变函数的边界在哪里,而非计算行数。
```go
// 不好:随意的行中断
func (s *Store) GetUser(ctx context.Context,
id string) (*User, error) {
// 好:所有参数各占一行
func (s *Store) GetUser(
ctx context.Context,
id string,
) (*User, error) {
```
---
## 局部一致性
当风格指南未做规定时,与附近代码保持一致:
**有效的** 局部选择:
- 错误格式化使用 `%s` 还是 `%v`
- 带缓冲 channel 还是 mutex
**无效的** 局部覆盖:
- 行长度限制
- 基于断言的测试库
@@ -0,0 +1,89 @@
# 风格原则参考
## 1. 清晰性
代码的目的和原理必须对读者清晰。
- **做什么**:使用描述性名称、有帮助的注释和高效的组织
- **为什么**:添加解释原理的注释,特别是对于微妙的细节
- 从读者的角度审视清晰性,而非作者的角度
- 代码应该易于阅读,而非易于编写
```go
// 好:目的清晰
func (c *Config) WriteTo(w io.Writer) (int64, error)
// 不好:不清晰,重复了接收者
func (c *Config) WriteConfigTo(w io.Writer) (int64, error)
```
## 2. 简洁性
代码应该以最简单的方式实现目标。
简洁的代码:
- 从头到尾容易阅读
- 不假定读者有先验知识
- 没有不必要的抽象层次
- 注释解释"为什么",而非"做什么"
- 可能与"巧妙"的代码互斥
### 最少机制
当有几种方式表达同一个想法时,优先使用最标准的工具:
1. 核心语言结构(channel、slice、map、loop、struct)
2. 标准库(HTTP 客户端、模板引擎)
3. 第三方库 — 仅在 (1) 和 (2) 不够用时使用
## 3. 精炼性
代码应该有高信噪比。
- 避免重复代码
- 避免多余的语法
- 避免不必要的抽象
- 使用表驱动测试提取公共代码
```go
// 好:常见惯用法,信号量高
if err := doSomething(); err != nil {
return err
}
// 好:为异常情况增强信号
if err := doSomething(); err == nil { // 如果没有错误
// ...
}
```
## 4. 可维护性
代码被修改的次数远多于被编写的次数。
可维护的代码:
- 对于未来的程序员来说容易正确修改
- API 能够优雅地扩展
- 使用可预测的名称(相同概念 = 相同名称)
- 最小化依赖
- 具有全面的测试和清晰的诊断信息
```go
// 不好:关键细节被隐藏
if user, err = db.UserByID(userID); err != nil { // = vs :=
// 好:显式且清晰
u, err := db.UserByID(userID)
if err != nil {
return fmt.Errorf("invalid origin user: %s", err)
}
user = u
```
## 5. 一致性
代码的外观和行为应该与代码库中的类似代码一致。
- 包级别的一致性最重要
- 当出现平局时,优先保持一致性
- 绝不为了局部一致性而覆盖有文档记录的风格原则