--- name: go-code-writer description: 根据用户要求编写Go代码,只读访问现有项目文件,安全生成新文件 license: MIT compatibility: opencode metadata: audience: Go developers workflow: code generation --- ## 功能概述 本技能帮助用户编写Go代码文件。技能只能查看项目中的现有文件(只读),不能修改任何现有文件。根据用户要求生成新的Go代码文件,并安全地保存到指定目录。 ## 核心限制 1. **只读访问**:只能读取现有项目文件来理解代码结构和模式,不能修改、删除或重命名任何现有文件 2. **安全生成**:所有新文件都生成到用户指定的目标目录 3. **备份保护**:如果目标文件已存在,自动创建备份文件(带序号)后再覆盖 4. **参考优先**:优先按照用户提供的参考代码模式编写新代码 ## 使用前准备 在使用本技能前,请确保以下信息已明确: 1. **目标目录**:新生成的Go代码文件保存的具体目录路径 2. **参考代码**:用户希望参考的现有代码文件或模式 3. **文件命名**:新Go文件的名称(包括`.go`扩展名) 4. **功能描述**:新代码需要实现的具体功能 **重要**:如果用户未提供明确的目标目录,必须先询问确认后才能开始编写。 ## 工作流程 ### 1. 收集需求 - 询问用户新代码的功能需求、目标文件路径和参考代码 - 确认目标目录是否存在,如果不存在询问是否创建 - 如果目标目录未指定,必须要求用户明确指定 ### 2. 分析现有代码 - 使用只读工具(`glob`, `grep`, `read`)查看项目中的相关文件 - 分析参考代码的结构、命名约定和设计模式 - 理解项目的包结构、导入规范和编码风格 - **注意**:此阶段只读取文件,不进行任何修改 ### 3. 检查目标文件 - 检查目标路径是否已存在同名文件 - 如果文件已存在,执行备份流程: - 生成备份文件名:`{原文件名}.backup.{序号}` - 序号从1开始递增,避免覆盖现有备份文件 - 例如:`main.go.backup.1`, `main.go.backup.2` - 向用户报告备份计划 ### 4. 编写新代码 - 根据用户需求和参考代码模式编写Go代码 - 遵循项目的编码规范和最佳实践 - 确保导入路径正确,包结构合理 - 生成完整、可编译的Go代码文件 ### 5. 保存文件 - 如果目标文件存在,先创建备份文件 - 将新代码写入目标文件路径 - 验证文件是否成功写入 - 向用户提供文件路径和备份信息 ## 备份策略 ### 备份文件命名规则 ``` {原文件名}.backup.{序号} ``` ### 备份流程 1. 检查目标文件是否存在 2. 如果不存在,直接写入新文件 3. 如果存在: - 查找最大备份序号:扫描 `{原文件名}.backup.*` - 新序号 = 最大序号 + 1 - 复制原文件到备份文件 - 写入新文件覆盖原文件 ### 示例 ```bash # 原文件: /path/to/main.go # 备份文件: /path/to/main.go.backup.1 # 如果已存在: /path/to/main.go.backup.2 ``` ## 输出示例 ### 用户请求 "在 `svc-code/internal/handlers` 目录下创建一个新的HTTP处理器 `user_handler.go`,参考现有的 `session_handler.go` 模式" ### 技能响应 ``` 已分析项目结构,找到参考文件 `svc-code/internal/handlers/session_handler.go`。 目标目录 `svc-code/internal/handlers` 存在。 目标文件 `user_handler.go` 不存在,无需备份。 正在编写新的HTTP处理器... 代码已生成并保存到:svc-code/internal/handlers/user_handler.go ``` ### 如果文件已存在 ``` 目标文件 `svc-code/internal/handlers/user_handler.go` 已存在。 创建备份文件:svc-code/internal/handlers/user_handler.go.backup.1 新文件已覆盖原文件,原文件已备份。 ``` ## 注意事项 1. **安全第一**:绝不修改现有文件,只生成新文件或覆盖前备份 2. **目录确认**:必须确认目标目录后才能开始编写 3. **代码质量**:生成的代码应符合Go最佳实践和项目规范 4. **备份保护**:确保备份文件不会被意外覆盖 5. **用户确认**:在覆盖现有文件前,告知用户备份计划 ## 错误处理 - 如果目标目录不存在,询问用户是否创建 - 如果无法理解用户需求,请求更详细的描述 - 如果参考代码不存在,询问替代参考或手动编写 - 如果写入文件失败,报告具体错误并提供解决方案 - 如果备份创建失败,中止操作并报告错误 ## 相关工具 - `glob`:查找文件模式,理解项目结构 - `grep`:搜索代码内容,分析模式和用法 - `read`:读取现有文件内容,理解代码逻辑 - `write`:安全写入新文件(自动处理备份) - `question`:收集用户需求和确认信息 ## 编码规范参考 遵循项目中的 `AGENTS.md` 文件中定义的Go编码规范: - 导入分组:标准库、第三方库、内部包 - 命名约定:PascalCase导出,camelCase非导出 - 错误处理:始终检查错误返回值 - 注释规范:中文或英文,文档化导出元素 - 包结构:合理的包组织和职责分离 ### 文件组织规范 1. **一个功能一个文件**:每个`.go`文件专注于单一主要功能 2. **单一公开方法**:每个文件只导出一个主要的公开函数/方法 3. **私有方法辅助**:辅助功能使用包内私有方法(小写开头) 4. **公用功能拆分**:跨文件复用的功能拆分为独立文件 5. **示例文件**:复杂功能提供示例文件展示用法 ### 启动验证函数设计 1. **启动阶段直接终止**:应用启动阶段的配置验证失败时直接调用`log.Fatalf()`终止程序 2. **不返回错误**:避免在`main()`函数中添加错误判断逻辑,简化主程序流程 3. **命名体现行为**:使用`OrExit`后缀明确标识"验证失败即退出"的函数 4. **警告与终止区分**: - 非关键配置缺失:记录警告日志,允许继续执行 - 关键配置错误:直接终止程序,防止后续运行时错误 5. **示例**: ```go // 验证数据库配置,失败即退出 func ValidateDbsConfigKeysOrExit() { // 空配置仅警告 if config == nil { log.Println("警告:数据库配置为空,相关功能受限") return } // 关键错误直接终止 if !isValid(config) { log.Fatalf("数据库配置错误: %v", config) } } ``` ### 完整示例 以下是一个完整的可编译示例,展示了启动验证函数的典型实现模式: ```go package service import ( "log" ) // ExampleValidateConfigOrExit 示例:启动配置验证函数 // // 设计原则: // 1. 使用 `OrExit` 后缀明确标识"验证失败即退出"的行为 // 2. 非关键配置缺失仅记录警告,允许继续执行 // 3. 关键配置错误直接终止程序,防止后续运行时错误 // 4. 不返回错误,简化 main() 函数的调用逻辑 // // 在 main() 中的调用方式: // // func main() { // service.ExampleValidateConfigOrExit() // // 其他初始化... // } func ExampleValidateConfigOrExit() { // 示例:检查必需的环境变量 checkRequiredEnvVarsOrExit() // 示例:验证配置文件 validateConfigFileOrExit() // 示例:检查外部依赖(如数据库) checkExternalDependenciesOrExit() log.Println("所有启动配置验证通过") } // checkRequiredEnvVarsOrExit 检查必需的环境变量 func checkRequiredEnvVarsOrExit() { // 关键环境变量:缺失时直接终止 requiredVars := []string{"APP_ENV", "DATABASE_URL"} for _, envVar := range requiredVars { if getEnv(envVar) == "" { log.Fatalf("必需环境变量 %s 未设置", envVar) } } // 可选环境变量:缺失时仅警告 optionalVars := []string{"LOG_LEVEL", "CACHE_TTL"} for _, envVar := range optionalVars { if getEnv(envVar) == "" { log.Printf("警告:可选环境变量 %s 未设置,使用默认值", envVar) } } } // validateConfigFileOrExit 验证配置文件 func validateConfigFileOrExit() { config := loadConfig() if config == nil { log.Println("警告:配置文件为空,使用默认配置") return } // 关键配置验证 if config.Port <= 0 { log.Fatalf("配置错误:服务端口必须大于0,当前值:%d", config.Port) } if config.Timeout <= 0 { log.Printf("警告:超时配置无效,使用默认值") config.Timeout = 30 } } // checkExternalDependenciesOrExit 检查外部依赖 func checkExternalDependenciesOrExit() { // 数据库连接检查 if err := checkDatabaseConnection(); err != nil { log.Fatalf("数据库连接失败: %v", err) } // 缓存服务检查(可选) if err := checkCacheService(); err != nil { log.Printf("警告:缓存服务不可用,相关功能受限: %v", err) // 允许继续执行,但记录警告 } } // getEnv 获取环境变量(示例辅助函数) func getEnv(key string) string { // 实际实现中应使用 os.Getenv() return "" } // Config 配置结构体(示例) type Config struct { Port int Timeout int } // loadConfig 加载配置(示例辅助函数) func loadConfig() *Config { // 实际实现中应从文件或环境变量加载配置 return nil } // checkDatabaseConnection 检查数据库连接(示例辅助函数) func checkDatabaseConnection() error { // 实际实现中应测试数据库连接 return nil } // checkCacheService 检查缓存服务(示例辅助函数) func checkCacheService() error { // 实际实现中应测试缓存服务连接 return nil } ``` ### 函数命名约定 1. **`OrExit`后缀**:用于启动验证函数,表示"验证失败即退出程序" - 示例:`ValidateConfigOrExit()`, `CheckDatabaseOrExit()` 2. **`Must`前缀**:用于初始化函数,表示"失败即panic",慎用 - 示例:`MustLoadConfig()`, `MustConnectDB()` 3. **明确职责**:函数名应清晰反映其行为后果,避免隐藏的副作用