util/mak: deprecate NonNil, add type-safe NonNilSliceForJSON, NonNilMapForJSON

And put the rationale in the name too to save the callers the need for a comment.

Change-Id: I090f51b749a5a0641897ee89a8fb2e2080c8b782
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2022-09-10 12:11:59 -07:00
committed by Maisem Ali
parent e7376aca25
commit f3ce1e2536
3 changed files with 42 additions and 33 deletions

View File

@@ -25,10 +25,8 @@ func Set[K comparable, V any, T ~map[K]V](m *T, k K, v V) {
// (currently only a slice or a map) and makes sure it's non-nil for
// JSON serialization. (In particular, JavaScript clients usually want
// the field to be defined after they decode the JSON.)
// MakeNonNil takes a pointer to a Go data structure
// (currently only a slice or a map) and makes sure it's non-nil for
// JSON serialization. (In particular, JavaScript clients usually want
// the field to be defined after they decode the JSON.)
//
// Deprecated: use NonNilSliceForJSON or NonNilMapForJSON instead.
func NonNil(ptr interface{}) {
if ptr == nil {
panic("nil interface")
@@ -51,3 +49,23 @@ func NonNil(ptr interface{}) {
rv.Set(reflect.MakeMap(rv.Type()))
}
}
// NonNilSliceForJSON makes sure that *slicePtr is non-nil so it will
// won't be omitted from JSON serialization and possibly confuse JavaScript
// clients expecting it to be preesnt.
func NonNilSliceForJSON[T any, S ~[]T](slicePtr *S) {
if *slicePtr != nil {
return
}
*slicePtr = make([]T, 0)
}
// NonNilMapForJSON makes sure that *slicePtr is non-nil so it will
// won't be omitted from JSON serialization and possibly confuse JavaScript
// clients expecting it to be preesnt.
func NonNilMapForJSON[K comparable, V any, M ~map[K]V](mapPtr *M) {
if *mapPtr != nil {
return
}
*mapPtr = make(M)
}

View File

@@ -69,3 +69,21 @@ func TestNonNil(t *testing.T) {
t.Error("map still nil")
}
}
func TestNonNilMapForJSON(t *testing.T) {
type M map[string]int
var m M
NonNilMapForJSON(&m)
if m == nil {
t.Fatal("still nil")
}
}
func TestNonNilSliceForJSON(t *testing.T) {
type S []int
var s S
NonNilSliceForJSON(&s)
if s == nil {
t.Fatal("still nil")
}
}