|
|
|
|
|
by MrDarcy
867 days ago
|
|
My favorite way to prevent this is to make the config truly immutable, but still configurable with something like this: package config
type options struct {
name string
}
type Option func(o *options)
func Name(name string) Option {
return func(o *options) {
o.name = name
}
}
type Config struct {
opts *options
}
func New(opts ...Option) *Config {
o := &options{}
for _, option := range opts {
option(o)
}
return &Config{opts: o}
}
func (c *Config) Name() string {
return c.opts.name
}
Use it with: cfg := config.New(config.Name("Emanon"))
fmt.Println(cfg.Name())
|
|
It's a lot of boilerplate to create something that's not actually immutable. It also makes it harder to figure out which options are available, since now you can't just look at the documentation of the type, you have to look at the whole module package to figure out what the various options are. If one of the fields is a slice or map you can just mutate that slice or map in place, so it's not really immutable. The pattern as Pike describes it has the benefit that supplying an option returns an option that reverses the effect of supplying the option so that you can use the options somewhat like Python context objects that have enter and exit semantics, but in practice I've found that to be useful in a small portion of situations.