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

bconfig

package module
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Jun 6, 2026 License: MIT Imports: 4 Imported by: 0

README

bconfig

bconfig is a lightweight configuration loading library for go that supports composing and overriding configuration from multiple sources using a clean driver/source pattern.


What bconfig Is

  • A library to load, merge, read, and decode configurations.
  • Supports combining configuration from files (YAML, JSON) and environment variables.
  • Supports hierarchical structures with dot-path lookups (specifically for file configurations).
  • Handles deep merging where later sources override earlier sources.
  • Supports decoding configurations into Go structs.

What bconfig Is Not

bconfig is strictly a configuration loading library. It does not provide:

  • HTTP/admin APIs or routing
  • KV database setup or DB storage
  • Dependency injection
  • Graceful shutdown or service lifecycle management
  • Tracing, metrics, or telemetry

Installation

go get github.com/brian-nunez/bconfig

Usage Examples

Basic File Example

Load configuration from a YAML or JSON file:

package main

import (
	"log"

	"github.com/brian-nunez/bconfig"
	"github.com/brian-nunez/bconfig/drivers/file"
)

func main() {
	cfg, err := bconfig.New(
		file.Source("config.yaml"),
	)
	if err != nil {
		log.Fatal(err)
	}

	addr := cfg.String("server.addr")
	log.Printf("Server address: %s", addr)
}
Basic Env Example

Load configuration from environment variables. Keys are lowercased and kept as flat keys:

package main

import (
	"log"

	"github.com/brian-nunez/bconfig"
	"github.com/brian-nunez/bconfig/drivers/env"
)

func main() {
	// If SERVER_PORT=8080, it maps to server_port
	cfg, err := bconfig.New(
		env.Source(),
	)
	if err != nil {
		log.Fatal(err)
	}

	port := cfg.Int("server_port")
	log.Printf("Server port: %d", port)
}
File + Env Example

Chain sources in order. Prefixes are never stripped from key names (preventing data loss), and environment variables are mapped as flat keys:

package main

import (
	"log"

	"github.com/brian-nunez/bconfig"
	"github.com/brian-nunez/bconfig/drivers/env"
	"github.com/brian-nunez/bconfig/drivers/file"
)

func main() {
	cfg, err := bconfig.New(
		file.Source("config.yaml"),
		env.Source("BAPP_"), // Loads only variables starting with BAPP_
	)
	if err != nil {
		log.Fatal(err)
	}

	// Read environment variable BAPP_SERVER_ADDR
	addr := cfg.String("bapp_server_addr")
	log.Printf("Server address: %s", addr)
}
Decode into Struct Example
package main

import (
	"log"

	"github.com/brian-nunez/bconfig"
	"github.com/brian-nunez/bconfig/drivers/file"
)

type AppConfig struct {
	Server struct {
		Addr string `json:"addr" yaml:"addr"`
	} `json:"server" yaml:"server"`
}

func main() {
	cfg, err := bconfig.New(
		file.Source("config.yaml"),
	)
	if err != nil {
		log.Fatal(err)
	}

	var appCfg AppConfig
	if err := cfg.Decode(&appCfg); err != nil {
		log.Fatal(err)
	}

	log.Printf("Decoded server address: %s", appCfg.Server.Addr)
}

Merge Order

Sources are evaluated sequentially from left to right. When multiple sources define the same key path, later sources override earlier sources.

Example:

cfg, err := bconfig.New(
	file.Source("config.yaml"),
	env.Source("BAPP_"),
)

Merge order:

config.yaml
  ↳ BAPP_ environment variables

If config.yaml defines:

server:
  addr: ":8080"
  timeout: "5s"

And BAPP_SERVER_ADDR=:9090 is set in the environment:

  1. The file.Source loads the initial configuration.
  2. The env.Source loads BAPP_SERVER_ADDR=:9090 (keeping prefix and mapping flatly).
  3. The values are deep-merged, resulting in:
server:
  addr: ":8080"
  timeout: "5s"
bapp_server_addr: ":9090"

Future Sources (Planned)

The package is designed with a core Source interface, allowing new sources to be added without modifying the root package.

Vault
vault.Source(vault.Options{
	Addr:  "https://vault.local",
	Token: token,
	Path:  "secret/data/my-app",
})
Consul
consul.Source(consul.Options{
	Addr: "localhost:8500",
	Key:  "apps/my-app/config",
})
S3
s3.Source(s3.Options{
	Bucket: "configs",
	Key:    "my-app/config.yaml",
	Region: "us-east-1",
})

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func WrapDecodeError

func WrapDecodeError(err error) error

WrapDecodeError wraps a decode error with the expected format: "bconfig: decode failed: <original_error>"

func WrapSourceError

func WrapSourceError(sourceName string, err error) error

WrapSourceError wraps a source error with the expected format: "bconfig: failed to load source <source_name>: <original_error>"

Types

type Config

type Config struct {
	// contains filtered or unexported fields
}

Config holds the merged configuration data.

func Load

func Load(ctx context.Context, sources ...Source) (*Config, error)

Load loads configuration from the given sources in order. Later sources override values from earlier sources.

func LoadWithOptions

func LoadWithOptions(ctx context.Context, sources []Source, opts ...Option) (*Config, error)

LoadWithOptions loads configuration from sources and applies options (e.g. validators).

func New

func New(sources ...Source) (*Config, error)

New loads configuration from the given sources using context.Background.

func (*Config) Bool

func (c *Config) Bool(path string) bool

Bool retrieves the value at the given dot-path as a bool. Returns false if the value is missing or not a bool.

func (*Config) Data

func (c *Config) Data() map[string]any

Data returns a deep copy of the configuration data map.

func (*Config) Decode

func (c *Config) Decode(target any) error

Decode unmarshals the configuration data into the target struct. It serializes the internal data map to JSON and then unmarshals it.

func (*Config) Float

func (c *Config) Float(path string) float64

Float retrieves the value at the given dot-path as a float64. Returns 0.0 if the value is missing or not a number.

func (*Config) Get

func (c *Config) Get(path string) any

Get retrieves the value at the given dot-path. Returns nil if the path is not found.

func (*Config) Int

func (c *Config) Int(path string) int

Int retrieves the value at the given dot-path as an int. Returns 0 if the value is missing or not a number.

func (*Config) String

func (c *Config) String(path string) string

String retrieves the value at the given dot-path as a string. Returns a empty string if the value is missing.

type Option

type Option func(*loader)

Option is a function that configures the loader.

func WithStrictMode

func WithStrictMode(enabled bool) Option

WithStrictMode enables or disables strict mode.

func WithValidator

func WithValidator(fn func(*Config) error) Option

WithValidator sets a validation function to be run after configuration is loaded.

type Source

type Source interface {
	Name() string
	Load(ctx context.Context) (map[string]any, error)
}

Source represents a configuration source that can load data.

Directories

Path Synopsis
drivers
env module
file module

Jump to

Keyboard shortcuts

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