Kind() == reflect.Ptr 是判断指针类型的唯一可靠方式,它对 nil 指针安全、不 panic,且不受层级嵌套或类型别名影响;Name() 和字符串匹配均不可靠。

用 Kind() 判断是否为指针类型最直接
Go 没有语法层面的 isPointer 运算符,但 reflect.Kind() 是唯一可靠、轻量、不 panic 的判断依据。它返回的是底层类型“种类”,不是类型名,所以不会被 *int 和 **string 的表层写法干扰。
-
reflect.ValueOf(x).Kind() == reflect.Ptr→ 是指针(包括*T、**T等任意层级) -
reflect.TypeOf(x).Kind() == reflect.Ptr→ 同样有效,适合只关心类型定义的场景(比如参数校验) - 注意:
Kind()对nil指针也安全,返回reflect.Ptr,不会 panic
var p *int = nil v := reflect.ValueOf(p) fmt.Println(v.Kind() == reflect.Ptr) // true —— 安全
别用 Name() 或字符串匹配来判断指针
Name() 返回的是类型名(如 "int"),对指针类型永远返回空字符串;而把 Type.String() 结果拿去字符串匹配 "*",既脆弱又不可靠——结构体嵌套字段、泛型类型参数、别名类型都可能破坏匹配逻辑。
-
reflect.TypeOf(&x).Name()→""(空),因为*int没有名字 -
reflect.TypeOf(&x).String()→"*int",但**map[string][]byte这类就难解析 - 一旦遇到自定义类型别名(如
type PtrInt *int),字符串匹配彻底失效
处理嵌套指针时,Elem() 要配合 IsNil() 一起用
想拿到指针指向的“真实类型”或“真实值”,必须调用 Elem(),但它在 nil 指针上会 panic。所以每次解引用前,必须确认非 nil 且可解引用。
- 先检查
v.Kind() == reflect.Ptr - 再检查
!v.IsNil()(IsNil()只对Ptr、Slice、Map等合法) - 满足后才调用
v.Elem(),否则 panic
func deref(v reflect.Value) reflect.Value {
for v.Kind() == reflect.Ptr {
if v.IsNil() {
return v // 或按需返回零值/错误
}
v = v.Elem()
}
return v
}
修改指针指向的值,必须确保原始变量可寻址
反射能改值的前提是:传入 reflect.ValueOf() 的是变量地址(&x),而不是值本身(x)。否则 SetXXX() 会 panic:“using unaddressable value”。
立即学习“go语言免费学习笔记(深入)”;
- 错:
v := reflect.ValueOf(x); v.Elem().SetInt(42)→ panic - 对:
v := reflect.ValueOf(&x); v.Elem().SetInt(42)→ 成功 - 对嵌套指针(如
***int),只要最外层是可寻址的(即你传了&p),就能一路Elem().Elem().Elem()改到底层
nil,改值时忘了传地址,或者误以为 Name() 能反映指针特征。记住,Kind() == reflect.Ptr 是唯一值得信赖的起点,其余全是围绕它做的防御性操作。










