Skip to content

Commit

Permalink
Allow noinit to apply to slices, maps, and unsafe pointers (#83)
Browse files Browse the repository at this point in the history
Previously, this would throw an error. Fixes GH-82.
  • Loading branch information
sethvargo committed Feb 13, 2023
1 parent bddf2fa commit c095b9c
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 5 deletions.
8 changes: 4 additions & 4 deletions README.md
Expand Up @@ -305,8 +305,8 @@ export APP_MYVAR="foo"
## Initialization
By default, all pointer fields are initialized (allocated) so they are not
`nil`. To disable this behavior, use the tag the field as `noinit`:
By default, all pointers, slices, and maps are initialized (allocated) so they
are not `nil`. To disable this behavior, use the tag the field as `noinit`:
```go
type MyStruct struct {
Expand All @@ -332,8 +332,8 @@ type ChildConfig struct {
}
```
The `noinit` tag is only applicable for pointer fields. Putting the tag on a
non-struct-pointer will return an error.
The `noinit` tag is only applicable for pointer, slice, and map fields. Putting
the tag on a different type will return an error.
## Extension
Expand Down
6 changes: 5 additions & 1 deletion envconfig.go
Expand Up @@ -301,7 +301,11 @@ func processWith(ctx context.Context, i interface{}, l Lookuper, parentNoInit bo
}

// NoInit is only permitted on pointers.
if opts.NoInit && ef.Kind() != reflect.Ptr {
if opts.NoInit &&
ef.Kind() != reflect.Ptr &&
ef.Kind() != reflect.Slice &&
ef.Kind() != reflect.Map &&
ef.Kind() != reflect.UnsafePointer {
return fmt.Errorf("%s: %w", tf.Name, ErrNoInitNotPtr)
}
shouldNotInit := opts.NoInit || parentNoInit
Expand Down
37 changes: 37 additions & 0 deletions envconfig_test.go
Expand Up @@ -26,6 +26,7 @@ import (
"strings"
"testing"
"time"
"unsafe"

"github.com/google/go-cmp/cmp"
)
Expand Down Expand Up @@ -2227,6 +2228,42 @@ func TestProcessWith(t *testing.T) {
"FIELD2": "5",
}),
},
{
name: "noinit/map",
input: &struct {
Field map[string]string `env:"FIELD, noinit"`
}{},
exp: &struct {
Field map[string]string `env:"FIELD, noinit"`
}{
Field: nil,
},
lookuper: MapLookuper(nil),
},
{
name: "noinit/slice",
input: &struct {
Field []string `env:"FIELD, noinit"`
}{},
exp: &struct {
Field []string `env:"FIELD, noinit"`
}{
Field: nil,
},
lookuper: MapLookuper(nil),
},
{
name: "noinit/unsafe_pointer",
input: &struct {
Field unsafe.Pointer `env:"FIELD, noinit"`
}{},
exp: &struct {
Field unsafe.Pointer `env:"FIELD, noinit"`
}{
Field: nil,
},
lookuper: MapLookuper(nil),
},
{
name: "noinit/error_not_ptr",
input: &struct {
Expand Down

0 comments on commit c095b9c

Please sign in to comment.