Hlavní navigace

Využití WebAssembly z programovacího jazyka Go

Pavel Tišnovský

Standardní překladač a linker jazyka Go dokáže vytvářet spustitelné binární soubory jak pro všechny podporované architektury, tak i pro virtuální stroj WebAssembly. Dnes se tedy s touto zajímavou technologií podrobněji seznámíme.

Doba čtení: 30 minut

Sdílet

11. WebAssembly a DOM

12. Změna obsahu vybrané značky

13. Přidání nových značek do HTML stránky

14. Kreslení do 2D canvasu

15. Komunikace mezi Go a JavaScriptem

16. Překlad programů naprogramovaných v Go do JavaScriptu

17. Repositář s demonstračními příklady

18. Pomocné soubory použité demonstračními příklady

19. Odkazy na články s tématem WebAssembly

20. Odkazy na Internetu

1. Využití WebAssembly z programovacího jazyka Go

Při tvorbě webových aplikací popř. aplikací používajících například dnes populární technologii Electron se mnohdy používá programovací jazyk JavaScript. Je to pochopitelné, protože většina současných webových prohlížečů (samozřejmě pokud se nejedná o specializované prohlížeče typu Lynx) obsahuje interpret a popř. i JIT (just-in-time) překladač JavaScriptu, přičemž podpora pro další programovací jazyky přímo neexistuje. To s sebou přináší některé výhody, ale i mnoho záporů, ostatně jako každá monokultura (nejenom) v IT. Pro webové aplikace, v nichž se intenzivně pracuje především s DOMem HTML stránky, nemusí být toto omezení tak kritické, ovšem pro výpočetně náročnější aplikace popř. ve chvíli, kdy se ve větší míře používá grafika (2D či 3D canvas) je již podpora pouze relativně vysokoúrovňového a dynamicky typovaného (a tím pádem hůře JITovatelného) JavaScriptu dosti omezující.

Jedno z možných řešení, které se nabízí, je buď použití nativních klientů (se všemi z toho plynoucími bezpečnostními aj. důsledky) nebo využití nějaké formy virtuálního stroje, který by ovšem měl být co nejjednodušší a ideálně dobře specifikovaný, aby ho bylo možné relativně snadno implementovat ve všech používaných prohlížečích. V současnosti je tímto virtuálním strojem WebAssembly, což je popis instrukcí tohoto stroje i jeho očekávaného chování. Díky tomu, že je WebAssembly podporován prakticky všemi relevantními prohlížeči, začal se postupně rozšiřovat, zejména ve výpočetně intenzivnějších aplikacích (například se jedná o šachový engine atd.). Dnes si ukážeme, jak je možné WebAssembly použít společně s programovacím jazykem Go pro tvorbu frontendových částí aplikací, nicméně je nutné poznamenat, že WebAssembly je dnes velmi populární zejména v komunitě vývojářů používajících programovací jazyk Rust.

Poznámka: použití virtuálního stroje přímo ve webovém prohlížeči samozřejmě není žádnou žhavou novinkou, protože se podobné technologie objevily již dříve, a to dokonce vícekrát. Připomeňme si JVM s technologií appletů, samozřejmě Flash či Silverlight. WebAssembly se však od těchto technologií poněkud liší, protože se skutečně jedná pouze o specifikaci virtuálního stroje (instrukce + jejich chování); nejedná se zde o snahu vytvořit zcela novou platformu s vlastním vykreslovacím engine či s vlastními knihovnami. V případě WebAssembly se počítá s tím, že se budou využívat již existující a ověřené části prohlížečů, zejména celý DOM a základní funkce pro práci s ním. To je podle mého názoru lepší a především praktičtější přístup než snaha o nové objevování kola.

2. Způsob využití různých programovacích jazyků na WWW stránkách

JavaScript is an assembly language. The JavaScript + HTML generate is like a .NET assembly. The browser can execute it, but no human should really care what's there.
Erik Meijer

Pravděpodobně nejjednodušší a nejpřímější cestou podpory nového programovacího jazyka ve webových prohlížečích je integrace jeho interpretru přímo do prohlížeče popř. použití pluginu s tímto interpretrem. Ovšem i přes snahy některých vývojářů a softwarových společností o začlenění dalších skriptovacích jazyků do webových prohlížečů (z historického pohledu se jednalo minimálně o Tcl, VBScript, Dart v Dartiu apod.) je patrné, že v současnosti je jediným široce akceptovaným skriptovacím jazykem na straně webového prohlížeče pouze JavaScript se všemi přednostmi a zápory, které tato monokultura přináší. To však v žádném případě neznamená, že by se ty části aplikace, které mají být spouštěny na straně klienta, musely psát pouze v JavaScriptu, jenž nemusí zdaleka všem vývojářům vyhovovat, ať již z objektivních či ze subjektivních příčin (například kvůli dosti zvláštně navrženému typovému systému, který ovšem umožnil realizovat například JSF*ck).

V relativně nedávné minulosti proto vzniklo a pořád ještě vzniká mnoho projektů, jejichž cílem je umožnit tvorbu webových aplikací pro prohlížeč v jiných programovacích jazycích. Zdrojové kódy je pak nutné nějakým způsobem zpracovat (transpřeložit, přeložit, …) takovým způsobem, aby je bylo možné ve webovém prohlížeči spustit. Možností je hned několik – lze použít plugin (velmi problematické a dnes značně nepopulární řešení), transpřekladač do JavaScriptu či virtuální stroj popř. interpret daného jazyka implementovaný opět v JavaScriptu. Právě posledními dvěma zmíněnými možnostmi se budeme zabývat v navazujících kapitolách.

3. Transpřekladače do JavaScriptu

Jednu z dnes velmi populárních technik umožňujících použití prakticky libovolného programovacího jazyka pro tvorbu aplikací běžících na straně webového prohlížeče, představuje použití takzvaných transcompilerů (source-to-source compiler) zajišťujících překlad programu napsaného ve zdrojovém programovacím jazyce do funkčně identického programu napsaného v JavaScriptu (někdy se setkáme i s označením transpiler). Transpřekladač se většinou spouští jen jednou na vývojářském počítači, samotní klienti již mají k dispozici JavaScriptový kód.

Poznámka: ve skutečnosti není technologie transpřekladačů žádným způsobem svázána právě s JavaScriptem, protože se používala (a používá) i pro další manipulace se zdrojovými kódy.

Existuje však i druhá možnost, kdy je samotný transpřekladač naprogramován v JavaScriptu a spouštěn přímo ve webovém prohlížeči klientů. Oba přístupy mají své přednosti, ale pochopitelně i nějaké zápory (například tvůrci uzavřených aplikací pravděpodobně budou upřednostňovat první možnost, protože výstupy transcompilerů jsou většinou dosti nečitelné; dokonce by mohla snaha o prozkoumání kódu spadat pod reverse engineering). Druhá možnost je relativně elegantní v tom ohledu, že se z pohledu programátora webové aplikace skutečně jedná o nový programovací jazyk, který je jakoby přímo zpracováván prohlížečem na stejné úrovni jako JavaScript. Příkladem může být kombinace JavaScriptu a jazyka WISP:

<html>
    <head>
        <title>Jazyk WISP na webové stránce</title>
        <meta http-equiv="content-type" content="text/html; charset=utf-8">
 
        <script src="wisp.min.js" type="application/javascript">
        </script>
 
        <script type="application/wisp">
        (print "část naprogramovaná ve WISPu")
        </script>
 
        <script type="application/javascript">
        console.log("část naprogramovaná v JavaScriptu")
        </script>
 
    </head>
 
    <body>
    </body>
</html>

4. Příklady existujících transpřekladačů do JavaScriptu

Z praxe můžeme uvést například následující projekty založené na transpřekladači. Některé z nich je možné použít přímo v prohlížeči, jiné provádí překlad do JavaScriptu na příkazovém řádku, existují i kombinace obou způsobů (opět viz WISP podporující oba režimy):

:
# Jazyk Poznámka
1 CoffeeScript přidání syntaktického cukru do JavaScriptu
2 JSweet překlad programů z Javy do JavaScriptu popř. do TypeScriptu
3 Transcrypt překlad Pythonu do JavaScriptu (tomuto nástroji se budeme věnovat v dalším článku)
4 ClojureScript překlad aplikací psaných v Clojure do JavaScriptu
5 Kaffeine rozšíření JavaScriptu o nové vlastnosti
6 RedScript jazyk inspirovaný Ruby
7 GorillaScript další rozšíření JavaScriptu
8 ghcjs transpřekladač pro fanoušky programovacího jazyka Haskell
9 wisp zjednodušená a dnes již nevyvíjená varianta ClojureScriptu
10 Babel překlad novějších variant JavaScript (ES2015) a TypeScriptu do zvolené (starší) verze JavaScriptu, stále populární, i přesto, že nové prohlížeče ES2015 podporují
11 GopherJS překladač programů naprogramovaných v jazyce Go do JavaScriptu
Poznámka: seznam všech (či alespoň většiny) známých transpřekladačů do JavaScriptu naleznete například na stránce https://github.com/jashke­nas/coffeescript/wiki/List-of-languages-that-compile-to-JS, i když je nutné varovat, že některé projekty (kromě výše zmíněných) jsou v dosti špatném stavu.

5. Nástroj Emscripten

Další alternativní technologii, která mi osobně přijde velmi zajímavá a v budoucnu možná i přelomová, představují transpřekladače provádějící překlad z bajtkódu či mezikódu do JavaScriptu (vstupem zde tedy není zdrojový kód v nějakém lidsky čitelném programovacím jazyku, ale většinou binárně reprezentovaný výsledek předchozího překladu). Příkladem tohoto typu transpřekladače je především nástroj Emscripten [1] umožňující překlad kódu z libovolného jazyka podporovaného LLVM (Rust, C, C++, Objective C, D, Ada, Fortran atd.) do JavaScriptu. Podívejme se nyní ve stručnosti na kroky, které je zapotřebí provést proto, aby se původní zdrojový kód napsaný například v Céčku, mohl nějakým způsobem spustit ve webovém prohlížeči:

  1. Na vstupu celého procesu je program napsaný v céčku
  2. Nejprve je proveden překlad pomocí clang do mezikódu LLVM (LLVM Intermediate Representation)
  3. Následně je zavolán Fastcomp (jádro překladače Emscriptenu) pro překlad mezikódu z předchozího kroku do JavaScriptu
  4. Výsledný JavaScriptový zdrojový kód je možné využít různými způsoby (node.js na serveru, na WWW stránce atd.)
Poznámka: poslední překlad (do JavaScriptu) generuje kód kompatibilní s asm.js, tj. používá se zde cíleně omezená podmnožina konstrukcí JavaScriptu. Více informací o asm.js naleznete například na stránkách https://developer.mozilla.org/en-US/docs/Games/Tools/asm.js a http://asmjs.org/ (původní verze specifikace). Alternativně může být výsledkem i bajtkód pro WebAssembly, o čemž se zmíníme v dalších kapitolách.

6. Virtuální stroj naprogramovaný v JavaScriptu

Právě projekt Emscripten zmíněný v předchozí kapitole do značné míry usnadnil další způsob zajištění běhu programů napsaných v různých programovacích jazycích ve webovém prohlížeči. Pokud je totiž možné přeložit jakýkoli program napsaný v jazycích C či C++ do JavaScriptu (samozřejmě za předpokladu, že se vhodným způsobem budou emulovat použité knihovní funkce), proč by nebylo možné do JavaScriptu rovnou přeložit celý virtuální stroj používaný daným programovacím jazykem? Samozřejmě to možné je, a to zejména v těch případech, kdy je překládaný virtuální stroj (alespoň z dnešního pohledu) malý, což je příklad VM pro jazyk Lua, tak i například poněkud většího virtuálního stroje Pythonu (.NET resp. CLR či Java VM už je pochopitelně mnohem těžší oříšek).

Překladem VM do JavaScriptu získáme poměrně mnoho výhod, zejména pak možnost mít přímo v HTML stránkách původní zdrojové kódy (Lua, Python atd.) a nikoli nečitelný výstup z transpřekladačů. Za tento postup však také zaplatíme, zejména pomalejším během aplikací v porovnání s nativní VM. V praxi se může jednat o výkonnostní propad zhruba na polovinu, což ovšem v mnoha aplikacích vůbec není tak špatný výsledek.

Příkladem takového typu virtuálního stroje je LuaJS.

7. WebAssembly

Konečně se dostáváme k technologii WebAssembly. Již v úvodní kapitole jsme si řekli, že se v první řadě jedná o specifikaci virtuálního stroje, především jeho struktury (je založen na zásobníku operandů, podobně jako například virtuální stroj Javy) a taktéž ze specifikace jeho instrukčního souboru. Důležité přitom je, že současně používaná varianta WebAssembly je skutečně dosti nízkoúrovňová, takže neobsahuje například ani podporu pro automatickou správu paměti a i specifikace runtime je dosti minimalistická. To je ovšem v mnoha ohledech výhoda, protože u jazyků typu C, C++ či Rust není automatická správa paměti relevantní a jejich runtime je malý a naopak u jazyků typu Go je správce paměti přímo součástí runtime (zjednodušeně řečeno knihoven, které jsou slinkovány a tvoří výsledný bajtkód předávaný WebAssembly). Správa paměti řízená přímo WebAssembly je prozatím ve fázi vývoje a dnes ji nebudeme potřebovat.

Již v předchozím odstavci jsme se zmínili o problematice runtime. Virtuální stroj WebAssembly akceptuje soubory s MIME typem application/wasm, které by měly obsahovat jak vlastní kód aplikace přeložený do bajtkódu, tak i veškerý podpůrný kód. V případě jazyka Go to konkrétně znamená, že soubory s přeloženou aplikací jsou poměrně velké. I ta nejjednodušší aplikace přeložená do WebAssembly má velikost cca 1300 kB, protože je ve výsledku obsažený celý potřebný runtime i automatický správce paměti.

Velikost výsledného souboru se zvětšujícím se zdrojovým kódem aplikace dále již roste jen pomalu, ovšem i přesto je nutné počítat s tím, že první načtení a inicializace bajtkódu může být pomalá (mobilní připojení atd.) a může se tedy jednat o jeden z důvodů, proč WebAssembly a Go v praxi spíše nepoužívat. Na druhou stranu si představme například aplikaci typu „webové IDE“ nebo Google Docs – zde se doba nutná pro přenos cca jednoho či dvou megabajtů runtime pravděpodobně ztratí mezi stovkami kilobajtů dalších souborů (navíc se vlastně mnohdy mohou odstranit všechny JavaScriptové knihovny); u podobných aplikací se navíc očekává, že budou spuštěny delší dobu, na rozdíl od běžných webových prezentací.

8. Jednoduchý projekt přeložený do WebAssembly

Nyní si ukažme, jakým způsobem se vlastně překládá projekt naprogramovaný v jazyce Go do bajtkódu kompatibilního s WebAssembly a jak se výsledný bajtkód stane součástí webové aplikace. Samotný projekt je tak triviální, že si možná ani nezaslouží označení „projekt“. Jeho zdrojový kód totiž vypadá následovně:

package main
 
import "fmt"
 
func main() {
        fmt.Println("Hello World!")
}

Běžný překlad by se provedl známým způsobem:

$ go build

Přičemž výsledkem by byl nativní spustitelný soubor pro použitou architekturu mikroprocesoru a operační systém.

Překlad ovšem můžeme provést i se specifikací jiné architektury, konkrétně architektury wasm (ostatně virtuální stroj se zásobníkem a instrukční sadou se vlastně nijak zásadně neliší od specifikace mikroprocesoru):

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

V tomto případě je výsledkem překladu soubor hello.wasm, který obsahuje bajtkód výše zmíněného projektu i příslušný runtime.

Poznámka: výsledný soubor hello.wasm svou velikostí přesahuje dva megabajty. To je v kontextu webových aplikací poměrně veliký objem a je do určité míry způsobem tím, že importujeme balíček fmt. V případě, že se namísto fmt.Println použije standardní funkce println, sníží se velikost hello.wasm o celý jeden megabajt!

9. Zařazení bajtkódu do webové stránky

Zbývá nám ještě zařídit zařazení a inicializaci bajtkódu na webové stránce. To není úplně triviální, na rozdíl od skriptů naprogramovaných v JavaScriptu, které stačí pouze přidat do tagu <script>. V případě WebAssembly potřebujeme podpůrný soubor wasm_exec.js, který získáte buď z uvedené adresy vedoucí do repositáře na GitHubu nebo přímo z adresáře, v němž je nainstalován jazyk Go. Dále si povšimněte inicializace objektu typu Go. Tento objekt se používá ve chvíli, kdy je nutné zajistit kooperaci mezi částí aplikace naprogramované v Go a přeložené do WebAssembly s částí vytvořenou v JavaScriptu (to si ukážeme v závěru článku). HTML stránka s inicializací WebAssembly může vypadat takto:

<html>
    <head>
        <meta charset="utf-8">
        <script src="wasm_exec.js"></script>
        <script>
            const go = new Go();
            WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
                    go.run(result.instance);
            });
        </script>
    </head>
    <body></body>
</html>

10. Server, který bude korektně pracovat se soubory s MIME typem „application/wasm“

Zbývá nám vyřešit ještě jeden problém – jak vlastně otevřít HTML stránku, v níž je umístěn odkaz na bajtkód, který má být spuštěn ve WebAssembly. Mohlo by se zdát, že se jedná o triviální úkol – prostě stránku otevřeme přímo ze souboru a prohlížeč si po jejím zparsování ostatní potřebné soubory načte automaticky sám. Toto řešení je sice funkční v případě obrázků či dalšího multimediálního obsahu, ovšem už v případě JavaScriptu nemusí vždy fungovat (tato funkcionalita může být zakázána) a nebude funkční ani v případě WebAssembly. Prohlížeč totiž v tomto případě striktně požaduje, aby mu byl předán obsah s MIME typem „application/wasm“. To zajistíme spuštěním vlastního HTTP serveru, který je v případě použití programovacího jazyka Go implementován téměř triviálním způsobem:

// HTTP server vracející statický obsah
 
package main
 
import (
        "net/http"
)
 
func main() {
        http.Handle("/", http.FileServer(http.Dir("")))
        http.ListenAndServe(":8000", nil)
}

Tento HTTP server spustíme přímo v adresáři, kde se nachází i přeložené soubory „.wasm“:

$ go run file_server.go

Předností HTTP serveru naprogramovaného přímo v jazyce Go s využitím základních balíčků ze standardní knihovny je fakt, že tento server správně rozpoznává koncovky souborů „.wasm“ a správně těmto souborům přiřazuje MIME typ (což je nutné u jiných HTTP serverů mnohdy ručně doplňovat). Ostatně o této funkcionalitě se můžeme velmi snadno přesvědčit, například stažením hlavičky nástrojem typu curl:

$ curl -I localhost:8000/hello.wasm
 
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 2424424
Content-Type: application/wasm
Last-Modified: Sat, 30 Mar 2019 18:27:52 GMT
Date: Sat, 30 Mar 2019 18:45:08 GMT

Obrázek 1: Webový server dodá prohlížeči postupně jak HTML stránku, tak i pomocný JavaScriptový soubor a soubor s bajtkódem WebAssembly.

Poznámka: po spuštění serveru otevřete HTML stránku demonstračního příkladu a v konzoli (Ctrl+Shift+K) byste měli uvidět zprávu vytištěnou z bajtkódu.

Obrázek 2: V konzoli by se měla objevit zpráva vytištěná z WebAssembly.

11. WebAssembly a DOM

V praxi se setkáme s nutností manipulace s DOMem celé HTML stránky popř. s DOMem souboru typu SVG. I tato možnost je pochopitelně na straně jazyka Go podporována, a to díky tomu, že balíček syscall/js zpřístupňuje programátorům objekt Global, který v JavaScriptu odpovídá objektu window (minimálně pokud se bavíme o HTML stránkách, nikoli o node.js):

window := js.Global()

Přes tento objekt můžeme přistoupit k dalšímu známému objektu document s obsahem HTML stránky:

document := window.Get("document")

Následně již můžeme volat metody objektu document, ovšem nepřímo přes:

document.Call("jméno_JS_metody", parametry)

popř. měnit atributy s využitím:

document.Set("jméno_atributu", hodnota)

12. Změna obsahu vybrané značky

Podívejme se nyní, jakým způsobem můžeme změnit obsah značky s identifikátorem „header“. V JavaScriptu by se jednalo o tento kód:

element = document.getElementById("header");
element.innerHTML = "foobar";

V jazyce Go a s využitím balíčku syscall/js by se podobná funkcionalita naprogramovala následujícím způsobem:

package main
 
import (
        "syscall/js"
)
 
func main() {
        println("started")
 
        window := js.Global()
        document := window.Get("document")
        element := document.Call("getElementById", "header")
 
        element.Set("innerHTML", "foobar")
 
        println("finished")
}

Ve zdrojovém kódu HTML stránky si povšimněte elementu s ID nastaveným na „header“:

<html>
    <head>
        <meta charset="utf-8">
        <script src="wasm_exec.js"></script>
        <script>
            const go = new Go();
            WebAssembly.instantiateStreaming(fetch("dom_manipulation.wasm"), go.importObject).then((result) => {
                    go.run(result.instance);
            });
        </script>
    </head>
    <body>
        <h1 id="header">nic</h2>
    </body>
</html>

Obrázek 3: Změna elementu na HTML stránce.

13. Přidání nových značek do HTML stránky

Podobným způsobem můžeme do HTML stránky přidat další značky, což je ukázáno na dalším demonstračním příkladu, po jehož inicializaci by se do stránky měla přidat tabulka s hodnotami faktoriálů čísel od nuly do deseti. Povšimněte si, že nyní voláme metodu document.createElement() a taktéž document.body.appendChild():

package main
 
import (
        "fmt"
        "syscall/js"
)
 
func Factorial(n int64) int64 {
        switch {
        case n < 0:
                return 1
        case n == 0:
                return 1
        default:
                return n * Factorial(n-1)
        }
}
 
func main() {
        println("started")
 
        window := js.Global()
        document := window.Get("document")
        element := document.Call("getElementById", "header")
 
        element.Set("innerHTML", "foobar")
 
        for n := int64(0); n <= 10; n++ {
                f := Factorial(n)
                message := fmt.Sprintf("%2d! = %d", n, f)
                pre := document.Call("createElement", "pre")
                pre.Set("innerHTML", message)
                document.Get("body").Call("appendChild", pre)
        }
 
        println("finished")
}

Obrázek 4: Přidání nových elementů na HTML stránku.

14. Kreslení do 2D canvasu

Poměrně často se aplikace překládané do WebAssembly používají pro kreslení 2D či 3D grafiky, typicky s přímým či nepřímým využitím WebGL. Tomuto zajisté zajímavému tématu se však dnes věnovat nebudeme. Namísto toho si ukážeme, jak může aplikace naprogramovaná v Go vytvořit 2D canvas (HTML 5) a kreslit do něj. Nejdříve si zpřístupníme objekt document, což již známe:

window := js.Global()
document := window.Get("document")

Následně do dokumentu (HTML stránky) vložíme nový canvas se zadanou velikostí:

canvas := document.Call("createElement", "canvas")
canvas.Set("height", CanvasWidth)
canvas.Set("width", CanvasHeight)
document.Get("body").Call("appendChild", canvas)

Získáme kontext pro kreslení:

context2d := canvas.Call("getContext", "2d")

A následně například vybarvíme celou plochu canvasu světle šedou barvou:

context2d.Set("fillStyle", "#c0c0c0")
context2d.Call("fillRect", 0, 0, CanvasWidth, CanvasHeight)

Úplný zdrojový kód příkladu s HTML canvasem vypadá následovně:

package main
 
import (
        "syscall/js"
)
 
func main() {
        const CanvasWidth = 256
        const CanvasHeight = 256
 
        println("started")
 
        window := js.Global()
        document := window.Get("document")
 
        canvas := document.Call("createElement", "canvas")
        canvas.Set("height", CanvasWidth)
        canvas.Set("width", CanvasHeight)
        document.Get("body").Call("appendChild", canvas)
 
        context2d := canvas.Call("getContext", "2d")
        context2d.Set("fillStyle", "#c0c0c0")
        context2d.Call("fillRect", 0, 0, CanvasWidth, CanvasHeight)
 
        context2d.Set("fillStyle", "yellow")
        context2d.Call("fillRect", 10, 10, CanvasWidth-20, CanvasHeight-20)
 
        println("finished")
}

Obrázek 5: Vykreslení na HTML 5 canvas přes WebAssembly.

15. Komunikace mezi Go a JavaScriptem

Nakonec si ukážeme nejsložitější příklad, v němž je ukázána komunikace mezi Go a JavaScriptem. V tomto příkladu vytvoříme pomocnou funkci naprogramovanou v Go, která bude volatelná z JavaScriptu. Povšimněte si, že se této funkci předává řez libovolných JavaScriptových hodnot:

func PrintHello(inputs []js.Value) {
        window := js.Global()
        document := window.Get("document")
        element := document.Call("getElementById", "header")
 
        element.Set("innerHTML", "Hello from Go")
}

Tuto funkci je nutné zaregistrovat, aby ji viděl i JavaScriptový engine, a to pod jménem „printHello“:

js.Global().Set("printHello", js.NewCallback(PrintHello))

To však není vše – dále musíme zajistit, aby se hlavní funkce Go (main) automaticky neukončila, protože by JavaScriptová část nemohla přistupovat k objektu Go. To se provede s využitím kanálu s nulovou kapacitou, z něhož se pokusíme přečíst hodnotu. Tato operace je blokující a nikdy neskončí:

func main() {
        println("started")
        c := make(chan bool)
        js.Global().Set("printHello", js.NewCallback(PrintHello))
        <-c
        println("finished")
}

Část naprogramovaná v Go vypadá následovně:

package main
 
import (
        "syscall/js"
)
 
func PrintHello(inputs []js.Value) {
        window := js.Global()
        document := window.Get("document")
        element := document.Call("getElementById", "header")
 
        element.Set("innerHTML", "Hello from Go")
}
 
func main() {
        println("started")
        c := make(chan bool)
        js.Global().Set("printHello", js.NewCallback(PrintHello))
        <-c
        println("finished")
}

Část naprogramovaná v JavaScriptu je již jednoduchá. Povšimněte si, že bez problémů voláme funkci printHello(), která není nikde na JavaScriptové straně deklarována:

const go = new Go();
WebAssembly.instantiateStreaming(fetch("js_interop.wasm"), go.importObject).then((result) => {
        go.run(result.instance);
        printHello();
});

Obrázek 6: Výsledek komunikace mezi jazyky Go a JavaScript.

16. Překlad programů naprogramovaných v Go do JavaScriptu

Příště si ukážeme alternativní možnost spouštění aplikací naprogramovaných v Go ve webových prohlížečích. Jedná se o projekt GopherJS, viz též https://github.com/gopher­js/gopherjs/blob/master/doc/pac­kages.md popř. „pískoviště“, v němž si můžete základní funkcionalitu otestovat. Toto pískoviště naleznete na adrese https://gopherjs.github.i­o/playground/.

17. Repositář s demonstračními příklady

Zdrojové kódy všech dnes popsaných demonstračních příkladů byly uloženy do Git repositáře, který je dostupný na adrese https://github.com/tisnik/go-root (stále na GitHubu :-). V případě, že nebudete chtít klonovat celý repositář (ten je ovšem – alespoň prozatím – velmi malý, dnes má přibližně jeden megabajt), můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující tabulce:

# Soubor Popis Cesta
1 hello.go zdrojový kód prvního příkladu: výpis zprávy na konzoli webového prohlížeče https://github.com/tisnik/go-root/blob/master/article19/hello.go
1 hello.html HTML stránka s kódem pro načtení prvního příkladu do prohlížeče https://github.com/tisnik/go-root/blob/master/article19/he­llo.html
1 build_hello skript pro překlad prvního příkladu do bajtkódu WebAssembly https://github.com/tisnik/go-root/blob/master/article19/bu­ild_hello
       
2 dom_manipulation.go zdrojový kód druhého příkladu: manipulace s DOMem https://github.com/tisnik/go-root/blob/master/article19/dom_ma­nipulation.go
2 dom_manipulation.html HTML stránka s kódem pro načtení druhého příkladu do prohlížeče https://github.com/tisnik/go-root/blob/master/article19/dom_ma­nipulation.html
2 build_dom_manipulation skript pro překlad druhého příkladu do bajtkódu WebAssembly https://github.com/tisnik/go-root/blob/master/article19/bu­ild_dom_manipulation
       
3 dom_add_element.go zdrojový kód třetího příkladu: přidání elementů do DOMu https://github.com/tisnik/go-root/blob/master/article19/dom_ad­d_element.go
3 dom_add_element.html HTML stránka s kódem pro načtení třetího příkladu do prohlížeče https://github.com/tisnik/go-root/blob/master/article19/dom_ad­d_element.html
3 build_add_element skript pro překlad třetího příkladu do bajtkódu WebAssembly https://github.com/tisnik/go-root/blob/master/article19/bu­ild_add_element
       
4 draw_into_canvas.go zdrojový kód čtvrtého příkladu: kreslení do canvasu https://github.com/tisnik/go-root/blob/master/article19/draw_in­to_canvas.go
4 draw_into_canvas.html HTML stránka s kódem pro načtení čtvrtého příkladu do prohlížeče https://github.com/tisnik/go-root/blob/master/article19/draw_in­to_canvas.html
4 build_draw_into_canvas skript pro překlad čtvrtého příkladu do bajtkódu WebAssembly https://github.com/tisnik/go-root/blob/master/article19/bu­ild_draw_into_canvas
       
5 js_interop.go zdrojový kód pátého příkladu: komunikace s JavaScriptem https://github.com/tisnik/go-root/blob/master/article19/js_in­terop.go
5 js_interop.html HTML stránka s kódem pro načtení pátého příkladu do prohlížeče https://github.com/tisnik/go-root/blob/master/article19/js_in­terop.html
5 build_js_interop skript pro překlad pátého příkladu do bajtkódu WebAssembly https://github.com/tisnik/go-root/blob/master/article19/bu­ild_js_interop

18. Pomocné soubory použité demonstračními příklady

Pomocné soubory jsou taktéž uloženy v repositáři https://github.com/tisnik/go-root:

# Soubor Popis Cesta
1 file_server.go implementace HTTP serveru popsaná v desáté kapitole https://github.com/tisnik/go-root/blob/master/article19/fi­le_server.go
2 file_server skript pro spuštění HTTP serveru https://github.com/tisnik/go-root/blob/master/article19/fi­le_server
       
3 wasm_exec.js inicializace WebAssembly (získáno z instalace Go) https://github.com/tisnik/go-root/blob/master/article19/was­m_exec.js
       
4 clean skript pro vymazání všech vygenerovaných .wasm souborů https://github.com/tisnik/go-root/blob/master/article19/clean

19. Odkazy na články s tématem WebAssembly

  1. WebAssembly
    https://webassembly.org/
  2. WebAssembly na Wiki Golangu
    https://github.com/golang/go/wi­ki/WebAssembly
  3. The future of WebAssembly – A look at upcoming features and proposals
    https://blog.scottlogic.com/2018/07/20/wasm-future.html
  4. Writing WebAssembly By Hand
    https://blog.scottlogic.com/2018/04/26/we­bassembly-by-hand.html
  5. WebAssembly Specification
    https://webassembly.github­.io/spec/core/index.html
  6. Index of Instructions
    https://webassembly.github­.io/spec/core/appendix/in­dex-instructions.html
  7. The WebAssembly Binary Toolkit
    https://github.com/WebAssembly/wabt
  8. Will WebAssembly replace JavaScript? Or Will WASM Make JavaScript More Valuable in Future?
    https://dev.to/vaibhavshah/will-webassembly-replace-javascript-or-will-wasm-make-javascript-more-valuable-in-future-5c6e
  9. Roadmap (pro WebAssemly)
    https://webassembly.org/roadmap/
  10. S-expression
    https://en.wikipedia.org/wiki/S-expression
  11. Understanding WebAssembly text format
    https://developer.mozilla.org/en-US/docs/WebAssembly/Under­standing_the_text_format
  12. Learning Golang through WebAssembly – Part 1, Introduction and setup
    https://www.aaron-powell.com/posts/2019–02–04-golang-wasm-1-introduction/
  13. Learning Golang through WebAssembly – Part 2, Writing your first piece of Go
    https://www.aaron-powell.com/posts/2019–02–05-golang-wasm-2-writing-go/
  14. Learning Golang through WebAssembly – Part 3, Interacting with JavaScript from Go
    https://www.aaron-powell.com/posts/2019–02–06-golang-wasm-3-interacting-with-js-from-go/
  15. Golang webassembly (wasm) testing with examples
    https://jelinden.fi/blog/golang-webassembly-wasm-testing-with-examples/qB7Tb2KmR
  16. Use Cases (of WebAssembly)
    https://webassembly.org/docs/use-cases/
  17. Tabulka s podporou WebAssembly v různých prohlížečích
    https://caniuse.com/#feat=wasm

20. Odkazy na Internetu

  1. Podpora canvasu ve webových prohlížečích
    https://caniuse.com/#feat=canvas
  2. Dokumentace k balíčku oglematchers
    https://godoc.org/github.com/ja­cobsa/oglematchers
  3. JSFuck
    http://www.jsfuck.com/
  4. Balíček oglematchers
    https://github.com/jacobsa/o­glematchers
  5. Dokumentace k balíčku ogletest
    https://godoc.org/github.com/ja­cobsa/ogletest
  6. Balíček ogletest
    https://github.com/jacobsa/ogletest
  7. Dokumentace k balíčku assert
    https://godoc.org/github.com/stret­chr/testify/assert
  8. Testify – Thou Shalt Write Tests
    https://github.com/stretchr/testify/
  9. Package testing
    https://golang.org/pkg/testing/
  10. Golang basics – writing unit tests
    https://blog.alexellis.io/golang-writing-unit-tests/
  11. An Introduction to Programming in Go / Testing
    https://www.golang-book.com/books/intro/12
  12. An Introduction to Testing in Go
    https://tutorialedge.net/golang/intro-testing-in-go/
  13. Advanced Go Testing Tutorial
    https://tutorialedge.net/go­lang/advanced-go-testing-tutorial/
  14. GoConvey
    http://goconvey.co/
  15. Testing Techniques
    https://talks.golang.org/2014/tes­ting.slide
  16. 5 simple tips and tricks for writing unit tests in #golang
    https://medium.com/@matryer/5-simple-tips-and-tricks-for-writing-unit-tests-in-golang-619653f90742
  17. Afinní transformace
    https://cs.wikibooks.org/wi­ki/Geometrie/Afinn%C3%AD_tran­sformace_sou%C5%99adnic
  18. package gg
    https://godoc.org/github.com/fo­gleman/gg
  19. Generate an animated GIF with Golang
    http://tech.nitoyon.com/en/blog/2016/01/07/­go-animated-gif-gen/
  20. Generate an image programmatically with Golang
    http://tech.nitoyon.com/en/blog/2015/12/31/­go-image-gen/
  21. The Go image package
    https://blog.golang.org/go-image-package
  22. Balíček draw2D: 2D rendering for different output (raster, pdf, svg)
    https://github.com/llgcode/draw2d
  23. Draw a rectangle in Golang?
    https://stackoverflow.com/qu­estions/28992396/draw-a-rectangle-in-golang
  24. YAML
    https://yaml.org/
  25. edn
    https://github.com/edn-format/edn
  26. Smile
    https://github.com/FasterXML/smile-format-specification
  27. Protocol-Buffers
    https://developers.google.com/protocol-buffers/
  28. Marshalling (computer science)
    https://en.wikipedia.org/wi­ki/Marshalling_(computer_sci­ence)
  29. Unmarshalling
    https://en.wikipedia.org/wi­ki/Unmarshalling
  30. Introducing JSON
    http://json.org/
  31. Package json
    https://golang.org/pkg/encoding/json/
  32. The Go Blog: JSON and Go
    https://blog.golang.org/json-and-go
  33. Go by Example: JSON
    https://gobyexample.com/json
  34. Writing Web Applications
    https://golang.org/doc/articles/wiki/
  35. Golang Web Apps
    https://www.reinbach.com/blog/golang-webapps-1/
  36. Build web application with Golang
    https://legacy.gitbook.com/bo­ok/astaxie/build-web-application-with-golang/details
  37. Golang Templates – Golang Web Pages
    https://www.youtube.com/wat­ch?v=TkNIETmF-RU
  38. Simple Golang HTTPS/TLS Examples
    https://github.com/denji/golang-tls
  39. Playing with images in HTTP response in golang
    https://www.sanarias.com/blog/1214Pla­yingwithimagesinHTTPrespon­seingolang
  40. MIME Types List
    https://www.freeformatter.com/mime-types-list.html
  41. Go Mutex Tutorial
    https://tutorialedge.net/golang/go-mutex-tutorial/
  42. Creating A Simple Web Server With Golang
    https://tutorialedge.net/go­lang/creating-simple-web-server-with-golang/
  43. Building a Web Server in Go
    https://thenewstack.io/building-a-web-server-in-go/
  44. How big is the pipe buffer?
    https://unix.stackexchange­.com/questions/11946/how-big-is-the-pipe-buffer
  45. How to turn off buffering of stdout in C
    https://stackoverflow.com/qu­estions/7876660/how-to-turn-off-buffering-of-stdout-in-c
  46. setbuf(3) – Linux man page
    https://linux.die.net/man/3/setbuf
  47. setvbuf(3) – Linux man page (stejný obsah jako předchozí stránka)
    https://linux.die.net/man/3/setvbuf
  48. Select waits on a group of channels
    https://yourbasic.org/golang/select-explained/
  49. Rob Pike: Simplicity is Complicated (video)
    http://www.golang.to/posts/dotgo-2015-rob-pike-simplicity-is-complicated-youtube-16893
  50. Algorithms to Go
    https://yourbasic.org/
  51. Využití knihovny Pygments (nejenom) pro obarvení zdrojových kódů
    https://www.root.cz/clanky/vyuziti-knihovny-pygments-nejenom-pro-obarveni-zdrojovych-kodu/
  52. Využití knihovny Pygments (nejenom) pro obarvení zdrojových kódů: vlastní filtry a lexery
    https://www.root.cz/clanky/vyuziti-knihovny-pygments-nejenom-pro-obarveni-zdrojovych-kodu-vlastni-filtry-a-lexery/
  53. Go Defer Simplified with Practical Visuals
    https://blog.learngoprogram­ming.com/golang-defer-simplified-77d3b2b817ff
  54. 5 More Gotchas of Defer in Go — Part II
    https://blog.learngoprogramming.com/5-gotchas-of-defer-in-go-golang-part-ii-cc550f6ad9aa
  55. The Go Blog: Defer, Panic, and Recover
    https://blog.golang.org/defer-panic-and-recover
  56. The defer keyword in Swift 2: try/finally done right
    https://www.hackingwithswift.com/new-syntax-swift-2-defer
  57. Swift Defer Statement
    https://andybargh.com/swift-defer-statement/
  58. Modulo operation (Wikipedia)
    https://en.wikipedia.org/wi­ki/Modulo_operation
  59. Node.js vs Golang: Battle of the Next-Gen Languages
    https://www.hostingadvice­.com/blog/nodejs-vs-golang/
  60. The Go Programming Language (home page)
    https://golang.org/
  61. GoDoc
    https://godoc.org/
  62. Go (programming language), Wikipedia
    https://en.wikipedia.org/wi­ki/Go_(programming_langua­ge)
  63. Go Books (kniha o jazyku Go)
    https://github.com/dariubs/GoBooks
  64. The Go Programming Language Specification
    https://golang.org/ref/spec
  65. Go: the Good, the Bad and the Ugly
    https://bluxte.net/musings/2018/04/10/go-good-bad-ugly/
  66. Package builtin
    https://golang.org/pkg/builtin/
  67. Package fmt
    https://golang.org/pkg/fmt/
  68. The Little Go Book (další kniha)
    https://github.com/dariubs/GoBooks
  69. The Go Programming Language by Brian W. Kernighan, Alan A. A. Donovan
    https://www.safaribookson­line.com/library/view/the-go-programming/9780134190570/e­book_split010.html
  70. Learning Go
    https://www.miek.nl/go/
  71. Go Bootcamp
    http://www.golangbootcamp.com/
  72. Programming in Go: Creating Applications for the 21st Century (další kniha o jazyku Go)
    http://www.informit.com/sto­re/programming-in-go-creating-applications-for-the-21st-9780321774637
  73. Introducing Go (Build Reliable, Scalable Programs)
    http://shop.oreilly.com/pro­duct/0636920046516.do
  74. Learning Go Programming
    https://www.packtpub.com/application-development/learning-go-programming
  75. The Go Blog
    https://blog.golang.org/
  76. Getting to Go: The Journey of Go's Garbage Collector
    https://blog.golang.org/ismmkeynote
  77. Go (programovací jazyk, Wikipedia)
    https://cs.wikipedia.org/wi­ki/Go_(programovac%C3%AD_ja­zyk)
  78. Rychle, rychleji až úplně nejrychleji s jazykem Go
    https://www.root.cz/clanky/rychle-rychleji-az-uplne-nejrychleji-s-jazykem-go/
  79. Installing Go on the Raspberry Pi
    https://dave.cheney.net/2012/09/25/in­stalling-go-on-the-raspberry-pi
  80. How the Go runtime implements maps efficiently (without generics)
    https://dave.cheney.net/2018/05/29/how-the-go-runtime-implements-maps-efficiently-without-generics
  81. Niečo málo o Go – Golang (slovensky)
    http://golangsk.logdown.com/
  82. How Many Go Developers Are There?
    https://research.swtch.com/gop­hercount
  83. Most Popular Technologies (Stack Overflow Survery 2018)
    https://insights.stackover­flow.com/survey/2018/#most-popular-technologies
  84. Most Popular Technologies (Stack Overflow Survery 2017)
    https://insights.stackover­flow.com/survey/2017#techno­logy
  85. JavaScript vs. Golang for IoT: Is Gopher Winning?
    https://www.iotforall.com/javascript-vs-golang-iot/
  86. The Go Programming Language: Release History
    https://golang.org/doc/de­vel/release.html
  87. Go 1.11 Release Notes
    https://golang.org/doc/go1.11
  88. Go 1.10 Release Notes
    https://golang.org/doc/go1.10
  89. Go 1.9 Release Notes (tato verze je stále používána)
    https://golang.org/doc/go1.9
  90. Go 1.8 Release Notes (i tato verze je stále používána)
    https://golang.org/doc/go1.8
  91. Go on Fedora
    https://developer.fedorapro­ject.org/tech/languages/go/go-installation.html
  92. Writing Go programs
    https://developer.fedorapro­ject.org/tech/languages/go/go-programs.html
  93. The GOPATH environment variable
    https://tip.golang.org/doc/co­de.html#GOPATH
  94. Command gofmt
    https://tip.golang.org/cmd/gofmt/
  95. The Go Blog: go fmt your code
    https://blog.golang.org/go-fmt-your-code
  96. C? Go? Cgo!
    https://blog.golang.org/c-go-cgo
  97. Spaces vs. Tabs: A 20-Year Debate Reignited by Google’s Golang
    https://thenewstack.io/spaces-vs-tabs-a-20-year-debate-and-now-this-what-the-hell-is-wrong-with-go/
  98. 400,000 GitHub repositories, 1 billion files, 14 terabytes of code: Spaces or Tabs?
    https://medium.com/@hoffa/400–000-github-repositories-1-billion-files-14-terabytes-of-code-spaces-or-tabs-7cfe0b5dd7fd
  99. Gofmt No Longer Allows Spaces. Tabs Only
    https://news.ycombinator.com/i­tem?id=7914523
  100. Why does Go „go fmt“ uses tabs instead of whitespaces?
    https://www.quora.com/Why-does-Go-go-fmt-uses-tabs-instead-of-whitespaces
  101. Interactive: The Top Programming Languages 2018
    https://spectrum.ieee.org/sta­tic/interactive-the-top-programming-languages-2018
  102. Go vs. Python
    https://www.peterbe.com/plog/govspy
  103. PackageManagementTools
    https://github.com/golang/go/wi­ki/PackageManagementTools
  104. A Tour of Go: Type inference
    https://tour.golang.org/basics/14
  105. Go Slices: usage and internals
    https://blog.golang.org/go-slices-usage-and-internals
  106. Go by Example: Slices
    https://gobyexample.com/slices
  107. What is the point of slice type in Go?
    https://stackoverflow.com/qu­estions/2098874/what-is-the-point-of-slice-type-in-go
  108. The curious case of Golang array and slices
    https://medium.com/@hackintoshrao/the-curious-case-of-golang-array-and-slices-2565491d4335
  109. Introduction to Slices in Golang
    https://www.callicoder.com/golang-slices/
  110. Golang: Understanding ‚null‘ and nil
    https://newfivefour.com/golang-null-nil.html
  111. What does nil mean in golang?
    https://stackoverflow.com/qu­estions/35983118/what-does-nil-mean-in-golang
  112. nils In Go
    https://go101.org/article/nil.html
  113. Go slices are not dynamic arrays
    https://appliedgo.net/slices/
  114. Go-is-no-good (nelze brát doslova)
    https://github.com/ksimka/go-is-not-good
  115. Rust vs. Go
    https://news.ycombinator.com/i­tem?id=13430108
  116. Seriál Programovací jazyk Rust
    https://www.root.cz/seria­ly/programovaci-jazyk-rust/
  117. Modern garbage collection: A look at the Go GC strategy
    https://blog.plan99.net/modern-garbage-collection-911ef4f8bd8e
  118. Go GC: Prioritizing low latency and simplicity
    https://blog.golang.org/go15gc
  119. Is Golang a good language for embedded systems?
    https://www.quora.com/Is-Golang-a-good-language-for-embedded-systems
  120. Running GoLang on an STM32 MCU. A quick tutorial.
    https://www.mickmake.com/post/running-golang-on-an-mcu-a-quick-tutorial
  121. Go, Robot, Go! Golang Powered Robotics
    https://gobot.io/
  122. Emgo: Bare metal Go (language for programming embedded systems)
    https://github.com/ziutek/emgo
  123. UTF-8 history
    https://www.cl.cam.ac.uk/~mgk25/uc­s/utf-8-history.txt
  124. Less is exponentially more
    https://commandcenter.blog­spot.com/2012/06/less-is-exponentially-more.html
  125. Should I Rust, or Should I Go
    https://codeburst.io/should-i-rust-or-should-i-go-59a298e00ea9
  126. Setting up and using gccgo
    https://golang.org/doc/install/gccgo
  127. Elastic Tabstops
    http://nickgravgaard.com/elastic-tabstops/
  128. Strings, bytes, runes and characters in Go
    https://blog.golang.org/strings
  129. Datový typ
    https://cs.wikipedia.org/wi­ki/Datov%C3%BD_typ
  130. Seriál o programovacím jazyku Rust: Základní (primitivní) datové typy
    https://www.root.cz/clanky/pro­gramovaci-jazyk-rust-nahrada-c-nebo-slepa-cesta/#k09
  131. Seriál o programovacím jazyku Rust: Vytvoření „řezu“ z pole
    https://www.root.cz/clanky/prace-s-poli-v-programovacim-jazyku-rust/#k06
  132. Seriál o programovacím jazyku Rust: Řezy (slice) vektoru
    https://www.root.cz/clanky/prace-s-vektory-v-programovacim-jazyku-rust/#k05
  133. Printf Format Strings
    https://www.cprogramming.com/tu­torial/printf-format-strings.html
  134. Java: String.format
    https://docs.oracle.com/ja­vase/8/docs/api/java/lang/Strin­g.html#format-java.lang.String-java.lang.Object…-
  135. Java: format string syntax
    https://docs.oracle.com/ja­vase/8/docs/api/java/util/For­matter.html#syntax
  136. Selectors
    https://golang.org/ref/spec#Selectors
  137. Calling Go code from Python code
    http://savorywatt.com/2015/09/18/ca­lling-go-code-from-python-code/
  138. Go Data Structures: Interfaces
    https://research.swtch.com/interfaces
  139. How to use interfaces in Go
    http://jordanorelli.com/pos­t/32665860244/how-to-use-interfaces-in-go
  140. Interfaces in Go (part I)
    https://medium.com/golangspec/in­terfaces-in-go-part-i-4ae53a97479c
  141. Part 21: Goroutines
    https://golangbot.com/goroutines/
  142. Part 22: Channels
    https://golangbot.com/channels/
  143. [Go] Lightweight eventbus with async compatibility for Go
    https://github.com/asaske­vich/EventBus
  144. What about Trait support in Golang?
    https://www.reddit.com/r/go­lang/comments/8mfykl/what_a­bout_trait_support_in_golan­g/
  145. Don't Get Bitten by Pointer vs Non-Pointer Method Receivers in Golang
    https://nathanleclaire.com/blog/2014/08/09/dont-get-bitten-by-pointer-vs-non-pointer-method-receivers-in-golang/
  146. Control Flow
    https://en.wikipedia.org/wi­ki/Control_flow
  147. Structured programming
    https://en.wikipedia.org/wi­ki/Structured_programming
  148. Control Structures
    https://www.golang-book.com/books/intro/5
  149. Control structures – Go if else statement
    http://golangtutorials.blog­spot.com/2011/06/control-structures-if-else-statement.html
  150. Control structures – Go switch case statement
    http://golangtutorials.blog­spot.com/2011/06/control-structures-go-switch-case.html
  151. Control structures – Go for loop, break, continue, range
    http://golangtutorials.blog­spot.com/2011/06/control-structures-go-for-loop-break.html
  152. Single Function Exit Point
    http://wiki.c2.com/?Single­FunctionExitPoint
  153. Entry point
    https://en.wikipedia.org/wi­ki/Entry_point
  154. Why does Go have a GOTO statement?!
    https://www.reddit.com/r/go­lang/comments/kag5q/why_do­es_go_have_a_goto_statemen­t/
  155. Effective Go
    https://golang.org/doc/ef­fective_go.html
  156. GoClipse: an Eclipse IDE for the Go programming language
    http://goclipse.github.io/
  157. GoClipse Installation
    https://github.com/GoClip­se/goclipse/blob/latest/do­cumentation/Installation.md#in­stallation