@@ -11,27 +11,21 @@ import (
11
11
"strings"
12
12
)
13
13
14
- // ErrInvalidArgument is returned when the argument provided to
15
- // [Load]/[LoadFrom] is invalid.
14
+ // ErrInvalidArgument is returned when the argument provided to [Load]/[LoadFrom] is invalid.
16
15
var ErrInvalidArgument = errors .New ("env: argument must be a non-nil struct pointer" )
17
16
18
- // ErrEmptyTagName is returned when the `env` tag is found but the name of the
19
- // environment variable is empty.
17
+ // ErrEmptyTagName is returned when the `env` tag is found but the name of the environment variable is empty.
20
18
var ErrEmptyTagName = errors .New ("env: empty tag name is not allowed" )
21
19
22
- // ErrUnsupportedType is returned when the provided struct contains a field of
23
- // an unsupported type.
20
+ // ErrUnsupportedType is returned when the provided struct contains a field of an unsupported type.
24
21
var ErrUnsupportedType = errors .New ("env: unsupported type" )
25
22
26
- // ErrInvalidTagOption is returned when the `env` tag contains an invalid
27
- // option, e.g. `env:"VAR,invalid"`.
23
+ // ErrInvalidTagOption is returned when the `env` tag contains an invalid option, e.g. `env:"VAR,invalid"`.
28
24
var ErrInvalidTagOption = errors .New ("env: invalid tag option" )
29
25
30
- // NotSetError is returned when environment variables are marked as required but
31
- // not set.
26
+ // NotSetError is returned when environment variables are marked as required but not set.
32
27
type NotSetError struct {
33
- // Names is a slice of the names of the missing required environment
34
- // variables.
28
+ // Names is a slice of the names of the missing required environment variables.
35
29
Names []string
36
30
}
37
31
@@ -40,15 +34,13 @@ func (e *NotSetError) Error() string {
40
34
return fmt .Sprintf ("env: %v are required but not set" , e .Names )
41
35
}
42
36
43
- // Load loads environment variables into the provided struct using the [OS]
44
- // [Provider] as their source. To specify a custom [Provider], use the
45
- // [LoadFrom] function. dst must be a non-nil struct pointer, otherwise Load
46
- // returns [ErrInvalidArgument].
37
+ // Load loads environment variables into the provided struct using the [OS] [Provider] as their source.
38
+ // To specify a custom [Provider], use the [LoadFrom] function.
39
+ // dst must be a non-nil struct pointer, otherwise Load returns [ErrInvalidArgument].
47
40
//
48
- // The struct fields must have the `env:"VAR"` struct tag, where VAR is the name
49
- // of the corresponding environment variable. Unexported fields are ignored. If
50
- // the tag is found but the name of the environment variable is empty, the
51
- // error will be [ErrEmptyTagName].
41
+ // The struct fields must have the `env:"VAR"` struct tag, where VAR is the name of the corresponding environment variable.
42
+ // Unexported fields are ignored.
43
+ // If the tag is found but the name of the environment variable is empty, the error will be [ErrEmptyTagName].
52
44
//
53
45
// # Supported types
54
46
//
@@ -60,33 +52,28 @@ func (e *NotSetError) Error() string {
60
52
// - [encoding.TextUnmarshaler]
61
53
// - slices of any type above (space is the default separator for values)
62
54
//
63
- // See the [strconv].Parse* functions for parsing rules. Implementing the
64
- // [encoding.TextUnmarshaler] interface is enough to use any user-defined type.
65
- // Nested structs of any depth level are supported, only the leaves of the
66
- // config tree must have the `env` tag. If a field of an unsupported type is
67
- // found, the error will be [ErrUnsupportedType].
55
+ // See the [strconv].Parse* functions for parsing rules.
56
+ // Implementing the [encoding.TextUnmarshaler] interface is enough to use any user-defined type.
57
+ // Nested structs of any depth level are supported, only the leaves of the config tree must have the `env` tag.
58
+ // If a field of an unsupported type is found, the error will be [ErrUnsupportedType].
68
59
//
69
60
// # Default values
70
61
//
71
- // Default values can be specified either using the `default` struct tag (has a
72
- // higher priority) or by initializing the struct fields directly.
62
+ // Default values can be specified either using the `default` struct tag (has a higher priority) or by initializing the struct fields directly.
73
63
//
74
64
// # Per-variable options
75
65
//
76
- // The name of the environment variable can be followed by comma-separated
77
- // options in the form of `env:"VAR,option1,option2,..."`:
66
+ // The name of the environment variable can be followed by comma-separated options in the form of `env:"VAR,option1,option2,..."`:
78
67
//
79
68
// - required: marks the environment variable as required
80
69
// - expand: expands the value of the environment variable using [os.Expand]
81
70
//
82
- // If environment variables are marked as required but not set, an error of type
83
- // [NotSetError] will be returned. If the tag contains an invalid option, the
84
- // error will be [ErrInvalidTagOption].
71
+ // If environment variables are marked as required but not set, an error of type [NotSetError] will be returned.
72
+ // If the tag contains an invalid option, the error will be [ErrInvalidTagOption].
85
73
//
86
74
// # Global options
87
75
//
88
- // In addition to the per-variable options, [env] also supports global options
89
- // that apply to all variables:
76
+ // In addition to the per-variable options, [env] also supports global options that apply to all variables:
90
77
//
91
78
// - [WithPrefix]: sets prefix for each environment variable
92
79
// - [WithSliceSeparator]: sets custom separator to parse slice values
@@ -98,44 +85,40 @@ func Load(dst any, opts ...Option) error {
98
85
return newLoader (OS , opts ... ).loadVars (dst )
99
86
}
100
87
101
- // LoadFrom loads environment variables into the provided struct using the
102
- // specified [Provider] as their source. See [Load] documentation for more
103
- // details.
88
+ // LoadFrom loads environment variables into the provided struct using the specified [Provider] as their source.
89
+ // See [Load] documentation for more details.
104
90
func LoadFrom (p Provider , dst any , opts ... Option ) error {
105
91
return newLoader (p , opts ... ).loadVars (dst )
106
92
}
107
93
108
94
// Option allows to configure the behaviour of the [Load]/[LoadFrom] functions.
109
95
type Option func (* loader )
110
96
111
- // WithPrefix configures [Load]/[LoadFrom] to automatically add the provided
112
- // prefix to each environment variable. By default, no prefix is configured.
97
+ // WithPrefix configures [Load]/[LoadFrom] to automatically add the provided prefix to each environment variable.
98
+ // By default, no prefix is configured.
113
99
func WithPrefix (prefix string ) Option {
114
100
return func (l * loader ) { l .prefix = prefix }
115
101
}
116
102
117
- // WithSliceSeparator configures [Load]/[LoadFrom] to use the provided separator
118
- // when parsing slice values. The default one is space.
103
+ // WithSliceSeparator configures [Load]/[LoadFrom] to use the provided separator when parsing slice values.
104
+ // The default one is space.
119
105
func WithSliceSeparator (sep string ) Option {
120
106
return func (l * loader ) { l .sliceSep = sep }
121
107
}
122
108
123
- // WithStrictMode configures [Load]/[LoadFrom] to treat all environment
124
- // variables without the `default` tag as required. By default, strict mode is
125
- // disabled.
109
+ // WithStrictMode configures [Load]/[LoadFrom] to treat all environment variables without the `default` tag as required.
110
+ // By default, strict mode is disabled.
126
111
func WithStrictMode () Option {
127
112
return func (l * loader ) { l .strictMode = true }
128
113
}
129
114
130
- // WithUsageOnError configures [Load]/[LoadFrom] to write an auto-generated
131
- // usage message to the provided [io.Writer], if an error occurs while loading
132
- // environment variables. The message format can be changed by assigning the
133
- // global [Usage] variable to a custom implementation.
115
+ // WithUsageOnError configures [Load]/[LoadFrom] to write an auto-generated usage message to the provided [io.Writer],
116
+ // if an error occurs while loading environment variables.
117
+ // The message format can be changed by assigning the global [Usage] variable to a custom implementation.
134
118
func WithUsageOnError (w io.Writer ) Option {
135
119
return func (l * loader ) { l .usageOutput = w }
136
120
}
137
121
138
- // loader is an environment variables loader.
139
122
type loader struct {
140
123
provider Provider
141
124
prefix string
@@ -144,8 +127,6 @@ type loader struct {
144
127
usageOutput io.Writer
145
128
}
146
129
147
- // newLoader creates a new loader with the specified [Provider] and applies the
148
- // provided options, which override the default settings.
149
130
func newLoader (p Provider , opts ... Option ) * loader {
150
131
l := loader {
151
132
provider : p ,
@@ -160,7 +141,6 @@ func newLoader(p Provider, opts ...Option) *loader {
160
141
return & l
161
142
}
162
143
163
- // loadVars loads environment variables into the provided struct.
164
144
func (l * loader ) loadVars (dst any ) (err error ) {
165
145
rv := reflect .ValueOf (dst )
166
146
if ! structPtr (rv ) {
@@ -178,8 +158,7 @@ func (l *loader) loadVars(dst any) (err error) {
178
158
}
179
159
}()
180
160
181
- // accumulate missing required variables
182
- // to return NotSetError after the loop is finished.
161
+ // accumulate missing required variables to return NotSetError after the loop is finished.
183
162
var notset []string
184
163
185
164
for _ , v := range vars {
@@ -191,8 +170,6 @@ func (l *loader) loadVars(dst any) (err error) {
191
170
continue
192
171
}
193
172
// ...otherwise, use the default value.
194
- // TODO: actually, there is no need to set a default value
195
- // if it has been obtained from the initialized struct field.
196
173
value = v .Default
197
174
}
198
175
@@ -213,16 +190,13 @@ func (l *loader) loadVars(dst any) (err error) {
213
190
return nil
214
191
}
215
192
216
- // parseVars parses environment variables from the fields of the provided
217
- // struct.
218
193
func (l * loader ) parseVars (v reflect.Value ) ([]Var , error ) {
219
194
var vars []Var
220
195
221
196
for i := 0 ; i < v .NumField (); i ++ {
222
197
field := v .Field (i )
223
198
if ! field .CanSet () {
224
- // skip unexported fields.
225
- continue
199
+ continue // skip unexported fields.
226
200
}
227
201
228
202
// special case: a nested struct, parse its fields recursively.
@@ -238,8 +212,7 @@ func (l *loader) parseVars(v reflect.Value) ([]Var, error) {
238
212
sf := v .Type ().Field (i )
239
213
value , ok := sf .Tag .Lookup ("env" )
240
214
if ! ok {
241
- // skip fields without the `env` tag.
242
- continue
215
+ continue // skip fields without the `env` tag.
243
216
}
244
217
245
218
parts := strings .Split (value , "," )
@@ -290,9 +263,6 @@ func (l *loader) parseVars(v reflect.Value) ([]Var, error) {
290
263
return vars , nil
291
264
}
292
265
293
- // lookupEnv retrieves the value of the environment variable named by the key
294
- // using the internal [Provider]. It replaces $VAR or ${VAR} in the result
295
- // using [os.Expand] if expand is true.
296
266
func (l * loader ) lookupEnv (key string , expand bool ) (string , bool ) {
297
267
value , ok := l .provider .LookupEnv (key )
298
268
if ! ok {
0 commit comments