GopherJS將GO程式碼編繹成純的JavaScript程式碼。它的主要目的是讓你有機會使用GO語言來寫前端程式碼。你可以線上玩一玩。
你可以使用GO優雅的型別系統和編繹時檢查系統,因此你有機會發現大量的潛在BUG,並可以更好的進行重構。想像一下你之前要處理多少有關JavaScript遺留的引數問題,因為你不確定會不會還有人在用這些老API。GopherJS會豪無怨言地幫你解決這些問題。你可以放心,這種BUG將不會再出現。
Goroutines
注*Goroutines是Go語言中一種輕量級的併發實現機制;可以理解為輕量級的多執行緒機制,不同的是Goroutines執行時還可以訪問當前上下文。
JavaScript沒有併發的概念(除了webworkers,但是與Goroutines不同,他們被隔離地太徹底了)。所以,JavaScript中的程式碼永遠不會被阻塞。一個阻塞的呼叫將會讓你的網頁停止響應。所以我們使用了一個帶參回撥來代替。
GopherJS對於這種限制做了大量的工作: 當一個指令被阻塞(比如通訊中的一個通道channel沒有好),整個棧就不會被執行(等待所有的函式都被呼叫過以後),其它goroutine會暫時休息。然後另外一個準備執行的goroutine會恢復執行(與本地變數一起恢復)。這種機制通過一個閉包來實現。
這種機制生成的程式碼效能非常好,但是還是沒有非阻塞系統(基於原生JS回撥)的好。這是GopherJS努力去克服的一面。
但是它也有一個優點,外部JavaScript從來不會被阻塞執行,但你可以使用go語法在JS中達到阻塞的效果。
這是一個Go編繹到JavaScript的示例,來自其Playgroud
GO的程式碼
package main import ( "fmt" "github.com/gopherjs/gopherjs/js" ) func main() { fmt.Println("Hello, playground") js.Global.Call("alert", "Hello, JavaScript") println("Hello, JS console") }
JavaScript程式碼
$packages["main"] = (function() { var $pkg = {}, fmt = $packages["fmt"], js = $packages["github.com/gopherjs/gopherjs/js"], main; main = function() { fmt.Println(new ($sliceType($emptyInterface))([new $String("Hello, playground")])); $global.alert($externalize("Hello, JavaScript", $String)); console.log("Hello, JS console"); }; $pkg.$run = function($b) { $packages["github.com/gopherjs/gopherjs/js"].$init(); $packages["runtime"].$init(); $packages["errors"].$init(); $packages["sync/atomic"].$init(); $packages["sync"].$init(); $packages["io"].$init(); $packages["math"].$init(); $packages["unicode"].$init(); $packages["unicode/utf8"].$init(); $packages["bytes"].$init(); $packages["syscall"].$init(); $packages["strings"].$init(); $packages["time"].$init(); $packages["os"].$init(); $packages["strconv"].$init(); $packages["reflect"].$init(); $packages["fmt"].$init(); $pkg.$init(); main(); }; $pkg.$init = function() { }; return $pkg; })();
引入了非常多的預定義packages和物件如($global,$String)等,個人認為這樣的前端程式碼實用性並不強,冗餘非常明顯,降低了可維護。
目前GO的編繹系統檢查地非常嚴格,不允許一些未定義的外部全域性變數的直接訪問,如你得這樣訪問document:
JS程式碼:
document.write("Hello world!");
GO程式碼:
js.Global.Get("document").Call("write", "Hello world!")
這種機制造成了與外部第三方外掛(如jQuery)等配合起來非常不便。要寫很多額外程式碼。實用性比目前的CoffeeScript和TypeScript還要差很多。
評論(1)