Help us shape the future of Go! Take the 2026 Go Developer Survey

optgen

command module
v0.2.6 Latest Latest
Warning

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

Go to latest
Published: Apr 2, 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