Skip to content

Commit 143367e

Browse files
authored
feat: Add parsing for netip and net.HardwareAddr types (#197)
This change expands the `getenv` package to support `netip.Addr`, `netip.Prefix`, and `net.HardwareAddr` types, along with their slice forms, significantly increasing the utility for network-related configurations. Error reporting for `ErrInvalidValue` is improved by wrapping the underlying parsing errors, providing more detailed diagnostics. A new `publicError` type is introduced to allow `errors.Is` checks against package sentinels while retaining the original error cause. Slice parsing error handling is also made more consistent. Additionally, the styling script `fmt.sh` now uses `gofmt` instead of `gofumpt`.
1 parent 62e5e0f commit 143367e

11 files changed

Lines changed: 1613 additions & 66 deletions

File tree

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ Types supported:
5050
- []url.URL
5151
- net.IP
5252
- []net.IP
53+
- netip.Addr
54+
- []netip.Addr
55+
- netip.Prefix
56+
- []netip.Prefix
57+
- net.HardwareAddr
58+
- []net.HardwareAddr
5359
- complex64
5460
- []complex64
5561
- complex128
@@ -190,11 +196,11 @@ Output:
190196
```
191197
[string]: golly; err: <nil>
192198
[int]: 123; err: <nil>
193-
[int]: 0; err: could not parse variable[GH_GETENV_TEST] value[123s4] to type[int]: invalid value
199+
[int]: 0; err: failed to parse environment variable[GH_GETENV_TEST]: strconv.ParseInt: parsing "123s4": invalid syntax: invalid value
194200
[time.Time]: 2022-01-20 00:00:00 +0000 UTC; err: <nil>
195201
[[]float64]: [26.89 0.67]; err: <nil>
196202
[time.Duration]: 2h35m0s; err: <nil>
197-
[url.URL]: {https test:abcd123 golangbyexample.com:8000 /tutorials/intro false false type=advance&compact=false history }; err: <nil>
203+
[url.URL]: https://test:abcd123@golangbyexample.com:8000/tutorials/intro?type=advance&compact=false#history; err: <nil>
198204
[net.IP]: 2001:cb8::17; err: <nil>
199205
[[]string]: [a b c d]; err: <nil>
200206
[complex128]: (1+2i); err: <nil>
@@ -332,7 +338,7 @@ Output:
332338
[time.Time]: 2022-01-20 00:00:00 +0000 UTC
333339
[[]float64]: [26.89 0.67]
334340
[time.Duration]: 2h35m0s
335-
[url.URL]: {https test:abcd123 golangbyexample.com:8000 /tutorials/intro false false type=advance&compact=false history }
341+
[url.URL]: https://test:abcd123@golangbyexample.com:8000/tutorials/intro?type=advance&compact=false#history
336342
[net.IP]: 2001:cb8::17
337343
[[]string]: [a b c d]
338344
[complex128]: (1+2i)

getenv.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@
4141
// - []url.URL
4242
// - net.IP
4343
// - []net.IP
44+
// - netip.Addr
45+
// - []netip.Addr
46+
// - netip.Prefix
47+
// - []netip.Prefix
48+
// - net.HardwareAddr
49+
// - []net.HardwareAddr
4450
// - complex64
4551
// - []complex64
4652
// - complex128
@@ -75,11 +81,17 @@ func Env[T internal.EnvParsable](key string, options ...option.Option) (T, error
7581
val, err := w.ParseEnv(key, params)
7682
if err != nil {
7783
if errors.Is(err, internal.ErrNotSet) {
78-
return t, fmt.Errorf("failed to get environment variable[%s]: %w", key, ErrNotSet)
84+
return t, fmt.Errorf("failed to get environment variable[%s]: %w", key, publicError{
85+
cause: err,
86+
sentinel: ErrNotSet,
87+
})
7988
}
8089

8190
if errors.Is(err, internal.ErrInvalidValue) {
82-
return t, fmt.Errorf("failed to parse environment variable[%s]: %w", key, ErrInvalidValue)
91+
return t, fmt.Errorf("failed to parse environment variable[%s]: %w", key, publicError{
92+
cause: err,
93+
sentinel: ErrInvalidValue,
94+
})
8395
}
8496

8597
return t, fmt.Errorf("failed to parse environment variable[%s]: %w", key, err)
@@ -106,6 +118,20 @@ func EnvOrDefault[T internal.EnvParsable](key string, defaultVal T, options ...o
106118
return val
107119
}
108120

121+
// publicError keeps parser details while matching exported sentinels.
122+
type publicError struct {
123+
cause error
124+
sentinel error
125+
}
126+
127+
func (e publicError) Error() string {
128+
return e.cause.Error()
129+
}
130+
131+
func (e publicError) Unwrap() []error {
132+
return []error{e.cause, e.sentinel}
133+
}
134+
109135
// newParseParams creates new parameters from options.
110136
func newParseParams(opts []option.Option) internal.Parameters {
111137
var p internal.Parameters

getenv_example_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ func ExampleEnv() {
241241
// Output:
242242
// [string]: golly; err: <nil>
243243
// [int]: 123; err: <nil>
244-
// [int]: 0; err: failed to parse environment variable[GH_GETENV_TEST]: invalid value
244+
// [int]: 0; err: failed to parse environment variable[GH_GETENV_TEST]: strconv.ParseInt: parsing "123s4": invalid syntax: invalid value
245245
// [time.Time]: 2022-01-20 00:00:00 +0000 UTC; err: <nil>
246246
// [[]float64]: [26.89 0.67]; err: <nil>
247247
// [time.Duration]: 2h35m0s; err: <nil>

0 commit comments

Comments
 (0)