Go语言指针混淆:如何正确传递指针给walk库完成赋值
Go语言walk库指针引用赋值问题解决方案
问题背景
使用Go语言walk声明式库时,库要求传入指针变量以自动填充实例。为便于管理,尝试编写函数返回引用传递给库,但无法在原函数中获取正确的对象引用。需在不修改模拟walk库的setup函数前提下,让test_ref结构体的map对应值被填充为"world"。
原工作代码
var t *walk.LineEdit ... LineEdit{ AssignTo: &t, },
我的尝试
LineEdit{ AssignTo: GetLineEdit("msg"), }, ... func GetLineEdit(name string) **walk.LineEdit {
简化测试代码
type test_ref struct { v map[string]*string } func (t *test_ref) init() { t.v = map[string]*string{} } func (t *test_ref) return_ref() **string { s := "hello" t.v["a"] = &s p := t.v["a"] return &p } type test_setup struct { s **string } // 禁止修改此函数 func setup(t test_setup) { w := "world" *(t.s) = &w } func main() { tr := test_ref{} tr.init() s := tr.return_ref() setup(test_setup{ s: s, }) fmt.Println(*tr.v["a"])// 输出hello,不符合预期 }
无效的修改方案(不想修改库代码)
若修改setup函数为以下形式可正常工作,但无法修改walk库代码:
func setup(t test_setup) { w := "world" **(t.s) = w }
解决方案
问题核心在于return_ref函数返回的是局部变量p的地址,而p是t.v["a"]的副本指针。setup函数修改*(t.s)时,仅改变了局部变量p的值,并未影响到test_ref结构体map中存储的指针。
修改return_ref函数,直接返回map中存储的指针的地址:
func (t *test_ref) return_ref() **string { // 先初始化map对应的key为指向nil的指针,避免未初始化问题 if t.v["a"] == nil { var empty *string t.v["a"] = &empty } // 返回map中指针的地址,而非局部变量的地址 return &t.v["a"] }
修改后,setup函数对*(t.s)的赋值会直接修改test_ref结构体map中的指针值,执行main函数后*tr.v["a"]将输出"world"。同时,此修改也规避了原代码中局部变量s被回收导致的悬空指针风险。
内容的提问来源于stack exchange,提问作者Sam Washington
相关产品推荐
相关产品推荐

