Flag Structure Patterns
goopt supports a variety of flag organization styles.
1. Flat Flag Structure
type Options struct {
Host string `goopt:"name:host"`
Port int `goopt:"name:port"`
ConfigPath string `goopt:"name:config-path"`
LogLevel string `goopt:"name:log-level"`
}
Advantages:
- Simple and straightforward
- Easy to see all available flags
- Good for small applications
Trade-offs:
- Can become unwieldy with many flags
- No logical grouping
- Potential naming conflicts
2. Namespaced Flags (Nested Structs)
type Options struct {
Server struct {
Host string `goopt:"name:host"`
Port int `goopt:"name:port"`
}
Logging struct {
Level string `goopt:"name:level"`
Path string `goopt:"name:path"`
Format string `goopt:"name:format"`
}
}
Advantages:
- Logical grouping of related flags
- Automatic flag namespacing (e.g.,
server.host
) - Better organization for many flags
- Clear ownership of configuration
Trade-offs:
- Longer flag names
- More nested structures
- Need to consider namespace collisions
3. Reusable Flag Groups
type DatabaseConfig struct {
Host string `goopt:"name:host"`
Port int `goopt:"name:port"`
User string `goopt:"name:user"`
Password string `goopt:"name:password"`
}
type Options struct {
Primary DatabaseConfig
Replica DatabaseConfig
}
Advantages:
- Reuse common flag groups
- Consistent configuration across similar components
- DRY principle applied to flags
- Good for repeated configurations
Trade-offs:
- Need to manage prefixes carefully
- Can lead to very long flag names
- May expose unnecessary options
4. Mixed Approach with Pointers
type LogConfig struct {
Level string `goopt:"name:level"`
Format string `goopt:"name:format"`
}
type Options struct {
Server struct {
Host string `goopt:"name:host"`
Port int `goopt:"name:port"`
Logs *LogConfig
}
Client struct {
Endpoint string `goopt:"name:endpoint"`
Logs *LogConfig
}
}
Advantages:
- Flexible composition of flag groups
- Optional configuration sections
- Good for complex applications
- Reuse without namespace conflicts
Trade-offs:
- Need to handle nil pointers
- Less obvious flag structure
- More complex initialization
Best Practices
- Choose organization based on scale:
- Flat structure for simple applications
- Namespaced for medium complexity
- Reusable groups for large applications
- Namespace Guidelines:
- Use consistent naming patterns
- Keep namespace depth reasonable (2-3 levels max)
- Consider command-line usability
- Flag Naming:
- Prefix for component disambiguation
- Keep names concise but clear
- Documentation:
- Group related flags in help output
- Document default values
- Explain namespace structure
- Reusability:
- Create common flag groups for repeated patterns
- Use pointers for optional configurations
- Consider versioning for shared configs
- Validation:
- Validate at appropriate namespace levels
- Handle dependencies between namespaces
- Consider required vs optional groups