最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言編譯原理之變量捕獲

 更新時間:2022年08月04日 15:06:26   作者:書旅  
這篇文章主要為大家介紹了Go語言編譯原理之變量捕獲示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

在前邊的幾篇文章中已經(jīng)基本分享完了編譯器前端的一些工作,后邊的幾篇主要是關于編譯器對抽象語法樹進行分析和重構,然后完成一系列的優(yōu)化,其中包括以下五個部分:

  • 變量捕獲
  • 函數(shù)內(nèi)聯(lián)
  • 逃逸分析
  • 閉包重寫
  • 遍歷函數(shù)

后邊的五篇文章主要就是上邊這五個主題,本文分享的是變量捕獲,變量捕獲主要是針對閉包場景的,因為閉包函數(shù)中可能引用閉包外的變量,因此變量捕獲需要明確在閉包中通過值引用或地址引用的方式來捕獲變量

變量捕獲概述

下邊通過一個示例來看一下什么是變量捕獲

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 = %d\n", i, a(i))
	}
}

上一篇文章分享了類型檢查,我們可以繼續(xù)順著編譯的入口文件中類型檢查后邊的代碼往下看,你會看到如下這段代碼

編譯入口文件: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 { //函數(shù)需要是閉包類型
			Curfn = n
			capturevars(n)
		}
	}
	capturevarscomplete = true

從上邊這段代碼及注釋中,我們可以得到以下幾個信息:

  • 變量捕獲應該在逃逸分析之前進行,因為值類型的變量捕獲,不會進行逃逸分析
  • 變量捕獲是針對閉包函數(shù)的
  • 變量捕獲的實現(xiàn)主要是調(diào)用了:src/cmd/compile/internal/gc/closure.go→capturevars

下邊我們就去看capturevars方法的內(nèi)部實現(xiàn),了解變量捕獲的一些細節(jié)

變量捕獲底層實現(xiàn)

所有類型檢查完成后,capturevars將在單獨的階段調(diào)用,它決定閉包捕獲的每個變量是通過值還是通過引用捕獲

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
}

該方法的代碼量很少,大致內(nèi)容就是,它會先獲取到閉包函數(shù)內(nèi)所有變量節(jié)點,然后對這些節(jié)點進行遍歷。確定該閉包需要捕獲的變量之后再沒有被修改時,該變量小于128字節(jié),則會認為他是值引用。后邊它會對外部引用的結點進行類型檢查

總結

本部分比較簡單,但是挺實用的,特別是我這種一直搞不明包閉包引用外部變量的人。后邊的逃逸分析、閉包重寫跟變量捕獲有一定的聯(lián)系,介紹的后邊內(nèi)容的時候再提

以上就是Go語言編譯原理之變量捕獲的詳細內(nèi)容,更多關于Go編譯原理變量捕獲的資料請關注腳本之家其它相關文章!

相關文章

  • go語言發(fā)送smtp郵件的實現(xiàn)示例

    go語言發(fā)送smtp郵件的實現(xiàn)示例

    這篇文章主要介紹了go發(fā)送smtp郵件的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • Golang異常處理之defer,panic,recover的使用詳解

    Golang異常處理之defer,panic,recover的使用詳解

    這篇文章主要為大家介紹了Go語言異常處理機制中defer、panic和recover三者的使用方法,文中示例代碼講解詳細,需要的朋友可以參考下
    2022-05-05
  • go語言中函數(shù)與方法介紹

    go語言中函數(shù)與方法介紹

    這篇文章介紹了go語言中的函數(shù)與方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • GO語言中接口和接口型函數(shù)的具體使用

    GO語言中接口和接口型函數(shù)的具體使用

    本文主要介紹了GO語言中接口和接口型函數(shù)的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-03-03
  • golang結構化日志log/slog包之slog.Record的用法簡介

    golang結構化日志log/slog包之slog.Record的用法簡介

    這篇文章主要為大家詳細介紹了golang結構化日志log/slog包中slog.Record結構體的使用方法和需要注意的點,文中的示例代碼講解詳細,需要的可以學習一下
    2023-10-10
  • Golang?template?包基本原理分析

    Golang?template?包基本原理分析

    這篇文章主要為大家介紹了Golang?template?包基本原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • golang數(shù)組-----尋找數(shù)組中缺失的整數(shù)方法

    golang數(shù)組-----尋找數(shù)組中缺失的整數(shù)方法

    這篇文章主要介紹了golang數(shù)組-----尋找數(shù)組中缺失的整數(shù)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang Gorm實現(xiàn)自定義多態(tài)模型關聯(lián)查詢

    Golang Gorm實現(xiàn)自定義多態(tài)模型關聯(lián)查詢

    GORM 是一個流行的開源 ORM (Object-Relational Mapping) 庫,專為 Go 語言設計,它簡化了與 SQL 數(shù)據(jù)庫的交互,GORM 封裝了數(shù)據(jù)庫操作,使得開發(fā)者能夠通過簡單的鏈式調(diào)用來執(zhí)行 CRUD,本文給大家介紹了Golang Gorm實現(xiàn)自定義多態(tài)模型關聯(lián)查詢,需要的朋友可以參考下
    2024-11-11
  • Go?web中cookie值安全securecookie庫使用原理

    Go?web中cookie值安全securecookie庫使用原理

    這篇文章主要為大家介紹了Go?web中cookie值安全securecookie庫使用及實現(xiàn)原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • Go語言單元測試的實現(xiàn)及用例

    Go語言單元測試的實現(xiàn)及用例

    在日常開發(fā)中,我們通常需要針對現(xiàn)有的功能進行單元測試,以驗證開發(fā)的正確性,本文主要介紹了Go語言單元測試的實現(xiàn)及用例,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01

最新評論

白银市| 周至县| 万源市| 黄大仙区| 清涧县| 肥乡县| 凭祥市| 南漳县| 湖口县| 舒城县| 湘潭县| 广州市| 松溪县| 巴林左旗| 图片| 东乡| 穆棱市| 深泽县| 石柱| 黑水县| 淅川县| 大同县| 岐山县| 明水县| 巴青县| 邵阳县| 陇西县| 油尖旺区| 怀化市| 岳普湖县| 金川县| 德安县| 安化县| 九龙县| 民勤县| 荃湾区| 乡宁县| 深州市| 南平市| 天等县| 五华县|