Obsah
1. Využití WebAssembly z programovacího jazyka Go
2. Způsob využití různých programovacích jazyků na WWW stránkách
3. Transpřekladače do JavaScriptu
4. Příklady existujících a používaných transpřekladačů do JavaScriptu
6. Virtuální stroj naprogramovaný v JavaScriptu
8. Jednoduchý projekt přeložený do WebAssembly
9. Zařazení bajtkódu do webové stránky
10. Server, který bude korektně pracovat se soubory s MIME typem „application/wasm“
12. Změna obsahu vybrané značky
13. Přidání nových značek do HTML stránky
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
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.
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.
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 |
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:
- Na vstupu celého procesu je program napsaný v céčku
- Nejprve je proveden překlad pomocí clang do mezikódu LLVM (LLVM Intermediate Representation)
- Následně je zavolán Fastcomp (jádro překladače Emscriptenu) pro překlad mezikódu z předchozího kroku do JavaScriptu
- 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.)
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.
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.
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/gopherjs/gopherjs/blob/master/doc/packages.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.io/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/hello.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/build_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_manipulation.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_manipulation.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/build_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_add_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_add_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/build_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_into_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_into_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/build_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_interop.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_interop.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/build_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/file_server.go |
2 | file_server | skript pro spuštění HTTP serveru | https://github.com/tisnik/go-root/blob/master/article19/file_server |
3 | wasm_exec.js | inicializace WebAssembly (získáno z instalace Go) | https://github.com/tisnik/go-root/blob/master/article19/wasm_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
- WebAssembly
https://webassembly.org/ - WebAssembly na Wiki Golangu
https://github.com/golang/go/wiki/WebAssembly - The future of WebAssembly – A look at upcoming features and proposals
https://blog.scottlogic.com/2018/07/20/wasm-future.html - Writing WebAssembly By Hand
https://blog.scottlogic.com/2018/04/26/webassembly-by-hand.html - WebAssembly Specification
https://webassembly.github.io/spec/core/index.html - Index of Instructions
https://webassembly.github.io/spec/core/appendix/index-instructions.html - The WebAssembly Binary Toolkit
https://github.com/WebAssembly/wabt - 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 - Roadmap (pro WebAssemly)
https://webassembly.org/roadmap/ - S-expression
https://en.wikipedia.org/wiki/S-expression - Understanding WebAssembly text format
https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format - Learning Golang through WebAssembly – Part 1, Introduction and setup
https://www.aaron-powell.com/posts/2019–02–04-golang-wasm-1-introduction/ - 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/ - 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/ - Golang webassembly (wasm) testing with examples
https://jelinden.fi/blog/golang-webassembly-wasm-testing-with-examples/qB7Tb2KmR - Use Cases (of WebAssembly)
https://webassembly.org/docs/use-cases/ - Tabulka s podporou WebAssembly v různých prohlížečích
https://caniuse.com/#feat=wasm
20. Odkazy na Internetu
- Podpora canvasu ve webových prohlížečích
https://caniuse.com/#feat=canvas - Dokumentace k balíčku oglematchers
https://godoc.org/github.com/jacobsa/oglematchers - JSFuck
http://www.jsfuck.com/ - Balíček oglematchers
https://github.com/jacobsa/oglematchers - Dokumentace k balíčku ogletest
https://godoc.org/github.com/jacobsa/ogletest - Balíček ogletest
https://github.com/jacobsa/ogletest - Dokumentace k balíčku assert
https://godoc.org/github.com/stretchr/testify/assert - Testify – Thou Shalt Write Tests
https://github.com/stretchr/testify/ - Package testing
https://golang.org/pkg/testing/ - Golang basics – writing unit tests
https://blog.alexellis.io/golang-writing-unit-tests/ - An Introduction to Programming in Go / Testing
https://www.golang-book.com/books/intro/12 - An Introduction to Testing in Go
https://tutorialedge.net/golang/intro-testing-in-go/ - Advanced Go Testing Tutorial
https://tutorialedge.net/golang/advanced-go-testing-tutorial/ - GoConvey
http://goconvey.co/ - Testing Techniques
https://talks.golang.org/2014/testing.slide - 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 - Afinní transformace
https://cs.wikibooks.org/wiki/Geometrie/Afinn%C3%AD_transformace_sou%C5%99adnic - package gg
https://godoc.org/github.com/fogleman/gg - Generate an animated GIF with Golang
http://tech.nitoyon.com/en/blog/2016/01/07/go-animated-gif-gen/ - Generate an image programmatically with Golang
http://tech.nitoyon.com/en/blog/2015/12/31/go-image-gen/ - The Go image package
https://blog.golang.org/go-image-package - Balíček draw2D: 2D rendering for different output (raster, pdf, svg)
https://github.com/llgcode/draw2d - Draw a rectangle in Golang?
https://stackoverflow.com/questions/28992396/draw-a-rectangle-in-golang - YAML
https://yaml.org/ - edn
https://github.com/edn-format/edn - Smile
https://github.com/FasterXML/smile-format-specification - Protocol-Buffers
https://developers.google.com/protocol-buffers/ - Marshalling (computer science)
https://en.wikipedia.org/wiki/Marshalling_(computer_science) - Unmarshalling
https://en.wikipedia.org/wiki/Unmarshalling - Introducing JSON
http://json.org/ - Package json
https://golang.org/pkg/encoding/json/ - The Go Blog: JSON and Go
https://blog.golang.org/json-and-go - Go by Example: JSON
https://gobyexample.com/json - Writing Web Applications
https://golang.org/doc/articles/wiki/ - Golang Web Apps
https://www.reinbach.com/blog/golang-webapps-1/ - Build web application with Golang
https://legacy.gitbook.com/book/astaxie/build-web-application-with-golang/details - Golang Templates – Golang Web Pages
https://www.youtube.com/watch?v=TkNIETmF-RU - Simple Golang HTTPS/TLS Examples
https://github.com/denji/golang-tls - Playing with images in HTTP response in golang
https://www.sanarias.com/blog/1214PlayingwithimagesinHTTPresponseingolang - MIME Types List
https://www.freeformatter.com/mime-types-list.html - Go Mutex Tutorial
https://tutorialedge.net/golang/go-mutex-tutorial/ - Creating A Simple Web Server With Golang
https://tutorialedge.net/golang/creating-simple-web-server-with-golang/ - Building a Web Server in Go
https://thenewstack.io/building-a-web-server-in-go/ - How big is the pipe buffer?
https://unix.stackexchange.com/questions/11946/how-big-is-the-pipe-buffer - How to turn off buffering of stdout in C
https://stackoverflow.com/questions/7876660/how-to-turn-off-buffering-of-stdout-in-c - setbuf(3) – Linux man page
https://linux.die.net/man/3/setbuf - setvbuf(3) – Linux man page (stejný obsah jako předchozí stránka)
https://linux.die.net/man/3/setvbuf - Select waits on a group of channels
https://yourbasic.org/golang/select-explained/ - Rob Pike: Simplicity is Complicated (video)
http://www.golang.to/posts/dotgo-2015-rob-pike-simplicity-is-complicated-youtube-16893 - Algorithms to Go
https://yourbasic.org/ - Využití knihovny Pygments (nejenom) pro obarvení zdrojových kódů
https://www.root.cz/clanky/vyuziti-knihovny-pygments-nejenom-pro-obarveni-zdrojovych-kodu/ - 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/ - Go Defer Simplified with Practical Visuals
https://blog.learngoprogramming.com/golang-defer-simplified-77d3b2b817ff - 5 More Gotchas of Defer in Go — Part II
https://blog.learngoprogramming.com/5-gotchas-of-defer-in-go-golang-part-ii-cc550f6ad9aa - The Go Blog: Defer, Panic, and Recover
https://blog.golang.org/defer-panic-and-recover - The defer keyword in Swift 2: try/finally done right
https://www.hackingwithswift.com/new-syntax-swift-2-defer - Swift Defer Statement
https://andybargh.com/swift-defer-statement/ - Modulo operation (Wikipedia)
https://en.wikipedia.org/wiki/Modulo_operation - Node.js vs Golang: Battle of the Next-Gen Languages
https://www.hostingadvice.com/blog/nodejs-vs-golang/ - The Go Programming Language (home page)
https://golang.org/ - GoDoc
https://godoc.org/ - Go (programming language), Wikipedia
https://en.wikipedia.org/wiki/Go_(programming_language) - Go Books (kniha o jazyku Go)
https://github.com/dariubs/GoBooks - The Go Programming Language Specification
https://golang.org/ref/spec - Go: the Good, the Bad and the Ugly
https://bluxte.net/musings/2018/04/10/go-good-bad-ugly/ - Package builtin
https://golang.org/pkg/builtin/ - Package fmt
https://golang.org/pkg/fmt/ - The Little Go Book (další kniha)
https://github.com/dariubs/GoBooks - The Go Programming Language by Brian W. Kernighan, Alan A. A. Donovan
https://www.safaribooksonline.com/library/view/the-go-programming/9780134190570/ebook_split010.html - Learning Go
https://www.miek.nl/go/ - Go Bootcamp
http://www.golangbootcamp.com/ - Programming in Go: Creating Applications for the 21st Century (další kniha o jazyku Go)
http://www.informit.com/store/programming-in-go-creating-applications-for-the-21st-9780321774637 - Introducing Go (Build Reliable, Scalable Programs)
http://shop.oreilly.com/product/0636920046516.do - Learning Go Programming
https://www.packtpub.com/application-development/learning-go-programming - The Go Blog
https://blog.golang.org/ - Getting to Go: The Journey of Go's Garbage Collector
https://blog.golang.org/ismmkeynote - Go (programovací jazyk, Wikipedia)
https://cs.wikipedia.org/wiki/Go_(programovac%C3%AD_jazyk) - Rychle, rychleji až úplně nejrychleji s jazykem Go
https://www.root.cz/clanky/rychle-rychleji-az-uplne-nejrychleji-s-jazykem-go/ - Installing Go on the Raspberry Pi
https://dave.cheney.net/2012/09/25/installing-go-on-the-raspberry-pi - 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 - Niečo málo o Go – Golang (slovensky)
http://golangsk.logdown.com/ - How Many Go Developers Are There?
https://research.swtch.com/gophercount - Most Popular Technologies (Stack Overflow Survery 2018)
https://insights.stackoverflow.com/survey/2018/#most-popular-technologies - Most Popular Technologies (Stack Overflow Survery 2017)
https://insights.stackoverflow.com/survey/2017#technology - JavaScript vs. Golang for IoT: Is Gopher Winning?
https://www.iotforall.com/javascript-vs-golang-iot/ - The Go Programming Language: Release History
https://golang.org/doc/devel/release.html - Go 1.11 Release Notes
https://golang.org/doc/go1.11 - Go 1.10 Release Notes
https://golang.org/doc/go1.10 - Go 1.9 Release Notes (tato verze je stále používána)
https://golang.org/doc/go1.9 - Go 1.8 Release Notes (i tato verze je stále používána)
https://golang.org/doc/go1.8 - Go on Fedora
https://developer.fedoraproject.org/tech/languages/go/go-installation.html - Writing Go programs
https://developer.fedoraproject.org/tech/languages/go/go-programs.html - The GOPATH environment variable
https://tip.golang.org/doc/code.html#GOPATH - Command gofmt
https://tip.golang.org/cmd/gofmt/ - The Go Blog: go fmt your code
https://blog.golang.org/go-fmt-your-code - C? Go? Cgo!
https://blog.golang.org/c-go-cgo - 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/ - 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 - Gofmt No Longer Allows Spaces. Tabs Only
https://news.ycombinator.com/item?id=7914523 - Why does Go „go fmt“ uses tabs instead of whitespaces?
https://www.quora.com/Why-does-Go-go-fmt-uses-tabs-instead-of-whitespaces - Interactive: The Top Programming Languages 2018
https://spectrum.ieee.org/static/interactive-the-top-programming-languages-2018 - Go vs. Python
https://www.peterbe.com/plog/govspy - PackageManagementTools
https://github.com/golang/go/wiki/PackageManagementTools - A Tour of Go: Type inference
https://tour.golang.org/basics/14 - Go Slices: usage and internals
https://blog.golang.org/go-slices-usage-and-internals - Go by Example: Slices
https://gobyexample.com/slices - What is the point of slice type in Go?
https://stackoverflow.com/questions/2098874/what-is-the-point-of-slice-type-in-go - The curious case of Golang array and slices
https://medium.com/@hackintoshrao/the-curious-case-of-golang-array-and-slices-2565491d4335 - Introduction to Slices in Golang
https://www.callicoder.com/golang-slices/ - Golang: Understanding ‚null‘ and nil
https://newfivefour.com/golang-null-nil.html - What does nil mean in golang?
https://stackoverflow.com/questions/35983118/what-does-nil-mean-in-golang - nils In Go
https://go101.org/article/nil.html - Go slices are not dynamic arrays
https://appliedgo.net/slices/ - Go-is-no-good (nelze brát doslova)
https://github.com/ksimka/go-is-not-good - Rust vs. Go
https://news.ycombinator.com/item?id=13430108 - Seriál Programovací jazyk Rust
https://www.root.cz/serialy/programovaci-jazyk-rust/ - Modern garbage collection: A look at the Go GC strategy
https://blog.plan99.net/modern-garbage-collection-911ef4f8bd8e - Go GC: Prioritizing low latency and simplicity
https://blog.golang.org/go15gc - Is Golang a good language for embedded systems?
https://www.quora.com/Is-Golang-a-good-language-for-embedded-systems - Running GoLang on an STM32 MCU. A quick tutorial.
https://www.mickmake.com/post/running-golang-on-an-mcu-a-quick-tutorial - Go, Robot, Go! Golang Powered Robotics
https://gobot.io/ - Emgo: Bare metal Go (language for programming embedded systems)
https://github.com/ziutek/emgo - UTF-8 history
https://www.cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt - Less is exponentially more
https://commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html - Should I Rust, or Should I Go
https://codeburst.io/should-i-rust-or-should-i-go-59a298e00ea9 - Setting up and using gccgo
https://golang.org/doc/install/gccgo - Elastic Tabstops
http://nickgravgaard.com/elastic-tabstops/ - Strings, bytes, runes and characters in Go
https://blog.golang.org/strings - Datový typ
https://cs.wikipedia.org/wiki/Datov%C3%BD_typ - Seriál o programovacím jazyku Rust: Základní (primitivní) datové typy
https://www.root.cz/clanky/programovaci-jazyk-rust-nahrada-c-nebo-slepa-cesta/#k09 - 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 - Seriál o programovacím jazyku Rust: Řezy (slice) vektoru
https://www.root.cz/clanky/prace-s-vektory-v-programovacim-jazyku-rust/#k05 - Printf Format Strings
https://www.cprogramming.com/tutorial/printf-format-strings.html - Java: String.format
https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#format-java.lang.String-java.lang.Object…- - Java: format string syntax
https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html#syntax - Selectors
https://golang.org/ref/spec#Selectors - Calling Go code from Python code
http://savorywatt.com/2015/09/18/calling-go-code-from-python-code/ - Go Data Structures: Interfaces
https://research.swtch.com/interfaces - How to use interfaces in Go
http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go - Interfaces in Go (part I)
https://medium.com/golangspec/interfaces-in-go-part-i-4ae53a97479c - Part 21: Goroutines
https://golangbot.com/goroutines/ - Part 22: Channels
https://golangbot.com/channels/ - [Go] Lightweight eventbus with async compatibility for Go
https://github.com/asaskevich/EventBus - What about Trait support in Golang?
https://www.reddit.com/r/golang/comments/8mfykl/what_about_trait_support_in_golang/ - 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/ - Control Flow
https://en.wikipedia.org/wiki/Control_flow - Structured programming
https://en.wikipedia.org/wiki/Structured_programming - Control Structures
https://www.golang-book.com/books/intro/5 - Control structures – Go if else statement
http://golangtutorials.blogspot.com/2011/06/control-structures-if-else-statement.html - Control structures – Go switch case statement
http://golangtutorials.blogspot.com/2011/06/control-structures-go-switch-case.html - Control structures – Go for loop, break, continue, range
http://golangtutorials.blogspot.com/2011/06/control-structures-go-for-loop-break.html - Single Function Exit Point
http://wiki.c2.com/?SingleFunctionExitPoint - Entry point
https://en.wikipedia.org/wiki/Entry_point - Why does Go have a GOTO statement?!
https://www.reddit.com/r/golang/comments/kag5q/why_does_go_have_a_goto_statement/ - Effective Go
https://golang.org/doc/effective_go.html - GoClipse: an Eclipse IDE for the Go programming language
http://goclipse.github.io/ - GoClipse Installation
https://github.com/GoClipse/goclipse/blob/latest/documentation/Installation.md#installation