Kratos provides a flexible configuration management system that supports multiple sources, hot-reloading, and type-safe value access.
Core Interface
type Config interface {
Load () error
Scan ( v any ) error
Value ( key string ) Value
Watch ( key string , o Observer ) error
Close () error
}
Load configuration from all sources
Unmarshal entire configuration into a struct
Get a specific configuration value by key
Watch
func(key string, o Observer) error
Watch for changes to a specific key
Close all configuration sources and stop watching
Creating a Config
import (
" github.com/go-kratos/kratos/v2/config "
" github.com/go-kratos/kratos/v2/config/file "
)
c := config . New (
config . WithSource (
file . NewSource ( "/path/to/config.yaml" ),
),
)
defer c . Close ()
if err := c . Load (); err != nil {
log . Fatal ( err )
}
Configuration Sources
Source Interface
type Source interface {
Load () ([] * KeyValue , error )
Watch () ( Watcher , error )
}
File Source
Load configuration from files:
import " github.com/go-kratos/kratos/v2/config/file "
c := config . New (
config . WithSource (
file . NewSource ( "/path/to/config.yaml" ),
file . NewSource ( "/path/to/config.json" ),
),
)
Supported formats:
JSON (.json)
YAML (.yaml, .yml)
TOML (.toml)
XML (.xml)
Environment Source
Load from environment variables:
import " github.com/go-kratos/kratos/v2/config/env "
c := config . New (
config . WithSource (
env . NewSource ( "APP_" ), // Prefix for env vars
),
)
Environment variables are automatically converted:
APP_DATABASE_HOST → database.host
APP_SERVER_PORT → server.port
Multiple Sources
Combine multiple sources with merge strategy:
c := config . New (
config . WithSource (
file . NewSource ( "/etc/app/config.yaml" ), // Base config
file . NewSource ( "./config.yaml" ), // Override
env . NewSource ( "APP_" ), // Environment overrides
),
)
Reading Configuration
Scan Entire Config
type Config struct {
Server struct {
HTTP struct {
Addr string `json:"addr"`
Timeout time . Duration `json:"timeout"`
} `json:"http"`
} `json:"server"`
}
var cfg Config
if err := c . Scan ( & cfg ); err != nil {
log . Fatal ( err )
}
log . Infof ( "HTTP Address: %s " , cfg . Server . HTTP . Addr )
Get Specific Values
// Get string value
addr := c . Value ( "server.http.addr" ). String ()
// Get int value with default
port := c . Value ( "server.http.port" ). Int ()
// Get duration
timeout := c . Value ( "server.http.timeout" ). Duration ()
// Get bool
enabled := c . Value ( "feature.enabled" ). Bool ()
Value Methods
The Value interface provides type-safe accessors:
val := c . Value ( "some.key" )
// Type conversions
val . Bool () bool
val . Int () int
val . Uint () uint
val . Float () float64
val . String () string
val . Duration () time . Duration
val . Slice () [] Value
val . Map () map [ string ] Value
// Scan into struct
var target MyStruct
val . Scan ( & target )
Hot Reload
Watch for Changes
type Observer func ( string , config . Value )
// Watch a specific key
err := c . Watch ( "server.http.addr" , func ( key string , value config . Value ) {
log . Infof ( "Config changed: %s = %s " , key , value . String ())
// Reload components that depend on this config
})
Automatic Reload
File and environment sources automatically watch for changes:
c := config . New (
config . WithSource (
file . NewSource ( "/path/to/config.yaml" ), // Auto-watches file
),
)
c . Load ()
// Configuration automatically reloads when file changes
Custom Decoder
import " gopkg.in/yaml.v3 "
func yamlDecoder ( kv * config . KeyValue , v map [ string ] interface {}) error {
return yaml . Unmarshal ( kv . Value , & v )
}
c := config . New (
config . WithDecoder ( yamlDecoder ),
config . WithSource (
file . NewSource ( "/path/to/config.yaml" ),
),
)
Custom Resolver
Resolve placeholders in configuration:
func envResolver ( input map [ string ] interface {}) error {
// Resolve ${ENV_VAR} placeholders
return nil
}
c := config . New (
config . WithResolver ( envResolver ),
config . WithSource (
file . NewSource ( "/path/to/config.yaml" ),
),
)
Complete Example
server :
http :
addr : 0.0.0.0:8000
timeout : 1s
grpc :
addr : 0.0.0.0:9000
timeout : 1s
data :
database :
driver : mysql
source : root:password@tcp(127.0.0.1:3306)/test
log :
level : info
import (
" github.com/go-kratos/kratos/v2/config "
" github.com/go-kratos/kratos/v2/config/file "
)
type Bootstrap struct {
Server struct {
HTTP struct {
Addr string `json:"addr"`
Timeout time . Duration `json:"timeout"`
} `json:"http"`
GRPC struct {
Addr string `json:"addr"`
Timeout time . Duration `json:"timeout"`
} `json:"grpc"`
} `json:"server"`
Data struct {
Database struct {
Driver string `json:"driver"`
Source string `json:"source"`
} `json:"database"`
} `json:"data"`
}
func main () {
// Create config
c := config . New (
config . WithSource (
file . NewSource ( "./config.yaml" ),
env . NewSource ( "APP_" ),
),
)
defer c . Close ()
// Load config
if err := c . Load (); err != nil {
log . Fatal ( err )
}
// Scan into struct
var bc Bootstrap
if err := c . Scan ( & bc ); err != nil {
log . Fatal ( err )
}
// Use config
httpSrv := http . NewServer (
http . Address ( bc . Server . HTTP . Addr ),
http . Timeout ( bc . Server . HTTP . Timeout ),
)
// Watch for changes
c . Watch ( "server.http.addr" , func ( key string , value config . Value ) {
log . Infof ( "HTTP address changed to: %s " , value . String ())
// Implement reload logic
})
// Start application...
}
Best Practices
Layer configuration sources from least to most specific: defaults → file → environment.
Scan Once, Watch Specific
Scan the entire config once at startup, then watch specific keys that need hot-reload.
Validate configuration after loading to catch errors early.
Always defer Close() to stop watchers and clean up resources.
Check the error when setting up watches - keys must exist before watching.
Logging Configure logging levels
HTTP Server Configure HTTP server options
gRPC Server Configure gRPC server options
Registry Configure service discovery