Merge pull request #4 from taigrr/cd/getters-and-docs

feat(getters): add GetFloat64 and GetInt64, fix docs
This commit is contained in:
2026-03-06 05:34:09 -05:00
committed by GitHub
5 changed files with 162 additions and 6 deletions

View File

@@ -15,7 +15,7 @@ Originally built to support [grlx](http://github.com/gogrlx/grlx).
go get github.com/taigrr/jety go get github.com/taigrr/jety
``` ```
Requires Go 1.26 or later. Requires Go 1.26.1 or later.
## Quick Start ## Quick Start
@@ -39,7 +39,7 @@ func main() {
// handle error // handle error
} }
// Get values (config file > env > default) // Get values (Set > env > config file > default)
port := jety.GetInt("port") port := jety.GetInt("port")
host := jety.GetString("host") host := jety.GetString("host")
} }
@@ -53,7 +53,7 @@ func main() {
- **Case-insensitive keys**: Keys normalized to lowercase - **Case-insensitive keys**: Keys normalized to lowercase
- **Type coercion**: Getters handle type conversion gracefully - **Type coercion**: Getters handle type conversion gracefully
- **Thread-safe**: Safe for concurrent access - **Thread-safe**: Safe for concurrent access
- **Config precedence**: config file > environment > defaults - **Config precedence**: Set() > environment > config file > defaults
## Nested Configuration ## Nested Configuration
@@ -103,7 +103,7 @@ export MYAPP_PORT=9000
export MYAPP_SERVICES_CLOUD_VAR=override_value export MYAPP_SERVICES_CLOUD_VAR=override_value
``` ```
**Note**: Environment variables override defaults but config files take highest precedence. **Note**: Environment variables override both defaults and config file values for registered keys (keys that appear in defaults or the config file).
## API ## API
@@ -127,11 +127,13 @@ export MYAPP_SERVICES_CLOUD_VAR=override_value
| `Get(key)` | Get raw value | | `Get(key)` | Get raw value |
| `GetString(key)` | Get as string | | `GetString(key)` | Get as string |
| `GetInt(key)` | Get as int | | `GetInt(key)` | Get as int |
| `GetInt64(key)` | Get as int64 |
| `GetFloat64(key)` | Get as float64 |
| `GetBool(key)` | Get as bool | | `GetBool(key)` | Get as bool |
| `GetDuration(key)` | Get as time.Duration | | `GetDuration(key)` | Get as time.Duration |
| `GetStringSlice(key)` | Get as []string | | `GetStringSlice(key)` | Get as []string |
| `GetIntSlice(key)` | Get as []int | | `GetIntSlice(key)` | Get as []int |
| `GetStringMap(key)` | Get as map[string]string | | `GetStringMap(key)` | Get as map[string]any |
| `IsSet(key)` | Check if key has a value | | `IsSet(key)` | Check if key has a value |
| `AllKeys()` | List all known keys | | `AllKeys()` | List all known keys |
| `AllSettings()` | Get all values as a map | | `AllSettings()` | Get all values as a map |

View File

@@ -20,6 +20,14 @@ func SetConfigName(name string) {
defaultConfigManager.SetConfigName(name) defaultConfigManager.SetConfigName(name)
} }
func GetFloat64(key string) float64 {
return defaultConfigManager.GetFloat64(key)
}
func GetInt64(key string) int64 {
return defaultConfigManager.GetInt64(key)
}
func GetInt(key string) int { func GetInt(key string) int {
return defaultConfigManager.GetInt(key) return defaultConfigManager.GetInt(key)
} }

View File

@@ -146,6 +146,64 @@ func (c *ConfigManager) GetStringSlice(key string) []string {
} }
} }
func (c *ConfigManager) GetFloat64(key string) float64 {
c.mutex.RLock()
defer c.mutex.RUnlock()
v, ok := c.resolve(key)
if !ok {
return 0
}
switch val := v.Value.(type) {
case float64:
return val
case float32:
return float64(val)
case int:
return float64(val)
case int64:
return float64(val)
case string:
f, err := strconv.ParseFloat(val, 64)
if err != nil {
return 0
}
return f
case nil:
return 0
default:
return 0
}
}
func (c *ConfigManager) GetInt64(key string) int64 {
c.mutex.RLock()
defer c.mutex.RUnlock()
v, ok := c.resolve(key)
if !ok {
return 0
}
switch val := v.Value.(type) {
case int64:
return val
case int:
return int64(val)
case string:
i, err := strconv.ParseInt(val, 10, 64)
if err != nil {
return 0
}
return i
case float32:
return int64(val)
case float64:
return int64(val)
case nil:
return 0
default:
return 0
}
}
func (c *ConfigManager) GetInt(key string) int { func (c *ConfigManager) GetInt(key string) int {
c.mutex.RLock() c.mutex.RLock()
defer c.mutex.RUnlock() defer c.mutex.RUnlock()

2
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/taigrr/jety module github.com/taigrr/jety
go 1.26.0 go 1.26.1
require ( require (
github.com/BurntSushi/toml v1.6.0 github.com/BurntSushi/toml v1.6.0

View File

@@ -120,6 +120,78 @@ func TestSetAndGetInt(t *testing.T) {
} }
} }
func TestSetAndGetInt64(t *testing.T) {
cm := NewConfigManager()
tests := []struct {
name string
value any
want int64
}{
{"int64", int64(9223372036854775807), 9223372036854775807},
{"int", 42, 42},
{"string", "123456789012345", 123456789012345},
{"float64", 99.9, 99},
{"float32", float32(50.5), 50},
{"invalid string", "not-a-number", 0},
{"nil", nil, 0},
{"unknown type", struct{}{}, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cm.Set("key", tt.value)
got := cm.GetInt64("key")
if got != tt.want {
t.Errorf("GetInt64() = %d, want %d", got, tt.want)
}
})
}
}
func TestSetAndGetFloat64(t *testing.T) {
cm := NewConfigManager()
tests := []struct {
name string
value any
want float64
}{
{"float64", 3.14159, 3.14159},
{"float32", float32(2.5), 2.5},
{"int", 42, 42.0},
{"int64", int64(100), 100.0},
{"string", "1.618", 1.618},
{"invalid string", "not-a-float", 0},
{"nil", nil, 0},
{"unknown type", struct{}{}, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cm.Set("key", tt.value)
got := cm.GetFloat64("key")
if got != tt.want {
t.Errorf("GetFloat64() = %f, want %f", got, tt.want)
}
})
}
}
func TestGetFloat64NotSet(t *testing.T) {
cm := NewConfigManager()
if got := cm.GetFloat64("nonexistent"); got != 0 {
t.Errorf("GetFloat64(nonexistent) = %f, want 0", got)
}
}
func TestGetInt64NotSet(t *testing.T) {
cm := NewConfigManager()
if got := cm.GetInt64("nonexistent"); got != 0 {
t.Errorf("GetInt64(nonexistent) = %d, want 0", got)
}
}
func TestSetAndGetBool(t *testing.T) { func TestSetAndGetBool(t *testing.T) {
cm := NewConfigManager() cm := NewConfigManager()
@@ -1466,3 +1538,19 @@ func TestPackageLevelGet(t *testing.T) {
t.Error("Get(key) failed") t.Error("Get(key) failed")
} }
} }
func TestPackageLevelGetFloat64(t *testing.T) {
defaultConfigManager = NewConfigManager()
Set("rate", 3.14)
if got := GetFloat64("rate"); got != 3.14 {
t.Errorf("GetFloat64(rate) = %f, want 3.14", got)
}
}
func TestPackageLevelGetInt64(t *testing.T) {
defaultConfigManager = NewConfigManager()
Set("bignum", int64(9223372036854775807))
if got := GetInt64("bignum"); got != 9223372036854775807 {
t.Errorf("GetInt64(bignum) = %d, want 9223372036854775807", got)
}
}