Skip to content

Commit c86469e

Browse files
author
Dean Karn
authored
Add UnwrapOr* functions (#40)
Added `UnwrapOr`, `UnwrapOrElse` and `UnwrapOrDefault` functions to `Option` & `Result` types.
1 parent b9698f8 commit c86469e

File tree

6 files changed

+101
-2
lines changed

6 files changed

+101
-2
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
## [5.21.3] - 2023-10-18
10+
### Added
11+
- `UnwrapOr`, `UnwrapOrElse` and `UnwrapOrDefault` functions to `Option` & `Result` types.
12+
913
## [5.21.3] - 2023-10-11
1014
### Fixed
1115
- Fix SQL Scanner interface not returning None for Option when source data is nil.
@@ -78,7 +82,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7882
### Added
7983
- Added `timext.NanoTime` for fast low level monotonic time with nanosecond precision.
8084

81-
[Unreleased]: https://github.com/go-playground/pkg/compare/v5.21.3...HEAD
85+
[Unreleased]: https://github.com/go-playground/pkg/compare/v5.22.0...HEAD
86+
[5.22.0]: https://github.com/go-playground/pkg/compare/v5.21.3..v5.22.0
8287
[5.21.3]: https://github.com/go-playground/pkg/compare/v5.21.2..v5.21.3
8388
[5.21.2]: https://github.com/go-playground/pkg/compare/v5.21.1..v5.21.2
8489
[5.21.1]: https://github.com/go-playground/pkg/compare/v5.21.0..v5.21.1

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# pkg
22

3-
![Project status](https://img.shields.io/badge/version-5.21.3-green.svg)
3+
![Project status](https://img.shields.io/badge/version-5.22.0-green.svg)
44
[![Lint & Test](https://github.com/go-playground/pkg/actions/workflows/go.yml/badge.svg)](https://github.com/go-playground/pkg/actions/workflows/go.yml)
55
[![Coverage Status](https://coveralls.io/repos/github/go-playground/pkg/badge.svg?branch=master)](https://coveralls.io/github/go-playground/pkg?branch=master)
66
[![GoDoc](https://godoc.org/github.com/go-playground/pkg?status.svg)](https://pkg.go.dev/mod/github.com/go-playground/pkg/v5)

values/option/option.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,30 @@ func (o Option[T]) Unwrap() T {
6969
panic("Option.Unwrap: option is None")
7070
}
7171

72+
// UnwrapOr returns the contained `Some` value or provided default value.
73+
//
74+
// Arguments passed to `UnwrapOr` are eagerly evaluated; if you are passing the result of a function call,
75+
// look to use `UnwrapOrElse`, which can be lazily evaluated.
76+
func (o Option[T]) UnwrapOr(value T) T {
77+
if o.isSome {
78+
return o.value
79+
}
80+
return value
81+
}
82+
83+
// UnwrapOrElse returns the contained `Some` value or computes it from a provided function.
84+
func (o Option[T]) UnwrapOrElse(fn func() T) T {
85+
if o.isSome {
86+
return o.value
87+
}
88+
return fn()
89+
}
90+
91+
// UnwrapOrDefault returns the contained `Some` value or the default value of the type T.
92+
func (o Option[T]) UnwrapOrDefault() T {
93+
return o.value
94+
}
95+
7296
// Some creates a new Option with the given values.
7397
func Some[T any](value T) Option[T] {
7498
return Option[T]{value, true}

values/option/option_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,37 @@ type testStructType struct {
2626
Name string
2727
}
2828

29+
func TestUnwraps(t *testing.T) {
30+
none := None[int]()
31+
PanicMatches(t, func() { none.Unwrap() }, "Option.Unwrap: option is None")
32+
33+
v := none.UnwrapOr(3)
34+
Equal(t, 3, v)
35+
36+
v = none.UnwrapOrElse(func() int { return 2 })
37+
Equal(t, 2, v)
38+
39+
v = none.UnwrapOrDefault()
40+
Equal(t, 0, v)
41+
42+
// now test with a pointer type.
43+
type myStruct struct {
44+
S string
45+
}
46+
47+
sNone := None[*myStruct]()
48+
PanicMatches(t, func() { sNone.Unwrap() }, "Option.Unwrap: option is None")
49+
50+
v2 := sNone.UnwrapOr(&myStruct{S: "blah"})
51+
Equal(t, &myStruct{S: "blah"}, v2)
52+
53+
v2 = sNone.UnwrapOrElse(func() *myStruct { return &myStruct{S: "blah 2"} })
54+
Equal(t, &myStruct{S: "blah 2"}, v2)
55+
56+
v2 = sNone.UnwrapOrDefault()
57+
Equal(t, nil, v2)
58+
}
59+
2960
func TestSQLDriverValue(t *testing.T) {
3061

3162
var v valueTest

values/result/result.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,30 @@ func (r Result[T, E]) Unwrap() T {
3838
panic("Result.Unwrap(): result is Err")
3939
}
4040

41+
// UnwrapOr returns the contained Ok value or a provided default.
42+
//
43+
// Arguments passed to UnwrapOr are eagerly evaluated; if you are passing the result of a function call,
44+
// look to use `UnwrapOrElse`, which can be lazily evaluated.
45+
func (r Result[T, E]) UnwrapOr(value T) T {
46+
if r.isOk {
47+
return r.ok
48+
}
49+
return value
50+
}
51+
52+
// UnwrapOrElse returns the contained Ok value or computes it from a provided function.
53+
func (r Result[T, E]) UnwrapOrElse(fn func() T) T {
54+
if r.isOk {
55+
return r.ok
56+
}
57+
return fn()
58+
}
59+
60+
// UnwrapOrDefault returns the contained Ok value or the default value of the type T.
61+
func (r Result[T, E]) UnwrapOrDefault() T {
62+
return r.ok
63+
}
64+
4165
// Err returns the error of the result. To be used after calling IsOK()
4266
func (r Result[T, E]) Err() E {
4367
return r.err

values/result/result_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,28 @@ package resultext
55

66
import (
77
"errors"
8+
"io"
89
"testing"
910

1011
. "github.com/go-playground/assert/v2"
1112
)
1213

1314
type myStruct struct{}
1415

16+
func TestUnwrap(t *testing.T) {
17+
er := Err[int, error](io.EOF)
18+
PanicMatches(t, func() { er.Unwrap() }, "Result.Unwrap(): result is Err")
19+
20+
v := er.UnwrapOr(3)
21+
Equal(t, 3, v)
22+
23+
v = er.UnwrapOrElse(func() int { return 2 })
24+
Equal(t, 2, v)
25+
26+
v = er.UnwrapOrDefault()
27+
Equal(t, 0, v)
28+
}
29+
1530
func TestResult(t *testing.T) {
1631
result := returnOk()
1732
Equal(t, true, result.IsOk())

0 commit comments

Comments
 (0)