go-options-gen
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesego-options-gen
go-options-gen
You are an expert in using the library (https://github.com/kazhuravlev/options-gen) to create robust, type-safe functional options for Go components. You prioritize unexported option fields to maintain encapsulation while providing a clean, exported API for configuration.
options-genCore Mandates
核心要求
- File Naming:
- Single Option Set: Struct definition MUST be in , and generated code MUST be in
options.go.options_generated.go - Multiple Option Sets: For a component named , the struct (e.g.,
MyService) MUST be inMyServiceOptions, and generated code MUST be inmyservice_options.go.myservice_options_generated.go
- Single Option Set: Struct definition MUST be in
- Encapsulation:
- Options fields within the struct SHOULD be unexported (start with a lowercase letter) to prevent direct modification from outside the package.
- Tooling:
- Always run the tool using .
go tool options-gen - Install and track the tool in using:
go.modbashgo get -tool github.com/kazhuravlev/options-gen/cmd/options-gen@latest
- Always run the tool using
- Validation:
- Always include validation tags (using syntax) for configuration fields.
go-playground/validator - ALWAYS call the generated method within the component's constructor.
Validate()
- Always include validation tags (using
- Component Integration:
- Store the resulting options struct in an unexported field named within your component struct.
opts
- Store the resulting options struct in an unexported field named
- 文件命名:
- 单个选项集:结构体定义必须放在中,生成的代码必须放在
options.go中。options_generated.go - 多个选项集:对于名为的组件,结构体(如
MyService)必须放在MyServiceOptions中,生成的代码必须放在myservice_options.go中。myservice_options_generated.go
- 单个选项集:结构体定义必须放在
- 封装性:
- 结构体中的选项字段应设为未导出(以小写字母开头),防止从包外直接修改。
- 工具使用:
- 始终使用运行该工具。
go tool options-gen - 使用以下命令在中安装并追踪该工具:
go.modbashgo get -tool github.com/kazhuravlev/options-gen/cmd/options-gen@latest
- 始终使用
- 验证:
- 始终为配置字段包含验证标签(使用语法)。
go-playground/validator - 必须在组件的构造函数中调用生成的方法。
Validate()
- 始终为配置字段包含验证标签(使用
- 组件集成:
- 将最终的选项结构体存储在组件结构体中名为的未导出字段中。
opts
- 将最终的选项结构体存储在组件结构体中名为
Developer Workflow
开发者工作流
-
Installation: Ensure the tool is tracked in your project:bash
go get -tool github.com/kazhuravlev/options-gen/cmd/options-gen@latest -
Define Options (): Define your options struct with unexported fields. Use the
options.godirective to specify the output filename and the target struct.//go:generategopackage mypackage import "time" //go:generate go tool options-gen -from-struct=Options -out-filename=options_generated.go type Options struct { timeout time.Duration `option:"mandatory" validate:"required"` maxRetries int `default:"3" validate:"min=1"` endpoints []string `option:"variadic=true"` } -
Generate: Run the generator:bash
go generate ./options.go -
Integration: Use the generated types in your component's constructor and store them in anfield.
optsgotype Component struct { opts Options } func New(setters ...OptionOptionsSetter) (*Component, error) { opts := NewOptions(setters...) if err := opts.Validate(); err != nil { return nil, fmt.Errorf("invalid options: %w", err) } return &Component{opts: opts}, nil }
-
安装: 确保工具已在项目中被追踪:bash
go get -tool github.com/kazhuravlev/options-gen/cmd/options-gen@latest -
定义选项(): 定义带有未导出字段的选项结构体。使用
options.go指令指定输出文件名和目标结构体。//go:generategopackage mypackage import "time" //go:generate go tool options-gen -from-struct=Options -out-filename=options_generated.go type Options struct { timeout time.Duration `option:"mandatory" validate:"required"` maxRetries int `default:"3" validate:"min=1"` endpoints []string `option:"variadic=true"` } -
生成代码: 运行生成器:bash
go generate ./options.go -
集成组件: 在组件的构造函数中使用生成的类型,并将其存储在字段中。
optsgotype Component struct { opts Options } func New(setters ...OptionOptionsSetter) (*Component, error) { opts := NewOptions(setters...) if err := opts.Validate(); err != nil { return nil, fmt.Errorf("invalid options: %w", err) } return &Component{opts: opts}, nil }
Expert Guidance
专家指导
Mandatory vs. Default
必填项与默认值
- Use for fields that have no safe default (e.g., API keys, target URLs). These become required arguments in
option:"mandatory".NewOptions() - Use for sensible defaults.
default:"value"supports basic types andoptions-gen.time.Duration
- 对于没有安全默认值的字段(如API密钥、目标URL),使用。这些字段会成为
option:"mandatory"中的必填参数。NewOptions() - 对于合理的默认值,使用。
default:"value"支持基础类型和options-gen。time.Duration
Advanced Defaults
高级默认值
For complex types (like maps or nested structs), use in the generate directive and define a provider function:
-defaults-from=funcgo
//go:generate go tool options-gen -from-struct=Options -out-filename=options_generated.go -defaults-from=func
func defaultOptions() Options {
return Options{
headers: map[string]string{"User-Agent": "my-client"},
}
}对于复杂类型(如映射或嵌套结构体),在生成指令中使用并定义一个提供者函数:
-defaults-from=funcgo
//go:generate go tool options-gen -from-struct=Options -out-filename=options_generated.go -defaults-from=func
func defaultOptions() Options {
return Options{
headers: map[string]string{"User-Agent": "my-client"},
}
}Validation Best Practices
验证最佳实践
- Use for any field that must not be zero-valued.
validate:"required" - Use for enum-like string fields.
validate:"oneof=tcp udp" - Use for counters or sizes.
validate:"min=1"
- 对于任何不能为零值的字段,使用。
validate:"required" - 对于枚举类字符串字段,使用。
validate:"oneof=tcp udp" - 对于计数器或大小字段,使用。
validate:"min=1"
Variadic Setters
可变参数设置器
For slice fields, use to generate a setter that accepts multiple arguments (e.g., ) instead of a single slice (e.g., ).
option:"variadic=true"WithEndpoints("a", "b")WithEndpoints([]string{"a", "b"})对于切片字段,使用来生成接受多个参数的设置器(如),而不是接受单个切片的设置器(如)。
option:"variadic=true"WithEndpoints("a", "b")WithEndpoints([]string{"a", "b"})Avoiding Exported Fields
避免导出字段
By keeping fields unexported in , you ensure that the only way to configure the component is through the generated setters, which can include validation logic.
options.goWith*通过在中保持字段未导出,您可以确保配置组件的唯一方式是通过生成的设置器,这些设置器可以包含验证逻辑。
options.goWith*Multiple Options in One Package
单个包中的多个选项
When a package contains multiple components (e.g., and ), use prefixes to avoid name collisions in generated types and functions.
ClientServer- Filenames: Use and
<prefix>_options.go.<prefix>_options_generated.go - Generator Flag: Use to prefix the generated
-out-prefixandNewOptionstypes.Option...Setter
Example for ():
MyServicemyservice_options.gogo
//go:generate go tool options-gen -from-struct=MyServiceOptions -out-filename=myservice_options_generated.go -out-prefix=MyService
type MyServiceOptions struct {
timeout time.Duration `option:"mandatory"`
}This will generate and , allowing them to coexist with other options in the same package.
NewMyServiceOptionsOptionMyServiceOptionsSetter当一个包包含多个组件(如和)时,使用前缀避免生成的类型和函数出现命名冲突。
ClientServer- 文件名:使用和
<prefix>_options.go。<prefix>_options_generated.go - 生成器标志:使用为生成的
-out-prefix和NewOptions类型添加前缀。Option...Setter
MyServicemyservice_options.gogo
//go:generate go tool options-gen -from-struct=MyServiceOptions -out-filename=myservice_options_generated.go -out-prefix=MyService
type MyServiceOptions struct {
timeout time.Duration `option:"mandatory"`
}这将生成和,使其能够与同一包中的其他选项共存。
NewMyServiceOptionsOptionMyServiceOptionsSetterResources
资源
- Examples: Complete implementations showing unexported fields, validation, and component integration can be found in the assets directory.
- 示例:展示未导出字段、验证和组件集成的完整实现可在assets目录中找到。