我想我理解here的答案,但为了以防万一,我想明确询问以下事项(如果你认为这是同一个问题,我道歉,但对我来说,关注的问题感觉不同):
func f() *int {
d := 6
pD := new(int)
pD = &d // option 1
*pD = d // option 2
return pD
}
我只是将引用复制为指针的第一个选项是性能方面,更优化(这是教育猜测,但似乎很明显) . 我更喜欢这种方法/模式 .
第二种选择是(浅)复制(?) . 我认为这种方法,因为它复制,我不担心GC扫描'd'的实例 . 由于我的不安全感(或作为初学者的无知),我经常使用这种方法 .
我所担心的(或更多,不安全)是在第一种方法(其中'd'的地址被转移)中,GC会认识到它('d'变量)被指针容器引用,因此它不会被扫除?因此,使用这种方法是安全的吗?即在应用程序的生命周期内,我可以安全地传递从func'f()'返回的指针'pD'吗?
2 回答
没有比官方文档更好的地方了:
(来源:"Effective Go")
因此第一个选项(返回指向局部变量的指针)绝对安全,甚至鼓励 . 通过执行escape analysis,编译器可以告诉变量转义其本地作用域并将其分配给堆 .
简而言之:不 .
第一:Go中没有“引用” . 现在忘了这个想法,否则你会伤到自己 . 真 . 关于“通过引用”的思考是完全错误的 .
第二:表现完全相同 . 暂时忘掉这种类型的纳米优化 . 特别是在处理int时 . 当且仅当您遇到性能问题时:测量,然后进行优化 . 可能直观地认为“处理8字节的小指针必须比复制具有30或甚至100字节的结构快得多” . 它不是,至少不是那么简单 .
第三:只需写一个
func f() *int { d := 6; return &d; }
. 这里没有必要做任何花哨的舞蹈 .第四:选项2对int进行“深层复制” . 但这可能会产生误导,因为没有int的“浅层副本”所以我不确定我是否理解你在这里问的是什么 . Go没有深层和浅层副本的概念 . 如果复制指针值,则复制指针值 . 你还记得第一点吗? Go中没有引用 . 指针值是一个值,如果复制,您有一个指针值的副本 . 这样的副本对指向的值绝对没有任何意义,特别是它不会复制 . 这会暗示Go中的副本不是“深度” . 在谈论Go时,忘记深/浅拷贝 . (当然,您可以实现执行自定义对象“深层复制”的功能)
第五:Go有一个正常工作的垃圾收集器 . 你所做的事情完全没有区别:当一个物体存在时,它将不被收集,一旦它被收集,它就会被收集 . 您可以传递,返回,复制,移交,获取地址,取消引用指针或任何您喜欢的内容,这无关紧要 . GC正常工作 . (除非你故意通过使用包不安全来寻找疼痛和错误 . )