No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SKILL.md 9.9KB


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
    • 复制原文件到备份文件
    • 写入新文件覆盖原文件

示例

# 原文件: /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) } }

完整示例

以下是一个完整的可编译示例,展示了启动验证函数的典型实现模式:

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. 明确职责:函数名应清晰反映其行为后果,避免隐藏的副作用