optgen

command module
v0.2.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 21, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

README

optgen

CI Status Go Report Card Go Reference

optgen is a Go code generator that creates functional options for your structs, following the functional options pattern popularized by Dave Cheney and Rob Pike.

Features

  • Functional Option Generation: Generates With* functions for struct fields
  • Sensitive Field Handling: Mark fields as sensitive to hide them in debug output
  • DebugMap Generation: Automatic debug-friendly map representations

Installation

go install github.com/ecordell/optgen@latest

Or add to your tools.go:

package tools

import (
    _ "github.com/ecordell/optgen"
)

Then run:

go mod tidy

Quick Start

1. Define Your Struct

Add debugmap tags to control field visibility:

package myapp

type Config struct {
    Name     string   `debugmap:"visible"`
    Port     int      `debugmap:"visible"`
    Password string   `debugmap:"sensitive"`
    Debug    bool     `debugmap:"visible"`
    Tags     []string `debugmap:"visible-format"`
}
2. Generate Options

Add a go:generate directive:

//go:generate go run github.com/ecordell/optgen -output=config_options.go . Config

Or run manually:

optgen -output=config_options.go . Config
3. Use the Generated Code
// Create new instance with options
config := NewConfigWithOptions(
    WithName("my-app"),
    WithPort(8080),
    WithPassword("secret"),
)

// Update existing instance
config = config.WithOptions(
    WithDebug(true),
    WithTags("production"),
)

// Safe debug output (hides sensitive fields)
fmt.Printf("Config: %+v\n", config.DebugMap())
// Output: map[Debug:true Name:my-app Port:8080 Password:(sensitive) Tags:[production]]

Usage

Command Line
optgen [flags] <package-path> <struct-name> [<struct-name>...]

Flags:

  • -output <path>: Output file path (required)
  • -package <name>: Package name for generated file (optional, inferred from output directory)
  • -prefix: Prefix generated function names with struct name (e.g., WithServerPort instead of WithPort)
  • -sensitive-field-name-matches <substring>: Comma-separated list of field name substrings to treat as sensitive (default: "secure")

Examples:

# Generate options for a single struct
optgen -output=config_options.go . Config

# Generate for multiple structs
optgen -output=options.go . Config Server Database

# Generate with prefixed function names
optgen -output=options.go -prefix . Config Server

# Custom sensitive field detection
optgen -output=opts.go -sensitive-field-name-matches=password,secret,token . Credentials
Generating for Multiple Structs

When generating options for multiple structs in the same file, you may encounter naming collisions if the structs share field names. Use the -prefix flag to avoid this:

type Config struct {
    Name string `debugmap:"visible"`
    Port int    `debugmap:"visible"`
}

type Server struct {
    Host string `debugmap:"visible"`
    Port int    `debugmap:"visible"` // Same field name as Config!
}

Without -prefix (causes collision):

optgen -output=options.go . Config Server
# ERROR: WithPort redeclared

With -prefix (generates unique names):

optgen -output=options.go -prefix . Config Server

Generated functions:

  • WithConfigName(string) ConfigOption
  • WithConfigPort(int) ConfigOption
  • WithServerHost(string) ServerOption
  • WithServerPort(int) ServerOption ✓ No collision!

Usage:

config := NewConfigWithOptions(
    WithConfigName("my-app"),
    WithConfigPort(8080),
)

server := NewServerWithOptions(
    WithServerHost("localhost"),
    WithServerPort(3000),
)
Struct Tags

The debugmap tag controls how fields appear in the generated DebugMap() method:

Tag Value Behavior Use Case
visible Shows actual value Safe, non-sensitive fields
visible-format Shows formatted value (expands slices/maps) Collections you want to inspect
sensitive Shows (sensitive) placeholder Passwords, API keys, tokens
hidden Completely omitted from output Internal fields, implementation details

Example:

type Credentials struct {
    Username string   `debugmap:"visible"`        // Shows: "admin"
    Password string   `debugmap:"sensitive"`      // Shows: "(sensitive)"
    Roles    []string `debugmap:"visible-format"` // Shows: [admin, user]
    Internal string   `debugmap:"hidden"`         // Not included in map
}
Generated Functions

For a struct named Config, optgen generates:

Constructor Functions
  • NewConfigWithOptions(opts ...ConfigOption) *Config - Create new instance
  • NewConfigWithOptionsAndDefaults(opts ...ConfigOption) *Config - Create with default values (requires github.com/creasty/defaults)
Modifier Functions
  • ConfigWithOptions(c *Config, opts ...ConfigOption) *Config - Apply options to existing instance
  • (c *Config) WithOptions(opts ...ConfigOption) *Config - Method variant
Option Builders

For each field:

  • Regular fields: WithFieldName(value T) ConfigOption
  • Slices:
    • WithFieldName(value T) ConfigOption - Append single item
    • SetFieldName(value []T) ConfigOption - Replace entire slice
  • Maps:
    • WithFieldName(key K, value V) ConfigOption - Add single key-value
    • SetFieldName(value map[K]V) ConfigOption - Replace entire map
Utility Functions
  • (c *Config) ToOption() ConfigOption - Convert instance to option
  • (c *Config) DebugMap() map[string]any - Safe debug representation

Advanced Examples

Working with Slices
type Server struct {
    Hosts []string `debugmap:"visible-format"`
}

// Append individual items
server := NewServerWithOptions(
    WithHosts("host1.example.com"),
    WithHosts("host2.example.com"),
)

// Or replace the entire slice
server = server.WithOptions(
    SetHosts([]string{"host1", "host2", "host3"}),
)
Working with Maps
type Config struct {
    Metadata map[string]string `debugmap:"visible-format"`
}

// Add individual entries
config := NewConfigWithOptions(
    WithMetadata("env", "production"),
    WithMetadata("region", "us-west"),
)

// Or replace the entire map
config = config.WithOptions(
    SetMetadata(map[string]string{
        "env": "staging",
        "region": "us-east",
    }),
)
Composition Pattern
// Convert existing config to option
baseConfig := NewConfigWithOptions(
    WithName("base"),
    WithPort(8080),
)

// Use it as template for new configs
prodConfig := NewConfigWithOptions(
    baseConfig.ToOption(),
    WithName("production"),
)

devConfig := NewConfigWithOptions(
    baseConfig.ToOption(),
    WithName("development"),
    WithDebug(true),
)

License

Licensed under the Apache License, Version 2.0. See LICENSE for details.

Inspiration

This project is inspired by:

Documentation

Overview

Package main implements optgen, a code generator for functional options in Go.

optgen generates functional option patterns for Go structs, including:

  • With* functions for setting field values
  • DebugMap methods for safe debug output
  • Special handling for slices, maps, and sensitive fields

Usage:

optgen [flags] <package-path> <struct-name> [<struct-name>...]

Flags:

-output <path>
    Location where generated options will be written (required)
-package <name>
    Name of package to use in output file (optional, inferred from output directory)
-sensitive-field-name-matches <substring>
    Comma-separated list of field name substrings considered sensitive (default: "secure")

Example:

//go:generate go run github.com/ecordell/optgen -output=config_options.go . Config

Struct Tag Format:

Fields must be annotated with the `debugmap` struct tag:

  • "visible" - Show actual field value in DebugMap
  • "visible-format" - Show formatted value (expands collections)
  • "sensitive" - Show "(sensitive)" placeholder
  • "hidden" - Omit from DebugMap entirely

Example struct:

type Config struct {
    Name     string `debugmap:"visible"`
    Password string `debugmap:"sensitive"`
    Data     []byte `debugmap:"hidden"`
}

Directories

Path Synopsis
Code generated by github.com/ecordell/optgen.
Code generated by github.com/ecordell/optgen.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL