sure 通过为现有的 Go 代码添加断言和崩溃处理功能来增强代码。它断言条件并在发生问题时崩溃,帮助在不手动添加重复检查的情况下改善代码的问题管理。
sure 是一个代码生成包,将现有的 Go 代码转换成带断言增强的版本。无需在整个代码库中添加重复的检查,sure 生成带有内置断言逻辑的包装代码,使问题检测和处理变得无缝。
该包提供三种不同的生成器,每种服务于不同的代码转换需求:
- sure_cls_gen: 创建启用断言的类包装
- sure_pkg_gen: 生成启用断言的包包装
- cls_stub_gen: 生成单例包装函数
🎯 三种断言模式
- Must: 遇到问题时崩溃(基于 panic)
- Soft: 记录警告并继续执行
- Omit: 静默模式 - 忽略问题
⚡ 自动代码生成
- 无需修改即可转换现有代码
- 生成类型安全的断言包装
- 保留函数签名和文档
🔧 灵活集成
- 适用于现有 Go 项目
- 生成的代码无运行时依赖
- 兼容标准 Go 包
📦 多种生成策略
- 基于类:包装对象方法
- 基于包:包装包函数
- 基于单例:将实例方法包装为包级函数
标准的 Go 问题处理需要重复检查:
result, err := SomeOperation()
if err != nil {
log.Printf("operation failed: %v", err)
return err
}
data, err := AnotherOperation(result)
if err != nil {
log.Printf("another operation failed: %v", err)
return err
}在大型代码库中,这变得冗长和重复。
使用 sure,生成启用断言的包装:
// 源函数
func ReadConfig(path string) (*Config, error)
// 生成的包装(Must 模式)
func (s *SureConfig) ReadConfig(path string) *Config
// 使用 - 遇到问题时崩溃,无需手动检查
config := sureConfig.ReadConfig("config.json")生成的代码处理断言,使业务逻辑更简洁。
目的:从现有对象创建包装类,在每个方法中嵌入断言逻辑。
使用场景:当处理具有多个返回问题的方法的对象时,生成处理所有断言的包装类。
工作原理:
- 获取现有的结构体/接口
- 分析所有返回问题的方法
- 生成带有断言方法的包装类
- 每个包装方法移除问题返回,添加断言逻辑
示例:
源数据库客户端:
type DB struct { }
func (db *DB) Connect(dsn string) error
func (db *DB) Query(sql string) (*Result, error)
func (db *DB) Close() error生成的断言包装:
type SureDB struct {
db *DB
}
func (s *SureDB) Connect(dsn string) // 遇到问题时 panic
func (s *SureDB) Query(sql string) *Result // 遇到问题时 panic
func (s *SureDB) Close() // 遇到问题时 panic优势:
- 无需手动编写断言代码
- 类型安全的包装
- 更简洁的业务逻辑代码
- 跨方法的一致问题处理
代码生成:
目的:从现有包中提取函数,生成新的启用断言的包版本。
使用场景:当一个包有多个返回问题的函数时,生成带有断言版本的配套包。
工作原理:
- 扫描目标包函数
- 识别返回问题的函数
- 生成带有断言包装的新包
- 维护函数签名(减去问题返回)
示例:
源包函数:
package config
func Load(path string) (*Config, error)
func Parse(data []byte) (*Config, error)
func Validate(cfg *Config) error生成的断言包:
package sureconfig
func Load(path string) *Config // 遇到问题时 panic
func Parse(data []byte) *Config // 遇到问题时 panic
func Validate(cfg *Config) // 遇到问题时 panic优势:
- 整个包获得断言版本
- 无需修改原始包
- 在适当时使用断言包
- 与原始包混合使用
代码生成:
目的:生成包装单例实例方法的包作用域函数。
使用场景:在使用单例模式时,提供包作用域函数作为便捷包装。
工作原理:
- 获取带有方法的结构体
- 假设存在单例实例
- 生成包作用域函数
- 每个函数委托给单例实例
示例:
带有方法的单例对象:
type Logger struct { }
func (l *Logger) Debug(msg string)
func (l *Logger) Info(msg string)
func (l *Logger) Warn(msg string)
func (l *Logger) Error(msg string)
var defaultLogger = &Logger{}生成的包级函数:
func Debug(msg string) {
defaultLogger.Debug(msg)
}
func Info(msg string) {
defaultLogger.Info(msg)
}
func Warn(msg string) {
defaultLogger.Warn(msg)
}
func Error(msg string) {
defaultLogger.Error(msg)
}优势:
- 简单的 API - 无需实例
- 包作用域便捷函数
- 与标准 Go 包设计一致
- 保持单例模式的优势
代码生成:
go get github.com/yylego/sureimport "github.com/yylego/sure/sure_cls_gen"
// 使用 Must 模式生成断言包装
options := sure_cls_gen.NewOptions().
WithPackageName("mypackage").
WithClassName("SureClient")
code := sure_cls_gen.GenerateClassMethods(
originalObject,
options,
sure.MUST, // 遇到问题时崩溃
)import "github.com/yylego/sure/sure_pkg_gen"
// 生成断言包
config := sure_pkg_gen.NewSurePackageConfig(
projectPath,
sure.MUST,
"original/package/path",
)
functions := sure_pkg_gen.GenerateSureFunctions(t, config, outputPath)import "github.com/yylego/sure/cls_stub_gen"
// 生成包级包装
stubConfig := &cls_stub_gen.StubGenConfig{
SourceRootPath: projectPath,
TargetPackageName: "api",
OutputPath: outputPath,
}
code := cls_stub_gen.GenerateStubMethods(
stubConfig,
cls_stub_gen.NewStubParam(singletonInstance, "instance"),
)带有重复检查的源代码:
conn, err := db.Connect(dsn)
if err != nil { return err }
result, err := conn.Query(sql)
if err != nil { return err }
err = conn.Close()
if err != nil { return err }使用 sure_cls_gen:
sureDB := NewSureDB(db)
sureDB.Connect(dsn)
result := sureDB.Query(sql)
sureDB.Close()源代码:
cfg, err := config.Load("app.json")
if err != nil { return err }
err = config.Validate(cfg)
if err != nil { return err }使用 sure_pkg_gen:
cfg := sureconfig.Load("app.json")
sureconfig.Validate(cfg)源单例:
client.SetEndpoint(url)
response, err := client.Get("/api/data")
if err != nil { return err }使用 cls_stub_gen:
SetEndpoint(url)
response := Get("/api/data")在以下情况使用 sure.MUST:
- 问题无法恢复
- 应用程序无法继续处理问题
- 初始化和设置期间
- 在测试代码中
在以下情况使用 sure.SOFT:
- 问题应该记录但不崩溃
- 可接受优雅降级
- 在生产环境中有回退逻辑
- 在不中断的情况下监控问题
在以下情况使用 sure.OMIT:
- 问题是预期且可接受的
- 希望静默失败
- 性能关键路径
- 当问题在其他地方处理时
sure 旨在补充 done 包:
- done: 提供内联断言函数(
done.Done(),done.VAE()) - sure: 生成带有内置断言的包装代码
编写新代码时使用 done,包装现有代码时使用 sure。
done 示例:
config := done.VAE(LoadConfig()).Nice()sure 示例:
config := sureConfig.Load() // 生成的包装两种方法都减少样板代码,根据上下文选择。
演示每种生成方式的综合示例:
- sure_cls_gen 示例 - 类包装生成
- sure_pkg_gen 示例 - 包包装生成
- cls_stub_gen 示例 - 单例包装生成
每个示例包括:
- 源代码设置
- 生成配置
- 生成的代码输出
- 使用演示
MIT 许可证。详见 LICENSE。
非常欢迎贡献代码!报告 BUG、建议功能、贡献代码:
- 🐛 发现问题? 在 GitHub 上提交问题并附上重现步骤
- 💡 功能建议? 创建 issue 讨论您的想法
- 📖 文档疑惑? 报告问题,帮助我们改进文档
- 🚀 需要功能? 分享使用场景,帮助理解需求
- ⚡ 性能瓶颈? 报告慢操作,帮助我们优化性能
- 🔧 配置困扰? 询问复杂设置的相关问题
- 📢 关注进展? 关注仓库以获取新版本和功能
- 🌟 成功案例? 分享这个包如何改善工作流程
- 💬 反馈意见? 欢迎提出建议和意见
新代码贡献,请遵循此流程:
- Fork:在 GitHub 上 Fork 仓库(使用网页界面)
- 克隆:克隆 Fork 的项目(
git clone https://github.com/yourname/repo-name.git) - 导航:进入克隆的项目(
cd repo-name) - 分支:创建功能分支(
git checkout -b feature/xxx) - 编码:实现您的更改并编写全面的测试
- 测试:(Golang 项目)确保测试通过(
go test ./...)并遵循 Go 代码风格约定 - 文档:为面向用户的更改更新文档,并使用有意义的提交消息
- 暂存:暂存更改(
git add .) - 提交:提交更改(
git commit -m "Add feature xxx")确保向后兼容的代码 - 推送:推送到分支(
git push origin feature/xxx) - PR:在 GitHub 上打开 Merge Request(在 GitHub 网页上)并提供详细描述
请确保测试通过并包含相关的文档更新。
非常欢迎通过提交 Merge Request 和报告问题来为此项目做出贡献。
项目支持:
- ⭐ 给予星标如果项目对您有帮助
- 🤝 分享项目给团队成员和(golang)编程朋友
- 📝 撰写博客关于开发工具和工作流程 - 我们提供写作支持
- 🌟 加入生态 - 致力于支持开源和(golang)开发场景
祝你用这个包编程愉快! 🎉🎉🎉