2 回答

TA贡献1765条经验 获得超5个赞
去 1.18
您可以使用通用函数来捕获切片的基本类型并返回长度为零的切片:
func echo[T any](v []T) []T {
return make([]T, 0)
}
func main() {
n := foo.GetFooBar()
if n == nil {
n = echo(n) // no need to refer to apiv17 here
}
bytes, _ := json.Marshal(n)
fmt.Println(string(bytes)) // prints []
}
需要常规参数v []Tin的目的echo是允许类型推断将切片[]apiv17.SomeObject与参数统一[]T并推断T为基本类型apiv17.SomeObject,这样您就可以调用它,echo(n)而无需显式类型参数。
该包apiv17当然在编译时是已知的,因为它是通过 传递导入的myPackage,因此您可以利用这一点和类型推断来避免为 . 添加显式import语句apiv17。
这就是它在多文件游乐场上的样子:https ://go.dev/play/p/4ycTkaGLFpo
该类型在bar包中声明,但main仅导入play.ground/foo且仅使用foo.GetFooBar.
转到 1.17 及以下版本
反射。只需将echo上面的函数更改为接受interface{}参数(anyGo 1.17 中没有,还记得吗?),然后执行以下操作reflect.MakeSlice:
func set(v interface{}) {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr {
panic("not a ptr")
}
reflect.Indirect(rv).Set(reflect.MakeSlice(rv.Type().Elem(), 0, 0))
}
然后传递一个指向切片的指针,这样你就可以用反射来设置它的值。
func main() {
n := foo.GetFooBar()
if n == nil {
set(&n)
}
fmt.Printf("type: %T, val: %v, is nil: %t\n", n, n, n == nil)
// type: []bar.FooBar, val: [], is nil: false
bytes, _ := json.Marshal(n)
fmt.Println(string(bytes)) // prints [] again
}
Go 1.17 游乐场:https ://go.dev/play/p/4jMkr22LMF7?v=goprev

TA贡献1864条经验 获得超2个赞
另一个答案描述了如何创建一个空切片。
但是你可以更简单地解决你原来的问题:如果results是nil,你不需要创建一个空切片,不管它有什么元素类型,[]无论如何 JSON 封送处理都是。因此,如果results是nil,则无需调用json.Marshal(),只需“输出”即可[]:
results, err := myLibrary.Search()
var bytes []byte
if results == nil {
bytes = []byte{'[', ']' } // JSON marshaling result is "[]"
} else {
bytes, err = json.Marshal(results)
// Handle error
}
- 2 回答
- 0 关注
- 86 浏览
添加回答
举报