gpt4 book ai didi

go - 分配空 slice 而不引用其类型?

转载 作者:行者123 更新时间:2023-12-05 00:51:02 25 4
gpt4 key购买 nike

我的代码调用了一个大致如下所示的库函数:

func Search() ([]myLibrary.SomeObject, error) {
var results []apiv17.SomeObject
// ...
if (resultsFound) {
results = append(results, someResult)
}
return results
}

...我的代码调用它,然后将其编码为 JSON。

results, err := myLibrary.Search()
bytes, err := json.Marshal(results)

现在的问题是,由于 Search 函数的编写方式(假设我们无法更改它),它会返回一个未初始化的 nil如果没有结果就 slice 。不幸的是,没有办法将 encoding/json 配置为将 nil slice 编码为 [](例如,请参阅此 proposal 正在进行讨论)。

显式检查 nil 可以解决问题:

results, err := myLibrary.Search()
if results == nil {
results = []apiv17.SomeObject{}
}
bytes, err := json.Marshal(results)

...但它还添加了对返回类型 apiv17.SomeObject 的显式依赖。这很不方便,因为该类型在库中经常更改。例如。在下一个库版本中,它可能是 apiv18.SomeObject

使用上面的 nil 检查,每次发生这种情况时我都必须更新我的代码。

有什么方法可以避免这种情况,并在不显式引用其类型的情况下为变量分配一个空的非零 slice ?像这样的:

results = [](type of results){}

最佳答案

转到 1.18

您可以使用一个通用函数来捕获 slice 的基本类型并返回一个长度为零的 slice :

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 []Techo是允许类型推断统一 slice []apiv17.SomeObject带有参数 []T并推断 T作为基本类型 apiv17.SomeObject , 这样您就可以将其称为 echo(n)并且没有明确的类型参数。

包裹apiv17在编译时当然是已知的,因为它是通过 myPackage 传递导入的。 ,因此您可以利用这一点和类型推断来避免添加显式 import apiv17 的声明.

这就是它在多文件 Playground 上的样子:https://go.dev/play/p/4ycTkaGLFpo

类型在 bar 中声明包,但 main仅进口 play.ground/foo并且只使用 foo.GetFooBar .


转到 1.17 及以下

反射。只需更改 echo函数从上面获取 interface{}参数(Go 1.17 中没有 any,记得吗?)并使用 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))
}

然后传递一个指向 slice 的指针,这样就可以通过反射来设置它的值。

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 Playground :https://go.dev/play/p/4jMkr22LMF7?v=goprev

关于go - 分配空 slice 而不引用其类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72914784/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com