如何在Go语言中检查泛型类型是否为nil?
泛型函数中安全检查参数是否为nil的实现方式
你的示例代码之所以触发panic,是因为reflect.Value.IsNil()方法只能用于指针、通道、函数、接口、map、切片这些可被赋值为nil的类型。当传入像int这样的值类型时,调用IsNil()会直接引发panic——值类型本身不存在nil的状态,也不支持这个方法。
下面是两种最佳实现方案,根据你的需求选择:
方案1:支持所有类型,仅对可nil类型做检查
如果你的函数需要接受任意类型,只对那些能为nil的类型做nil校验,可以先通过反射判断类型是否支持IsNil(),再执行检查:
package main import ( "fmt" "reflect" ) func main() { Hello(1) // 正常输出:Hello 1 Hello((*int)(nil))// 触发panic:id cannot be nil Hello([]int(nil)) // 触发panic:id cannot be nil } func Hello[T any](id T) { v := reflect.ValueOf(id) // 仅对可nil的类型执行检查 switch v.Kind() { case reflect.Ptr, reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Slice: if v.IsNil() { panic("id cannot be nil") } // 值类型无需检查,直接跳过 default: } fmt.Printf("Hello %v\n", id) }
方案2:编译期限制仅接受可nil类型
如果你的函数只允许接收可nil的类型(比如指针、切片、map等),可以通过类型约束在编译阶段就拦截非法类型,同时直接用== nil判断,无需反射:
package main import "fmt" // 定义可nil类型的约束 type Nilable interface { ~*any | ~[]any | ~map[any]any | ~chan any | ~func() | error } func main() { // Hello(1) // 编译报错:int does not implement Nilable Hello((*int)(nil))// 触发panic:id cannot be nil Hello([]int{1,2}) // 正常输出:Hello [1 2] } func Hello[T Nilable](id T) { if id == nil { panic("id cannot be nil") } fmt.Printf("Hello %v\n", id) }
方案对比
- 方案1更灵活,支持任意类型,但依赖反射,性能略低
- 方案2更安全,编译期就能排查非法类型,无需反射,性能更好
内容的提问来源于stack exchange,提问作者Ado Ren
相关产品推荐
相关产品推荐

