go-defaults
go-defaults
provides functionality to parse and set default values for struct fields based on their "default" tags
Table of Contents
About The Project
The defaults
package simplifies the process of setting default values for struct fields in Go
when they are unset (i.e., at their zero value or nil for pointers). Instead of manually checking each field for its zero value and assigning defaults, defaults uses struct tags to automatically parse and set default values, making your code cleaner and more maintainable. This project was inspired by the need for a streamlined, reusable solution to initialize struct fields with predefined defaults, especially in scenarios involving configuration structs, data models, or nested structures.
Key Features
-
Automatic Default Value Setting: The Defaults function processes a non-nil pointer to a struct, setting default values for exported fields based on their "default" tags (configurable via the package-level Tag variable).
-
Recursive Struct Handling: Nested structs are processed recursively, applying default values to their fields.
-
Broad Type Support: Supports a wide range of field types, including numeric types, strings, booleans, maps, slices, arrays, and their pointers. See Supported/Unsupported Field Types
-
Robust Error Handling: Returns errors for invalid inputs, unexported fields, empty tags (for non-struct fields), parsing failures, out-of-range values, or unsupported types.
Getting Started
Note that we only supports the two most recent minor versions of Go.
go get github.com/lthphuw/go-defaults@latest
Usage
With go-defaults
, you can define defaults
in struct tags
and let the Defaults
function handle initialization:
1type Config struct { 2 Port int `default:"8080"` 3 Host string `default:"localhost"` 4} 5 6func main() { 7 var config Config 8 // Load from env 9 // ... 10 11 // Set defaults 12 if err := defaults.Defaults(&config); err != nil { 13 log.Fatal(err) 14 } 15 fmt.Printf("Port: %d, Host: %s\n", config.Port, config.Host) 16 // Output: Port: 8080, Host: localhost 17}
This approach reduces boilerplate code, improves readability, and ensures consistent default value handling across your application.
Here’s a another complete example demonstrating various field types:
1package main 2 3import ( 4 "fmt" 5 defaults "github.com/lthphuw/go-defaults" 6) 7 8type Nested struct { 9 Value int `default:"100"` 10} 11 12type Example struct { 13 ID int `default:"123"` 14 Name *string `default:"hello"` 15 Data map[string]any `default:"{\"key\":\"value\",\"num\":42}"` 16 Numbers [3]int `default:"[1,2,3]"` 17 Nested Nested 18} 19 20func main() { 21 var s Example 22 if err := defaults.Defaults(&s); err != nil { 23 fmt.Printf("Error: %v\n", err) 24 return 25 } 26 fmt.Printf("ID: %d, Name: %v, Data: %v, Numbers: %v, Nested.Value: %d\n", 27 s.ID, *s.Name, s.Data, s.Numbers, s.Nested.Value) 28}
Output:
1ID: 123, Name: hello, Data: map[key:value num:42], Numbers: [1 2 3], Nested.Value: 100
Supported/Unsupported Field Type
Supported Field Types and Example Tags
The Defaults function supports the following field types with their respective "default" tag formats:
-
Numeric Types:
-
int
: default:"123" -
int8
: default:"127" -
int16
: default:"32767" -
int32
: default:"2147483647" -
int64
: default:"9223372036854775807" -
uint
: default:"123" -
uint8
: default:"255" -
uint16
: default:"65535" -
uint32
: default:"4294967295" -
uint64
: default:"18446744073709551615" -
float32
: default:"3.14" -
float64
: default:"3.14159265359" -
complex64
: default:"1+2i" -
complex128
: default:"1.5+2.5i"
-
-
string
: default:"hello" -
bool
: default:"true" -
map
(e.g., map[string]any): default:"{"key":"value","num":42}" -
slice
(e.g., []string): default:"["a","b","c"]" -
array
(e.g., [3]int): default:"[1,2,3]"
struct
: triggers recursive default setting for nested fields.
Pointers to Above Types:
-
\*int
: default:"123" -
\*string
: default:"hello" -
\*map[string]any
: default:"{"key":"value"}" -
\*[]string
: default:"["a","b"]" -
\*[3]int
: default:"[1,2,3]" -
\*struct
: triggers recursive default setting for nested fields. -
...
Unsupported Field Types
The following types are not supported by Defaults
:
-
Function types
(e.g., func(), *func()) -
Channels
(e.g., chan int) -
Interfaces
-
Unsafe pointers
(e.g., unsafe.Pointer) -
Any other types not listed above
License
This project is licensed under the MIT License – see the LICENSE file for details.
Contact
Maintained by Phu.
For questions, feedback, or support, please contact: lthphuw@gmail.com