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

Go語言對前端領(lǐng)域的入侵WebAssembly運(yùn)行原理

 更新時間:2022年07月20日 10:14:06   作者:老錢  
這篇文章主要為大家介紹了不安分的Go語言對Web?前端領(lǐng)域的入侵WebAssembly運(yùn)行原理實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

從 Go 語言誕生以來,它就開始不斷侵蝕 Java 、C、C++ 語言的領(lǐng)地。今年下半年 Go 語言發(fā)布了 1.11 版本,引入了 WebAssembly 技術(shù),瀏覽器端 Javascript 的壟斷地位也開始遭遇 Go 語言的攻擊。這次不同以往,它意味著 Go 語言從后端滲透進(jìn)了前端,進(jìn)入了一個全新的世界。

WebAssembly 運(yùn)行原理

WebAssembly 這個名字翻譯過來就是 「Web 匯編」,也就是 Web 端的匯編語言。它是一段二進(jìn)制字節(jié)碼程序,Javascript 可以將這段二進(jìn)制程序編譯成模塊,然后再實例化這個模塊就可以調(diào)用字節(jié)碼邏輯了。WebAssembly 代碼運(yùn)行的速度很快,比 Javascript 要快很多,Javascript 可以通過 WebAssembly 技術(shù)將關(guān)鍵性耗費(fèi)性能的邏輯交給 WebAssembly 來做就可以明顯提升瀏覽器端的性能。

對比顯示,使用 WebAssembly 運(yùn)行斐波那契數(shù)列相比使用原生 Javascript 來實現(xiàn),運(yùn)行效率上能帶來 3.5 倍的提升。

WebAssembly 是一項比較新的技術(shù),只有比較現(xiàn)代的瀏覽器才支持 WebAssembly,例如 Chrome、FireFox瀏覽器。

Go WebAssembly 運(yùn)行原理

Go 編譯器可以將代碼編譯成 WebAssembly 二進(jìn)制字節(jié)碼,被瀏覽器以靜態(tài)資源的形式加載進(jìn)來后轉(zhuǎn)換成 Javascript 模塊。有了這個模塊,瀏覽器可以直接操縱 Go 語言生成的二進(jìn)制字節(jié)碼邏輯。同時在 Go 語言編寫的代碼中可以直接讀寫瀏覽器里面 Javascript 運(yùn)行時對象,這樣就完成了 Javascript 和 Go 代碼的雙向交互。

Go 語言直到 1.11 版本之后才開啟了對 WebAssembly 的支持。如需體驗,必須升級。

Go WebAssembly 初體驗

下面我們就開始體驗一下 Chrome 瀏覽器與 Go 代碼是如何交互的。我們要實現(xiàn)一個功能,在瀏覽器的輸入框里輸入一個正整數(shù),然后調(diào)用 Go 代碼的斐波那契數(shù)列,再將結(jié)果再呈現(xiàn)在頁面上。涉及到 4 個文件,分別是 fib.go、main.go、index.html、wasm_exec.js。

第一步

使用 Go 代碼編寫 WebAssembly 模塊文件 fib.go,將 Go 語言實現(xiàn)的斐波那契函數(shù)注冊到 Javascript 全局環(huán)境。這需要使用內(nèi)置的 syscall/js 模塊,它提供了和 Javascript 引擎交互的接口。

// fib.go
package main
import "syscall/js"
func main() {
	f_fib := func(params []js.Value) {
		var n = params[0].Int() // 輸入?yún)?shù)
		var callback = params[1] // 回調(diào)參數(shù)
		var result = fib(n)
		// 調(diào)用回調(diào)函數(shù),傳入計算結(jié)果
		callback.Invoke(result)
	}
	// 注冊全局函數(shù)
	js.Global().Set("fib", js.NewCallback(f_fib))
	// 保持 main 函數(shù)持續(xù)運(yùn)行
        select {}
}
// 計算斐波那契數(shù)
func fib(n int) int {
        if n <= 0 {
          return 0
        }
	var result = make([]int, n+1)
	result[0] = 0
	result[1] = 1
	if n <= 1 {
		return result[n]
	}
	for i:=2;i<=n;i++ {
		result[i] = result[i-2] + result[i-1]
	}
	return result[n]
}

Go 語言注冊到 Javascript 引擎的函數(shù)在執(zhí)行時是異步的,所以這個函數(shù)沒有返回值,在完成計算后需要通過調(diào)用「傳進(jìn)來的回調(diào)函數(shù)」將結(jié)果傳遞到 Javascript 引擎。注意 main 函數(shù)要保持運(yùn)行狀態(tài)不要退出,不然注冊進(jìn)去的 fib 函數(shù)體就銷毀了。

第二步

下面將 Go 代碼編譯成 WebAssembly 二進(jìn)制字節(jié)碼。

$ GOARCH=wasm GOOS=js go build -o fib.wasm fib.go

執(zhí)行完成后可以看到目錄下多了一個 fib.wasm,這個就是字節(jié)碼文件。它的大小是 1.3M,作為靜態(tài)文件傳遞到瀏覽器似乎有點大,不過靜態(tài)文件服務(wù)器一般有 gzip 壓縮,壓縮后的大小只有幾百K,這差不多也可以接受了。

第三步

編寫網(wǎng)頁文件 index.html,這個網(wǎng)頁包含兩個輸入框,第一個輸入框用來輸入整數(shù)參數(shù),第二個輸入框用來呈現(xiàn)計算結(jié)果。當(dāng)?shù)谝粋€輸入框內(nèi)容發(fā)生改變時,調(diào)用 javascript 代碼,執(zhí)行通過 WebAssembly 注冊的 fib 函數(shù)。需要傳入?yún)?shù) n 和回調(diào)的函數(shù)。

<html>
<head>
	<meta charset="utf-8">
	<title>Go wasm</title>
</head>
<style>
body {
	text-align: center
}
input {
	height: 50px;
	font-size: 20px;
}
#result {
	margin-left: 20px;
}
</style>
<body>
	<script src="wasm_exec.js"></script>
	<script>
	// 容納 WebAssembly 模塊的容器
 	var go = new Go();
	// 下載 WebAssembly 模塊并執(zhí)行模塊
        // 也就是運(yùn)行 Go 代碼里面的 main 函數(shù)
        // 這樣 fib 函數(shù)就注冊進(jìn)了 Javascript 全局環(huán)境
        WebAssembly.instantiateStreaming(fetch("fib.wasm"), go.importObject).then((result) => {
		go.run(result.instance);
	});
	function callFib() {
		let paramInput = document.getElementById("param")
		let n = parseInt(paramInput.value || "0")
		// 傳入輸入?yún)?shù)和回調(diào)函數(shù)
                // 回調(diào)函數(shù)負(fù)責(zé)呈現(xiàn)結(jié)果
                fib(n, function(result) {
        	    var resultDom = document.getElementById("result")
        	    resultDom.value = result
        	})
	}
	</script>
	// 輸入發(fā)生變化時,調(diào)用 WebAssembly 的 fib 函數(shù)
        <input type="number" id="param" oninput="callFib()"/>
	<input type="text" id="result" />
</body>
</html>

注意代碼中引入了一個特殊的 js 文件 wasm_exec.js,這個文件可以從 Go 安裝目錄的 misc 子目錄里找到,將它直接拷貝過來。它實現(xiàn)了和 WebAssembly 模塊交互的功能。

第四步

運(yùn)行靜態(tài)文件服務(wù)器,這里不能使用普通的靜態(tài)文件服務(wù)器,因為瀏覽器要求請求到的 WebAssemly 字節(jié)碼文件的 Content-Type 必須是 application/wasm,很多靜態(tài)文件服務(wù)器并不會因為擴(kuò)展名是 wasm 就會自動使用這個 Content-Type。但是 Go 內(nèi)置的 HTTP 服務(wù)器可以。所以下面我們使用 Go 代碼簡單編寫一個靜態(tài)文件服務(wù)器。

package main
import (
	"log"
	"net/http"
)
func main() {
	mux := http.NewServeMux()
	mux.Handle("/", http.FileServer(http.Dir(".")))
	log.Fatal(http.ListenAndServe(":8000", mux))
}

使用下面的命令運(yùn)行它

$ go run main.go

第五步

打開瀏覽器,訪問 http://localhost:8000,現(xiàn)在就可以體驗它的運(yùn)行效果了。

Javascript 真的需要擔(dān)心 Go WebAssembly 的威脅么?

其實根本不用擔(dān)心,WebAssembly 的目的是替換前端運(yùn)行比較耗時的邏輯,不是用來替換前端框架的,它也替換不了。雖然開源社區(qū)冒出了一個 github.com/elliotforbe… 的 Go WebAssembly 框架,可以讓你使用 Go 語言編寫前端應(yīng)用程序。但是我仔細(xì)看了一下它的的源碼,發(fā)現(xiàn)它原來只是一個玩具 ^_^,實現(xiàn)上沒幾行代碼,離真實的應(yīng)用程序差距太遠(yuǎn)。

如果 Go WebAssembly 對 javascript 是個威脅,那么威脅 javascript 的可不止 Go 語言了,能夠?qū)⒋a編譯成 WebAssembly 字節(jié)碼的語言多達(dá)幾十種。

希望將當(dāng)前 javascript 項目的部分代碼替換成 Go 語言,成本也是顯而易見的。技術(shù)棧的切換成本,字節(jié)碼的加載成本,框架項目持續(xù)集成的成本都是需要考慮的點。除非能獲得巨大的性能提升,否則使用純粹的 javascript 來完成項目依然是最佳選擇。

以上就是Go語言對前端領(lǐng)域的入侵WebAssembly運(yùn)行原理的詳細(xì)內(nèi)容,更多關(guān)于Go WebAssembly運(yùn)行原理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 利用go語言判斷是否是完全二叉樹

    利用go語言判斷是否是完全二叉樹

    這篇文章主要介紹了利用go語言判斷是否是完全二叉樹,當(dāng)一個節(jié)點存在右子節(jié)點但是不存在左子節(jié)點這顆樹視為非完全二叉樹,通過利用GO語言判斷來判斷出否是完全二叉樹,詳細(xì)內(nèi)容參考如下
    2022-05-05
  • Go語言中的time.Tick 函數(shù)用法解讀

    Go語言中的time.Tick 函數(shù)用法解讀

    Go1.23+中time.Tick自動回收資源,適配長期定時任務(wù);NewTicker需手動Stop(),適合需精細(xì)控制的場景,簡單任務(wù)推薦Tick,復(fù)雜需求或舊版本仍建議NewTicker+defer Stop()
    2025-07-07
  • 詳解Golang中的各種時間操作

    詳解Golang中的各種時間操作

    這篇文章主要介紹了詳解Golang中的各種時間操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • GoLang逃逸分析講解

    GoLang逃逸分析講解

    我們都知道go語言中內(nèi)存管理工作都是由Go在底層完成的,這樣我們可以不用過多的關(guān)注底層的內(nèi)存問題。本文主要總結(jié)一下?Golang內(nèi)存逃逸分析,需要的朋友可以參考以下內(nèi)容,希望對大家有幫助
    2022-12-12
  • Go語言sync包與鎖實現(xiàn)限制線程對變量的訪問

    Go語言sync包與鎖實現(xiàn)限制線程對變量的訪問

    本文主要介紹了Go語言sync包與鎖實現(xiàn)限制線程對變量的訪問,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Go語言什么時候該使用指針

    Go語言什么時候該使用指針

    本文主要介紹了Go語言什么情況下應(yīng)該使用指針,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • go語言K8S?的?informer機(jī)制淺析

    go語言K8S?的?informer機(jī)制淺析

    這篇文章為大家主要介紹了go語言K8S?的?informer機(jī)制淺析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • go xorm存庫處理null值問題

    go xorm存庫處理null值問題

    這篇文章主要介紹了go xorm存庫處理null值問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Go語言的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)JSON

    Go語言的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)JSON

    本文主要介紹了Go語言的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)JSON,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • golang默認(rèn)Logger日志庫在項目中使用Zap日志庫

    golang默認(rèn)Logger日志庫在項目中使用Zap日志庫

    這篇文章主要為大家介紹了golang默認(rèn)Logger日志庫在項目中使用Zap日志庫,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04

最新評論

南乐县| 喀喇| 北安市| 新化县| 巩义市| 香港| 白城市| 三明市| 阿瓦提县| 武平县| 长泰县| 遂宁市| 昌乐县| 洱源县| 邮箱| 蒙山县| 海盐县| 松原市| 定襄县| 虞城县| 嫩江县| 扶绥县| 涟水县| 温泉县| 那坡县| 新巴尔虎右旗| 富顺县| 罗平县| 通辽市| 永川市| 颍上县| 泰安市| 清镇市| 滦南县| 宿松县| 启东市| 苗栗市| 松原市| 柏乡县| 化州市| 名山县|