用 reflect.TypeOf(v).Kind() == reflect.Slice 判断是否为 slice,需先用 reflect.ValueOf(v) 处理接口和 nil,再循环解指针;数组 [N]T 的 Kind 是 Array 而非 Slice,不可混淆。

如何用 reflect.TypeOf() 判断一个值是否为 slice
Go 中没有直接的 isSlice() 函数,必须借助 reflect 包。关键不是看变量名或声明,而是看运行时类型;reflect.TypeOf(v).Kind() 返回的是底层类型分类,对所有切片(无论元素类型)都返回 reflect.Slice。
- 传入指针、结构体、map 等非 slice 类型时,
.Kind()会是Ptr、Struct、Map,不是Slice - 注意:不能对
nil接口直接调用reflect.TypeOf(),会 panic;需先判空或用reflect.ValueOf()配合.IsValid() -
reflect.TypeOf([]int{}).Kind() == reflect.Slice✅reflect.TypeOf([3]int{}).Kind() == reflect.Array❌(数组不是 slice)
如何区分 slice 和 array(避免常见误判)
很多人混淆 []T 和 [N]T,但它们在反射中完全不同的 Kind。仅靠 .Kind() == reflect.Slice 才是真正 slice;若想进一步确认元素类型,可用 .Elem() 获取切片的元素类型。
-
reflect.Slice:对应[]string、[]*http.Request等动态长度切片 -
reflect.Array:对应[5]int、[0]byte等固定长度数组 - 错误写法:
reflect.TypeOf([2]int{}).Kind() == reflect.Slice→ 实际返回Array,结果为 false
完整可运行检测函数示例
下面是一个安全、泛用的 IsSlice() 函数,能处理接口、nil、指针指向 slice 等边界情况:
func IsSlice(v interface{}) bool {
rv := reflect.ValueOf(v)
if !rv.IsValid() {
return false
}
// 解引用指针,例如 *[]int → []int
for rv.Kind() == reflect.Ptr {
rv = rv.Elem()
if !rv.IsValid() {
return false
}
}
return rv.Kind() == reflect.Slice
}
- 支持
IsSlice([]string{})→ true - 支持
IsSlice(&[]byte{})→ true(自动解指针) - 支持
IsSlice(nil)→ false(不会 panic) - 不支持
IsSlice(42)或IsSlice("hello")→ false
为什么不用 reflect.ValueOf(x).Type().String() 做判断?
有人尝试用字符串匹配,比如检查 reflect.ValueOf(x).Type().String() 是否包含 "[]",这是不可靠的。因为:
立即学习“go语言免费学习笔记(深入)”;
-
type MySlice []int的.String()是"main.MySlice",不含"[]" - 嵌套类型如
[][]string的字符串是"[][]string",正则易误判 -
.Kind()是反射系统定义的稳定枚举,语义明确,性能也更好 - 永远优先用
.Kind()判断大类(slice/array/map/chan),再用.Elem()或.In()查细节
类型系统里,“是不是 slice”是个 Kind 层级问题,不是字符串格式问题。










