如何返回泛型类型
nil
T
?
func (list *mylist[T]) pop() T {
if list.first != nil {
data := list.first.data
list.first = list.first.next
return data
}
return nil
}
func (list *mylist[T]) getfirst() T {
if list.first != nil {
return list.first.data
}
return nil
}
我收到以下编译错误:
cannot use nil as T value in return statement
您无法为
any类型返回
nil
。例如,如果 int
用作 T
的类型参数,则返回 nil
没有任何意义。 nil
也不是结构的有效值。
您可以做的——也是有意义的——是为用于 T
的类型参数返回
零值。例如,指针、切片的零值是
nil
,整数和浮点数的 string
和 0
是空字符串。
如何返回零值?只需声明一个类型为
T
的变量,然后返回它:
func getZero[T any]() T {
var result T
return result
}
测试:
i := getZero[int]()
fmt.Printf("%T %v\n", i, i)
s := getZero[string]()
fmt.Printf("%T %q\n", s, s)
p := getZero[image.Point]()
fmt.Printf("%T %v\n", p, p)
f := getZero[*float64]()
fmt.Printf("%T %v\n", f, f)
哪个输出(在Go Playground上尝试一下):
int 0
string ""
image.Point (0,0)
*float64 <nil>
*new(T)
成语这已被建议作为 golang-nuts 中的首选选项。如果/当某些零值内置函数添加到语言中时,它可能可读性较差,但更容易查找和替换。
它还允许单行分配。
new
内置为任何类型的变量分配存储空间并返回指向它的指针,因此取消引用*new(T)
实际上会产生T
的零值。您可以使用类型参数作为参数:
func Zero[T any]() T {
return *new(T)
}
如果
T
具有可比性,这可以方便地检查某个变量是否为零值:
func IsZero[T comparable](v T) bool {
return v == *new(T)
}
var
类型为 T
简单易读,但总是需要多一行:
func Zero[T any]() T {
var zero T
return zero
}
如果您不想显式声明变量,可以使用命名返回。并不是每个人都喜欢这种语法,尽管当您的函数体比这个人为的示例更复杂时,或者如果您需要操作
defer
语句中的值时,这可能会派上用场:
func Zero[T any]() (ret T) {
return
}
func main() {
fmt.Println(Zero[int]()) // 0
fmt.Println(Zero[map[string]int]()) // map[]
fmt.Println(Zero[chan chan uint64]()) // <nil>
}
命名返回的语法不可能与 var 声明的语法非常相似。
用你的例子:
func (list *mylist[T]) pop() (data T) {
if list.first != nil {
data = list.first.data
list.first = list.first.next
}
return
}
nil
如果您确实想这样做,如问题中所述,您可以明确地返回
*T
。
当类型参数T
被限制为排除指针类型时,可以完成此操作。在这种情况下,您可以将返回类型声明为
*T
,现在您可以返回
nil
,这是指针类型的零值。
// constraint includes only non-pointer types
func getNilFor[T constraints.Integer]() *T {
return nil
}
func main() {
fmt.Println(reflect.TypeOf(getNilFor[int]())) // *int
fmt.Println(reflect.TypeOf(getNilFor[uint64]())) // *uint64
}
让我再说一遍:当 T
NOT 限制为任何允许指针类型的东西时,效果最好,否则你得到的是指针到指针类型:
// pay attention to this
func zero[T any]() *T {
return nil
}
func main() {
fmt.Println(reflect.TypeOf(zero[int]())) // *int, good
fmt.Println(reflect.TypeOf(zero[*int]())) // **int, maybe not what you want...
}
if l == 0 {
var empty T
return empty, errors.New("empty Stack")
}