
Go 中 interface{} 并非等价于 C 的 void,它存储的是值(或地址)及其类型信息;若想通过 interface{} 修改原始整型变量,必须显式解包为 int 并解引用赋值,而非直接给 interface{} 参数重新赋值。
go 中 interface{} 并非等价于 c 的 void*,它存储的是值(或地址)及其类型信息;若想通过 interface{} 修改原始整型变量,必须显式解包为 *int 并解引用赋值,而非直接给 interface{} 参数重新赋值。
在 Go 中,interface{} 是一个空接口,可接收任意类型的值——但它按值传递,且内部由两部分组成:动态类型(type)和动态值(value)。当你传入 &test(即 *int 类型的指针),interface{} 会完整保存该指针值(即内存地址),但函数参数 i 本身是一个新的 interface{} 变量,对 i 直接赋值(如 i = newFunnyValue)仅改变这个局部接口变量的内部值,完全不影响原始变量 test 或其地址所指向的内容。
要真正修改 test 的值,关键在于:获取 i 中存储的 *int 指针,并通过解引用 *p 向该地址写入新值。这需要类型断言(type assertion)安全地提取底层指针:
import "errors"
func someChange(i interface{}) error {
newFunnyValue := 42
// 安全断言:尝试将 i 转换为 *int 类型
if p, ok := i.(*int); ok {
*p = newFunnyValue // ✅ 解引用后赋值,修改原始变量
return nil
}
return errors.New("expected *int, got " + fmt.Sprintf("%T", i))
}使用示例:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
var test int
err := someChange(&test)
if err != nil {
log.Fatal(err)
}
log.Printf("after function: %d", test) // 输出: 42⚠️ 注意事项:
-
不要省略类型检查:
i.(*int)若类型不匹配会 panic;务必使用带ok的断言(p, ok := i.(*int))进行安全转换。 -
struct 包装不是必需的:问题中提到“传 struct 时正常”,是因为 struct 值本身常被取地址传递(如
&MyStruct{}),而你在函数内可能恰好对其字段做了(*s).Field = ...操作——本质仍是解引用修改。对int,只需同样解引用即可,无需额外封装。 -
interface{} ≠ void*:C 的
void*是纯地址,而 Go 的interface{}是类型安全的抽象容器;它不支持隐式指针算术或强制重解释,一切类型转换需显式、安全。
总结:Go 的内存模型强调明确性与安全性。通过 interface{} 传递指针以修改原值,核心是「断言出具体指针类型 → 解引用 → 赋值」三步。掌握这一模式,你就能稳健地处理各类基础类型指针的泛型化操作。

















