Go中无引用类型,但指针等可模拟引用语义;必须用T而非T的场景包括:修改原变量、避免大结构体拷贝、实现仅在T定义的方法集的接口。
Go 语言中没有传统意义上的“引用类型”(如 Java 的 Object 或 C# 的 class),所有类型本质上都是值类型;但通过指针、切片、map、channel、func 和 interface 这些类型,可以表现出类似引用语义的行为。所谓“值类型与引用类型转换”,实际是

*T 而不是 T?当你需要函数修改原始变量、避免大结构体拷贝、或实现接口时,必须显式使用指针。
func process(s MyBigStruct) 应改为 func process(s *MyBigStruct)
*int 能让 increment(&x) 改变 x 的值,int 参数做不到*T 上定义(比如有 func (t *T) Set(...)),那只有 *T 变量能赋值给该 interface,T 值不行interface{} 接收值还是指针?为什么有时 panic?interface{} 可以保存任意类型值,但它保存的是「值的副本」——包括指针值本身。问题常出在类型断言或反射时对底层类型的误判。
&v(一个 *int),再用 v2 := i.(int) 断言,会 panic:类型不匹配,正确写法是 v2 := i.(*int)
reflect.ValueOf(x).Interface() 获取 interface{} 时,如果 x 是指针,结果仍是 *T;如果后续没注意,直接当 T 用就会出错interface{} 无需取地址,也不建议取地址(&mySlice 是 *[]T,极少需要)T 和 *T 间转换?转换本身很简单(&v 和 *p),但关键在生命周期和有效性检查。
func bad() *int { x := 42; return &x } 是非法的(编译器会报错或自动分配到堆)if p != nil { use(*p) }
interface{} 恢复为具体类型时,优先用「逗号 ok」语法:if v, ok := i.(*MyType); ok { ... },避免 panic&(x + y)、&map[k](若 map 未初始化)、&struct{}.Field 都非法func example() {
s := struct{ name string }{"alice"}
var i interface{} = s // 存值副本
// i = &s // 也可存指针,但类型变成 *struct{...}
if p, ok := i.(*struct{ name string }); ok {
fmt.Println("got pointer:", p.name)
} else if v, ok := i.(struct{ name string }); ok {
fmt.Println("got value:", v.name)
}}
真正容易被忽略的不是语法转换,而是“谁拥有这块内存”和“这个指针是否还有效”。Go 不提供自动装箱/拆箱,也不允许隐式引用提升——每一步取地址或解引用,都得你自己明确写出并担起责任。