返回泛型类型的默认值



如何为泛型类型T返回nil

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

您不能为任何类型返回nil。例如,如果int用作T的类型参数,则返回nil毫无意义。nil也不是结构的有效值。

您可以做的事情——以及有意义的事情——是返回用于T的类型参数的零值。例如,对于指针、切片,零值是nil,对于整数和浮点数,它是string0的空字符串。

如何返回零值?只需声明一个类型为T的变量,并返回它:

func getZero[T any]() T {
var result T
return result
}

测试:

i := getZero[int]()
fmt.Printf("%T %vn", i, i)
s := getZero[string]()
fmt.Printf("%T %qn", s, s)
p := getZero[image.Point]()
fmt.Printf("%T %vn", p, p)
f := getZero[*float64]()
fmt.Printf("%T %vn", f, f)

哪些输出(在Go Playground上尝试(:

int 0
string ""
image.Point (0,0)
*float64 <nil>

*new(T)习语

这已被建议作为果朗坚果的首选。如果/当一些零值内建被添加到该语言中时,它可能可读性较差,但更容易找到和替换。

它还允许单行分配。

内置的new为任何类型的变量分配存储空间,并返回指向该变量的指针,因此取消引用*new(T)有效地为T生成零值。您可以使用类型参数作为参数:

func Zero[T any]() T {
return *new(T)
}

T具有可比性的情况下,这对于检查某个变量是否为零值非常有用:

func IsZero[T comparable](v T) bool {
return v == *new(T)
}

Tvar

简洁易读,尽管它总是需要多写一行:

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
}

让我再次声明:当TNOT约束到任何允许指针类型的东西时,这效果最好,否则你得到的是一个指向指针类型的指针:

// 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")
}

最新更新