サンプル
Pin spf13/viper's configuration precedence order and the env, IsSet and case-folding traps around it, without reading a config file from disk
sha256:ea36c1c79c3a4263305e79d2403494634711a275d2fd41a2d8df834ac7e9101b
PUBLISHED
L3_CONTRACT_PASS
MIT-0
ケース
- ゴール
- Pin spf13/viper's configuration precedence order and the env, IsSet and case-folding traps around it, without reading a config file from disk HOW
- パッケージ
- github.com/spf13/viper 1.21.0 github.com/spf13/pflag 1.0.10
- 環境
- go 1.26
- 作成日
- 2026-08-14T13:24:24Z
コントラクト
- assert the documented ladder top down by writing the same key at every rung at once: explicit Set beats a changed flag beats env beats config file beats key/value store beats default, each rung checked with everything below it populated
- assert the key/value rung is reachable offline through viper.RemoteConfig, whose interface type is unexported but whose three methods are not, so the one rung nobody ever sees is observable without an etcd server
- assert a bound flag only sits at flag height once pflag records it as Changed, and that its default is consulted last of all, below SetDefault, so a flag default loses to a config file
- assert IsSet searches with that flag-default pass switched off, so it returns false for a key whose Get returns the flag's default
- assert AutomaticEnv computes the name as uppercase(prefix + underscore + key) by exporting the literal name CSX_LOG.LEVEL and watching a dotted key find it, which no shell could have exported
- assert that without SetEnvKeyReplacer the expected CSX_LOG_LEVEL is never consulted for the key log.level, and that installing the replacer reaches it
- assert the underscore between prefix and key is added by viper, so SetEnvPrefix("csx_") looks up CSX__LOG_LEVEL
- assert the replacer runs over the finished name rather than the key alone, so SetEnvPrefix("csx.app") with a dot replacer looks up CSX_APP_LOG_LEVEL
- assert an env var exported empty is treated as unset and falls through to the config file, until AllowEmptyEnv(true) makes the empty string a value that IsSet agrees is set
- assert BindEnv with one argument means prefix plus key, while a second argument is the env name verbatim with no prefix, no uppercasing and no replacer
- assert Get, GetString, GetInt, GetBool and GetDuration return zero values rather than errors on a missing key, so a typo is indistinguishable from a zero, and IsSet is the only thing that tells them apart
- assert, measured, that IsSet is true for a key that only has a default, while Set(key, nil) is invisible to the search and does not even shadow the default underneath it
- assert keys are case-insensitive and stored folded: Get agrees across spellings, AllKeys reports only the lower-case form, and a document's keys are folded on read while its values are left alone
- assert Unmarshal enumerates AllKeys rather than searching per key, so a value AutomaticEnv makes Get return is absent from both AllSettings and the struct, and that either a default for the key or viper.ExperimentalBindStruct brings it back
ファイル
- csx.json
- go.mod
- go.sum
- src/config.go
- test/main.go
オリジンシーダー
検証レシート
- go 1.26 · CONTAINER_RUN · compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS · golang@1 · 2026-08-14 · ed25519:a2ec939a4c60e243
- · CONTAINER_RUN · compile:SKIPPED · contract:FAIL · load:SKIPPED · resolve:PASS · golang@1 · 2026-08-14 · ed25519:7da3f610facce8bf