2025-11-25 21:10:31 -05:00
2025-11-25 21:19:08 -05:00
2025-11-25 21:19:08 -05:00
2025-11-25 21:10:31 -05:00
2025-11-25 21:10:31 -05:00
2025-11-25 21:10:31 -05:00
2025-11-25 21:10:31 -05:00

settings

A small, concurrency-safe Go package to load simple key/value configuration files and keep them updated automatically.

Package: settings

Quick overview

  • What it does: Parses simple text files containing key/value pairs and stores them in a thread-safe in-memory map. It can watch the file (via a background goroutine) and refresh values when the file on disk changes.
  • File format: Each non-empty, non-comment line must contain a key and a value separated by a delimiter (: or =). Lines beginning with // or # are treated as comments and ignored.

Key features

  • Automatic updates: A background maintenance goroutine periodically calls Update() to reload the file when it changes.
  • Thread-safe: All exported methods on Settings use mutexes or atomic flags where appropriate.
  • Simple scanner: The scanner reads lines, supports comments and a small set of delimiters, and returns clear errors for malformed lines.

Installation

This package is part of the current module. To run tests or use it, ensure your module is initialized (see go.mod) and import it using the module path where it's hosted, e.g.:

import "your/module/path/settings"

Replace your/module/path with your module path.

Public API

  • func NewSettings(filename string, logUpdates bool) *Settings — create a Settings instance using context.Background(); starts the background maintenance goroutine.
  • func NewSettingsWithContext(ctx context.Context, filename string, logUpdates bool) *Settings — same as above but accepts a context.Context to control lifecycle (cancellation stops the maintenance goroutine).
  • func (s *Settings) GetFilename() string — returns the current filename.
  • func (s *Settings) SetFilename(filename string) (updated bool) — atomically change the filename and attempt an immediate update; returns true if filename changed.
  • func (s *Settings) SetKeyValue(key, value string) (updated bool) — set a key/value pair in the in-memory map (returns whether it changed).
  • func (s *Settings) ContainsKey(key string) bool — returns whether a key exists.
  • func (s *Settings) GetKeyValue(key string) string — returns the value for a key (empty string if not present).
  • func (s *Settings) Update() error — force a synchronous update from the current filename; returns an error on IO problems.

Constants / package variables

  • MaintenanceRoutinePace (time.Duration) — pacing for the background maintenance goroutine (default time.Second).
  • WarnIfFileNotFound (bool) — when true, log messages for missing files even if they are os.ErrNotExist.

Scanner details

  • KeyValueDelimiterChars — allowed delimiter bytes (default ':' and '=').
  • ErrNoValidDelimiter — returned when a non-comment non-empty line doesn't contain a valid delimiter.
  • LineIsComment(line string) bool — returns true for lines starting with // or #.

File format example

Valid settings file contents:

// comments allowed
# another comment
host: localhost
port = 8080

mode: production

Notes on behavior

  • When created, NewSettings* immediately attempts an initial load. If the file doesn't exist or another IO error occurs, an error is logged but a Settings instance is still returned.
  • The background maintenance goroutine invokes Update() every MaintenanceRoutinePace. Use NewSettingsWithContext and pass a cancellable context to stop the goroutine when you no longer need the Settings instance.
  • SetFilename will attempt to read the new file immediately. If reading fails an error may be logged depending on WarnIfFileNotFound.
  • LogUpdates is an atomic.Bool on the Settings struct; set to true if you want the package to log add/update operations for keys.

Examples

Create and use Settings:

ctx := context.Background()
settings := settings.NewSettingsWithContext(ctx, "config.settings", false)

// read a value
if settings.ContainsKey("host") {
    host := settings.GetKeyValue("host")
    fmt.Println("host =", host)
}

// change the file being used
settings.SetFilename("other.settings")

// programmatically set a value
settings.SetKeyValue("local_only", "true")

// force a synchronous reload
if err := settings.Update(); err != nil {
    log.Printf("update error: %v", err)
}

Running tests

From the repository root run:

go test ./...

This package includes unit tests for both the scanner and the Settings behaviors (see scanner_test.go and settings_test.go).

Contributing / License

This repository has no public license in the source tree. If you plan to reuse or publish this code, add a LICENSE file or consult the repository owner.

Questions

If you want any additional examples, a different README layout, or embedded documentation for each exported symbol, tell me which format you prefer and I will update the file.

Description
Super simple threadsafe self-updating Settings class with a reader for easily parsing .settings files.
Readme MIT 43 KiB
Languages
Go 100%