-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add DerefOrEmpty func to the client
- Loading branch information
Showing
2 changed files
with
189 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package next | ||
|
||
import "reflect" | ||
|
||
// DerefOrEmpty returns the dereferenced value of the input pointer, or the zero | ||
// value of the type if the input is nil. | ||
func DerefOrEmpty[T any](in *T) T { | ||
if in == nil { | ||
tType := reflect.TypeOf(*new(T)) | ||
switch tType.Kind() { | ||
Check failure on line 10 in next/deref.go
|
||
case reflect.Slice, reflect.Array: | ||
return reflect.MakeSlice(tType, 0, 0).Interface().(T) | ||
case reflect.Map: | ||
return reflect.MakeMap(tType).Interface().(T) | ||
default: | ||
var empty T | ||
return empty | ||
} | ||
} | ||
|
||
return *in | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
package next_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/krystal/go-katapult/next" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func ptr[T any](v T) *T { | ||
return &v | ||
} | ||
|
||
func TestDerefOrEmpty_string(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
in *string | ||
want string | ||
}{ | ||
{ | ||
name: "Nil input", | ||
in: nil, | ||
want: "", | ||
}, | ||
{ | ||
name: "Non-nil input", | ||
in: ptr("hello"), | ||
want: "hello", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
require.Equal(t, tt.want, next.DerefOrEmpty(tt.in)) | ||
}) | ||
} | ||
} | ||
|
||
func TestDerefOrEmpty_int(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
in *int | ||
want int | ||
}{ | ||
{ | ||
name: "Nil input", | ||
in: nil, | ||
want: 0, | ||
}, | ||
{ | ||
name: "Non-nil input", | ||
in: ptr(22), | ||
want: 22, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
require.Equal(t, tt.want, next.DerefOrEmpty(tt.in)) | ||
}) | ||
} | ||
} | ||
|
||
func TestDerefOrEmpty_float64(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
in *float64 | ||
want float64 | ||
}{ | ||
{ | ||
name: "Nil input", | ||
in: nil, | ||
want: 0.0, | ||
}, | ||
{ | ||
name: "Non-nil input", | ||
in: ptr(3.14), | ||
want: 3.14, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
require.Equal(t, tt.want, next.DerefOrEmpty(tt.in)) | ||
}) | ||
} | ||
} | ||
|
||
func TestDerefOrEmpty_slice(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
in *[]string | ||
want []string | ||
}{ | ||
{ | ||
name: "Nil input", | ||
in: nil, | ||
want: []string{}, | ||
}, | ||
{ | ||
name: "Non-nil input", | ||
in: ptr([]string{"hello", "world"}), | ||
want: []string{"hello", "world"}, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
require.Equal(t, tt.want, next.DerefOrEmpty(tt.in)) | ||
}) | ||
} | ||
} | ||
|
||
func TestDerefOrEmpty_map(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
in *map[string]int | ||
want map[string]int | ||
}{ | ||
{ | ||
name: "Nil input", | ||
in: nil, | ||
want: map[string]int{}, | ||
}, | ||
{ | ||
name: "Non-nil input", | ||
in: ptr(map[string]int{"hello": 32}), | ||
want: map[string]int{"hello": 32}, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
require.Equal(t, tt.want, next.DerefOrEmpty(tt.in)) | ||
}) | ||
} | ||
} | ||
|
||
func TestDerefOrEmpty_struct(t *testing.T) { | ||
type testStruct struct { | ||
Name string | ||
Age int | ||
} | ||
|
||
tests := []struct { | ||
name string | ||
in *testStruct | ||
want testStruct | ||
}{ | ||
{ | ||
name: "Nil input", | ||
in: nil, | ||
want: testStruct{}, | ||
}, | ||
{ | ||
name: "Non-nil input", | ||
in: ptr(testStruct{Name: "Alice", Age: 22}), | ||
want: testStruct{Name: "Alice", Age: 22}, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
require.Equal(t, tt.want, next.DerefOrEmpty(tt.in)) | ||
}) | ||
} | ||
} |