<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
從 Go 語言誕生以來,它就開始不斷侵蝕 Java 、C、C++ 語言的領地。今年下半年 Go 語言釋出了 1.11 版本,引入了 WebAssembly 技術,瀏覽器端 Javascript 的壟斷地位也開始遭遇 Go 語言的攻擊。這次不同以往,它意味著 Go 語言從後端滲透進了前端,進入了一個全新的世界。
WebAssembly 這個名字翻譯過來就是 「Web 組合」,也就是 Web 端的組合語言。它是一段二進位制位元組碼程式,Javascript 可以將這段二進位制程式編譯成模組,然後再範例化這個模組就可以呼叫位元組碼邏輯了。WebAssembly 程式碼執行的速度很快,比 Javascript 要快很多,Javascript 可以通過 WebAssembly 技術將關鍵性耗費效能的邏輯交給 WebAssembly 來做就可以明顯提升瀏覽器端的效能。
對比顯示,使用 WebAssembly 執行斐波那契數列相比使用原生 Javascript 來實現,執行效率上能帶來 3.5 倍的提升。
WebAssembly 是一項比較新的技術,只有比較現代的瀏覽器才支援 WebAssembly,例如 Chrome、FireFox瀏覽器。
Go 編譯器可以將程式碼編譯成 WebAssembly 二進位制位元組碼,被瀏覽器以靜態資源的形式載入進來後轉換成 Javascript 模組。有了這個模組,瀏覽器可以直接操縱 Go 語言生成的二進位制位元組碼邏輯。同時在 Go 語言編寫的程式碼中可以直接讀寫瀏覽器裡面 Javascript 執行時物件,這樣就完成了 Javascript 和 Go 程式碼的雙向互動。
Go 語言直到 1.11 版本之後才開啟了對 WebAssembly 的支援。如需體驗,必須升級。
下面我們就開始體驗一下 Chrome 瀏覽器與 Go 程式碼是如何互動的。我們要實現一個功能,在瀏覽器的輸入框裡輸入一個正整數,然後呼叫 Go 程式碼的斐波那契數列,再將結果再呈現在頁面上。涉及到 4 個檔案,分別是 fib.go、main.go、index.html、wasm_exec.js。
使用 Go 程式碼編寫 WebAssembly 模組檔案 fib.go,將 Go 語言實現的斐波那契函數註冊到 Javascript 全域性環境。這需要使用內建的 syscall/js 模組,它提供了和 Javascript 引擎互動的介面。
// fib.go package main import "syscall/js" func main() { f_fib := func(params []js.Value) { var n = params[0].Int() // 輸入引數 var callback = params[1] // 回撥引數 var result = fib(n) // 呼叫回撥函數,傳入計算結果 callback.Invoke(result) } // 註冊全域性函數 js.Global().Set("fib", js.NewCallback(f_fib)) // 保持 main 函數持續執行 select {} } // 計算斐波那契數 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 引擎的函數在執行時是非同步的,所以這個函數沒有返回值,在完成計算後需要通過呼叫「傳進來的回撥函數」將結果傳遞到 Javascript 引擎。注意 main 函數要保持執行狀態不要退出,不然註冊進去的 fib 函數體就銷燬了。
下面將 Go 程式碼編譯成 WebAssembly 二進位制位元組碼。
$ GOARCH=wasm GOOS=js go build -o fib.wasm fib.go
執行完成後可以看到目錄下多了一個 fib.wasm,這個就是位元組碼檔案。它的大小是 1.3M,作為靜態檔案傳遞到瀏覽器似乎有點大,不過靜態檔案伺服器一般有 gzip 壓縮,壓縮後的大小隻有幾百K,這差不多也可以接受了。
編寫網頁檔案 index.html,這個網頁包含兩個輸入框,第一個輸入框用來輸入整數引數,第二個輸入框用來呈現計算結果。當第一個輸入框內容發生改變時,呼叫 javascript 程式碼,執行通過 WebAssembly 註冊的 fib 函數。需要傳入引數 n 和回撥的函數。
<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 模組並執行模組 // 也就是執行 Go 程式碼裡面的 main 函數 // 這樣 fib 函數就註冊進了 Javascript 全域性環境 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") // 傳入輸入引數和回撥函數 // 回撥函數負責呈現結果 fib(n, function(result) { var resultDom = document.getElementById("result") resultDom.value = result }) } </script> // 輸入發生變化時,呼叫 WebAssembly 的 fib 函數 <input type="number" id="param" oninput="callFib()"/> <input type="text" id="result" /> </body> </html>
注意程式碼中引入了一個特殊的 js 檔案 wasm_exec.js,這個檔案可以從 Go 安裝目錄的 misc 子目錄裡找到,將它直接拷貝過來。它實現了和 WebAssembly 模組互動的功能。
執行靜態檔案伺服器,這裡不能使用普通的靜態檔案伺服器,因為瀏覽器要求請求到的 WebAssemly 位元組碼檔案的 Content-Type 必須是 application/wasm,很多靜態檔案伺服器並不會因為擴充套件名是 wasm 就會自動使用這個 Content-Type。但是 Go 內建的 HTTP 伺服器可以。所以下面我們使用 Go 程式碼簡單編寫一個靜態檔案伺服器。
package main import ( "log" "net/http" ) func main() { mux := http.NewServeMux() mux.Handle("/", http.FileServer(http.Dir("."))) log.Fatal(http.ListenAndServe(":8000", mux)) }
使用下面的命令執行它
$ go run main.go
開啟瀏覽器,存取 http://localhost:8000,現在就可以體驗它的執行效果了。
其實根本不用擔心,WebAssembly 的目的是替換前端執行比較耗時的邏輯,不是用來替換前端框架的,它也替換不了。雖然開源社群冒出了一個 github.com/elliotforbe… 的 Go WebAssembly 框架,可以讓你使用 Go 語言編寫前端應用程式。但是我仔細看了一下它的的原始碼,發現它原來只是一個玩具 ^_^,實現上沒幾行程式碼,離真實的應用程式差距太遠。
如果 Go WebAssembly 對 javascript 是個威脅,那麼威脅 javascript 的可不止 Go 語言了,能夠將程式碼編譯成 WebAssembly 位元組碼的語言多達幾十種。
希望將當前 javascript 專案的部分程式碼替換成 Go 語言,成本也是顯而易見的。技術棧的切換成本,位元組碼的載入成本,框架專案持續整合的成本都是需要考慮的點。除非能獲得巨大的效能提升,否則使用純粹的 javascript 來完成專案依然是最佳選擇。
以上就是Go語言對前端領域的入侵WebAssembly執行原理的詳細內容,更多關於Go WebAssembly執行原理的資料請關注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