How to Set Default Values in Go Structs
Daniel Hayes
Full-Stack Engineer · Leapcell

Key Takeaways
- Go structs initialize fields with zero values by default.
- Custom defaults should be set via constructor functions or third-party libraries.
- Reflection and tags offer flexibility but increase complexity.
In Go, when a struct is declared, its fields are automatically initialized to their respective zero values. For example, numeric types default to 0
, booleans to false
, and strings to an empty string ""
. However, there are scenarios where assigning custom default values to struct fields is beneficial. This article explores various methods to set default values in Go structs.
1. Constructor Functions
A common practice is to use constructor functions that return a struct instance with desired default values. This approach ensures that every new instance starts with consistent defaults.
type Config struct { Host string Port int } func NewConfig() Config { return Config{ Host: "localhost", Port: 8080, } }
By invoking NewConfig()
, you obtain a Config
struct with Host
set to "localhost"
and Port
to 8080
.
2. Using Struct Tags with Reflection
Go's reflect
package allows reading struct tags at runtime, enabling dynamic assignment of default values based on tags.
type User struct { Name string `default:"John Doe"` Age int `default:"30"` }
A function can iterate over the struct fields, check for the default
tag, and assign the value if the field is uninitialized.
Note: Implementing this requires careful handling and is more complex than constructor functions.
3. Utilizing Third-Party Libraries
Several libraries simplify the process of setting default values in structs:
-
creasty/defaults: This library uses struct tags to define default values and applies them recursively to nested structs.
import "github.com/creasty/defaults" type Server struct { Address string `default:"127.0.0.1"` Port int `default:"8080"` } func main() { srv := Server{} defaults.Set(&srv) // srv.Address is now "127.0.0.1" // srv.Port is now 8080 }
Reference: creasty/defaults on GitHub
-
mcuadros/go-defaults: Similar to
creasty/defaults
, this library uses struct tags to assign default values.import "github.com/mcuadros/go-defaults" type AppConfig struct { Debug bool `default:"true"` Mode string `default:"production"` } func main() { cfg := AppConfig{} defaults.SetDefaults(&cfg) // cfg.Debug is now true // cfg.Mode is now "production" }
Reference: mcuadros/go-defaults on GitHub
4. Custom Initialization Methods
Implementing a method to initialize default values provides flexibility, especially when default values depend on certain conditions.
type Profile struct { Username string Active bool } func (p *Profile) InitDefaults() { if p.Username == "" { p.Username = "guest" } // Active remains false if not set }
By calling InitDefaults()
on a Profile
instance, uninitialized fields receive their default values.
Conclusion
While Go does not support default values for struct fields out of the box, various techniques can achieve similar functionality:
- Constructor functions offer a straightforward approach.
- Reflection with struct tags provides dynamic assignment but adds complexity.
- Third-party libraries like
creasty/defaults
andmcuadros/go-defaults
simplify the process using tags. - Custom methods allow conditional defaulting based on specific logic.
Choosing the appropriate method depends on the specific requirements and complexity of your application.
FAQs
No, Go only assigns zero values by default. Custom defaults require manual assignment.
Use constructor functions that return structs with preset field values.
Yes, libraries like creasty/defaults
are widely used and reliable, though they add dependency overhead.
We are Leapcell, your top choice for hosting Go projects.
Leapcell is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:
Multi-Language Support
- Develop with Node.js, Python, Go, or Rust.
Deploy unlimited projects for free
- pay only for usage — no requests, no charges.
Unbeatable Cost Efficiency
- Pay-as-you-go with no idle charges.
- Example: $25 supports 6.94M requests at a 60ms average response time.
Streamlined Developer Experience
- Intuitive UI for effortless setup.
- Fully automated CI/CD pipelines and GitOps integration.
- Real-time metrics and logging for actionable insights.
Effortless Scalability and High Performance
- Auto-scaling to handle high concurrency with ease.
- Zero operational overhead — just focus on building.
Explore more in the Documentation!
Follow us on X: @LeapcellHQ