<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在前邊的幾篇文章中已經基本分享完了編譯器前端的一些工作,後邊的幾篇主要是關於編譯器對抽象語法樹進行分析和重構,然後完成一系列的優化,其中包括以下五個部分:
後邊的五篇文章主要就是上邊這五個主題,本文分享的是變數捕獲,變數捕獲主要是針對閉包場景的,因為閉包函數中可能參照閉包外的變數,因此變數捕獲需要明確在閉包中通過值參照或地址參照的方式來捕獲變數
下邊通過一個範例來看一下什麼是變數捕獲
package main import ( "fmt" ) func main() { a := 1 b := 2 go func() { //在閉包裡對a或b進行了重新賦值,也會改變參照方式 fmt.Println(a, b) }() a = 666 }
我們可以看到在閉包中參照了外部的變數a、b,由於變數a在閉包之後進行了其他賦值操作,因此在閉包中,a、b變數的參照方式會有所不同。在閉包中,必須採取地址參照的方式對變數a進行操作,而對變數b的參照將通過直接值傳遞的方式進行
我們可以通過如下方式檢視當前程式閉包變數捕獲的情況
go tool compile -m=2 main.go | grep capturing
assign=true代表變數a在閉包完成後又進行了賦值操作
也可以看一個稍微複雜的
func adder() func(int) int {//累加器 sum := 0 //地址參照 return func(v int) int { sum += v return sum } } func main() { a := adder() for i:=0;i<10;i++{ fmt.Printf("0 + 1 + ... + %d = %dn", i, a(i)) } }
上一篇文章分享了型別檢查,我們可以繼續順著編譯的入口檔案中型別檢查後邊的程式碼往下看,你會看到如下這段程式碼
編譯入口檔案:src/cmd/compile/main.go -> gc.Main(archInit) // Phase 4: Decide how to capture closed variables.(決定如何捕獲閉包變數) // This needs to run before escape analysis, // because variables captured by value do not escape.(變數捕獲應該在逃逸分析之前進行,因為值型別的變數捕獲,不會進行逃逸分析) timings.Start("fe", "capturevars") for _, n := range xtop { if n.Op == ODCLFUNC && n.Func.Closure != nil { //函數需要是閉包型別 Curfn = n capturevars(n) } } capturevarscomplete = true
從上邊這段程式碼及註釋中,我們可以得到以下幾個資訊:
capturevars
下邊我們就去看capturevars
方法的內部實現,瞭解變數捕獲的一些細節
所有型別檢查完成後,capturevars將在單獨的階段呼叫,它決定閉包捕獲的每個變數是通過值還是通過參照捕獲
func capturevars(xfunc *Node) { ...... clo := xfunc.Func.Closure cvars := xfunc.Func.Cvars.Slice() out := cvars[:0] for _, v := range cvars { ...... out = append(out, v) ...... outer := v.Name.Param.Outer outermost := v.Name.Defn // out parameters will be assigned to implicitly upon return. if outermost.Class() != PPARAMOUT && !outermost.Name.Addrtaken() && !outermost.Name.Assigned() && v.Type.Width <= 128 { v.Name.SetByval(true) } else { outermost.Name.SetAddrtaken(true) outer = nod(OADDR, outer, nil) } ...... outer = typecheck(outer, ctxExpr) clo.Func.Enter.Append(outer) } xfunc.Func.Cvars.Set(out) lineno = lno }
該方法的程式碼量很少,大致內容就是,它會先獲取到閉包函數內所有變數節點,然後對這些節點進行遍歷。確定該閉包需要捕獲的變數之後再沒有被修改時,且該變數小於128位元組,則會認為他是值參照。後邊它會對外部參照的結點進行型別檢查
本部分比較簡單,但是挺實用的,特別是我這種一直搞不明包閉包參照外部變數的人。後邊的逃逸分析、閉包重寫跟變數捕獲有一定的聯絡,介紹的後邊內容的時候再提
以上就是Go語言編譯原理之變數捕獲的詳細內容,更多關於Go編譯原理變數捕獲的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45