Obsah
1. Programovací jazyk Go a 2D grafika
5. Vazba mezi SDL a dalšími programovacími jazyky
6. Instalace vývojové verze SDL2 a balíčku go-sdl2
7. Inicializace SDL, otevření okna a vyplnění plochy realizované v céčku
8. První demonstrační příklad v jazyce C
9. Přepis prvního příkladu do jazyka Go
10. Vykreslení rastrového obrázku funkcí typu blit
11. Druhý demonstrační příklad v jazyce C
12. Přepis druhého příkladu do jazyka Go
13. Třetí příklad – vykreslení obrázku se změnou jeho měřítka
14. Přepis třetího příkladu do jazyka Go
15. Přesné umístění obrázku doprostřed okna
16. Přepis čtvrtého příkladu do jazyka Go
17. Interaktivní prohlížeč fraktálů naprogramovaný v C
18. Interaktivní prohlížeč fraktálů naprogramovaný v Go
19. Repositář s demonstračními příklady
1. Programovací jazyk Go a 2D grafika
Programovací jazyk Go se v současnosti používá převážně pro tvorbu různých typů služeb popř. démonů, tj. pro takové aplikace, u nichž není vyžadován přímý grafický výstup. Ovšem to neznamená, že se situace nemůže změnit popř. že Go není vhodným jazykem pro tvorbu 2D či 3D grafiky. Dnes se zaměříme především na oblast dvourozměrné grafiky. Existuje pochopitelně mnoho různých způsobů, jakými mohou aplikace naprogramované v Go zobrazovat dvourozměrnou grafiku. Na nejnižší (resp. přesněji řečeno rozumně nízké) úrovni je možné otevřít framebuffer, zjistit jeho formát a zapisovat data do framebufferu přes sdílenou paměť. Ovšem toto řešení má celou řadu nevýhod, takže se hodí jen pro specifické případy, například pro práci s 2D grafikou na zařízeních typu Raspberry Pi. Tomuto tématu jsme se již na stránkách Roota věnovali v článcích Operace s framebufferem na Raspberry Pi, Operace s framebufferem na Raspberry Pi (vykreslování do framebufferu) a Framebuffer na Raspberry Pi: vykreslování složitějších objektů. Použít lze ovšem i OpenGL ES či některou z více či méně pokročilých herních knihoven.
Navíc vždycky existuje alternativní možnost spočívající v použití překladače do WASM (Web Assembly) a v provádění vykreslování přímo do canvasu v okně prohlížeče, což je téma, kterému jsme se v tomto seriálu ve stručnosti věnovali. Pro některé typy aplikací se nemusí jednat o špatné řešení, ovšem systémové nároky jsou vyšší, než v případě použití nativního kódu a nějaké nativní knihovny.
2. Knihovna SDL
U některých typů aplikací může být výhodnější se použití vysokoúrovňových knihoven zcela vyhnout a použít namísto nich nějakou nativní knihovnu, která bude požadované grafické operace nabízet. V případě 3D grafiky je tak možné využít OpenGL či Direct3D, ovšem pokud se jedná o 2D grafiku, nabízí se celkem zajímavá volba – využití nativní knihovny SDL, která je sama o sobě pouze relativně tenkou vrstvou mezi uživatelskými programy a multimediálními zařízeními (grafickou a zvukovou kartou, ale též klávesnicí, joysticky a myší či časovačem). Mezi přednosti SDL patří její jednoduchost (z toho se odvíjí i existence vazby mezi SDL a programovacími jazyky, i když její základní API je čistě céčkové), přenositelnost na různé platformy (včetně Androidu, minimálně v případě SDL 1.x) a v neposlední řadě taktéž existence několika doplňujících modulů, například modulu pro vykreslování TTF fontů, vytvoření grafického kontextu pro OpenGL, modulu pro komunikaci po síti atd. I díky těmto vlastnostem je SDL používána v mnoha úspěšných hrách, viz též http://en.wikipedia.org/wiki/List_of_games_using_SDL.
Tato knihovna programátorům nabízí jak vykreslování do okna v případě použití systému X Window, tak i vykreslování do framebufferu. Přitom se v případě SDL 1.2 jedná o poměrně úzkou vrstvu mezi framebufferem a aplikací, což mj. znamená, že z vykreslovacích (grafických) operací jsou k dispozici pouze operace určené pro vykreslení obdélníku konstantní barvou, přenosu obrázku operací bitblt a uzamčení obrazové paměti s vrácením ukazatele do framebufferu (v tento okamžik, tj. po uzamčení obrazové paměti, se vlastně programátor nachází v podobném stavu, jako my při otevření speciálního zařízení /dev/fb0 a jeho namapování do adresního prostoru aplikace). SDL2 je již pojata odlišným způsobem, protože využívá možností nabízených grafickými akcelerátory, zejména možnost uchovat vykreslované bitmapy ve formě textur v paměti grafického akcelerátoru s tím, že vykreslení takových bitmap je mnohem rychlejší a vůbec nezatěžuje CPU.
Všechny příklady, s nimiž se seznámíme, využívají SDL2. Kromě SDL2 se ještě stále můžete setkat s návody popř. i aplikacemi, které jsou založeny na SDL(1). Ovšem mezi původním SDL a SDL2 je, jak jsme si již naznačili v předchozím odstavci, celá řada rozdílů, které se týkají především grafického subsystému. Je to ostatně logické, protože původní knihovna SDL vznikala v době, kdy se používalo softwarové vykreslování (hry typu Doom atd.), takže programy měly přímý přístup ke všem používaným bitmapám a vykreslování spočívalo v přenosu dat mezi operační pamětí a video pamětí. Dnes je situace zcela odlišná, protože vykreslované objekty (i pro 2D grafiku) bývají uloženy přímo v paměti grafické karty a vykreslení se většinou provádí bez nutnosti opakovaného přenosu dat z operační paměti do video paměti. To mj. znamená, že například vykreslované sprity musí být uloženy ve formátu podporovaného grafickou kartou (ve formě textur). Tyto principiální rozdíly se projevily právě ve vydání knihovny SDL2, která není a vlastně ani nemůže být zpětně kompatibilní.
3. Allegro 4 a Allegro 5
Určitou alternativou (či možná lépe řečeno konkurencí, i když méně známou) ke knihovně SDL je knihovna nazvaná Allegro, která v současnosti existuje ve dvou variantách: „klasická“ varianta založená na softwarovém renderingu nese označení Allegro 4 a zcela přepracovaná varianta, která již dokáže využívat některé možnosti nabízené grafickými akcelerátory, se jmenuje Allegro 5 (zpětná kompatibilita zde není zachována, podobně jako je tomu u SDL 1.2 → SDL 2.0). Z hlediska tvorby grafiky jsou nejdůležitější funkce pro vykreslování různých grafických primitiv (od pixelů přes úsečky až po křivky), práci s rastrovými obrázky a sprity (včetně použití tzv. kompilovaných spritů), ale i například podpora pro práci s animacemi uloženými ve formátu FLI/FLC. Pro některé účely může být zajímavý i modul nabízející velmi snadno použitelné GUI, které sice neobsahuje všechny dnes očekávané widgety (chybí například strom), ale pro konfigurační dialogy s tlačítky, scrollbary, vstupními textovými poli, přepínači atd. je to někdy použitelná a přitom výkonnostně a především paměťově nenáročná alternativa k plnohodnotným GUI knihovnám.
4. EGL
Taktéž je možné využít technologii, která je přímo navržena pro práci s grafickým procesorem. Jedná se o EGL neboli též Native Platform Interface používané jako mezivrstva mezi grafickým procesorem (přičemž každý grafický procesor může mít zcela odlišný způsob ovládání) na jedné straně a knihovnou OpenVG či OpenGL ES na straně druhé (alternativně je samozřejmě možné volat funkce poskytované EGL přímo. Za vývojem EGL stojí sdružení Khronos, které kromě toho „pečuje“ i o specifikace a implementace OpenGL, OpenGL ES, OpenVG atd. Jedním ze základních úkolů EGL je vytvoření a správa grafického kontextu, ploch (surface), do kterých je možné přes knihovny OpenGL ES a OpenVG provádět vykreslování atd. Mimochodem – plochy (surface) mohou být vytvořeny tak, aby aplikace běžela v systému X Window (i v okně), přes framebuffer nebo lze vykreslování provádět do takzvaného zadního bufferu. Další důležitou funkcí nabízenou EGL je kopie obsahu bitmap mezi jednotlivými plochami, tj. operace typu bitblt.
5. Vazba mezi SDL a dalšími programovacími jazyky
Jak jsme se již řekli v úvodních kapitolách, pro většinu dnes používaných programovacích jazyků existuje rozhraní umožňující volat funkce knihovny SDL. Mezi podporované jazyky patří (pochopitelně kromě nativního céčka) zejména Ada, C++, C#, D, Fortran, Genie, Go, Haskell, Julia, Lua, Nim, OCaml, Pascal, Perl, PHP, Python, Rust, Vala a dokonce i Common Lisp. SDL lze použít i z jazyka Java (a tím pádem z jakéhokoli jazyka postaveného nad JVM), což je téma, kterým jsme se opět již zabývali:
- Pohled pod kapotu JVM – využití knihovny SDLJava v graficky náročných aplikacích
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-vyuziti-knihovny-sdljava-v-graficky-narocnych-aplikacich/ - Pohled pod kapotu JVM – základní koncepty, na nichž je postavena knihovna SDLJava
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-zakladni-koncepty-na-nichz-je-postavena-knihovna-sdljava/ - Pohled pod kapotu JVM – nízkoúrovňový přístup k framebufferu i bitmapám s využitím knihovny SDLJava
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-nizkourovnovy-pristup-k-framebufferu-i-bitmapam-s-vyuzitim-knihovny-sdljava/ - Pohled pod kapotu JVM – volání funkcí OpenGL s využitím knihovny SDLJava
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-volani-funkci-opengl-s-vyuzitim-knihovny-sdljava/ - Pohled pod kapotu JVM – složitější tělesa, textury a sprity v knihovně SDLJava
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-slozitejsi-telesa-textury-a-sprity-v-knihovne-sdljava/ - Pohled pod kapotu JVM – práce s texturami v knihovně SDLJava
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-prace-s-texturami-v-knihovne-sdljava/ - Pohled pod kapotu JVM – blending a textury s alfa kanálem v knihovně SDLJava
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-blending-a-textury-s-alfa-kanalem-v-knihovne-sdljava/ - Pohled pod kapotu JVM – zpracování událostí v knihovně SDLJava
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-zpracovani-udalosti-v-knihovne-sdljava/ - Pohled pod kapotu JVM – zpracování událostí v knihovně SDLJava (klávesnice a myš)
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-zpracovani-udalosti-v-knihovne-sdljava-klavesnice-a-mys/ - Pohled pod kapotu JVM – zpracování událostí v knihovně SDLJava (dokončení)
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-zpracovani-udalosti-v-knihovne-sdljava-dokonceni/ - Pohled pod kapotu JVM – práce s TTF fonty v knihovně SDLJava
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-prace-s-ttf-fonty-v-knihovne-sdljava/ - Pohled pod kapotu JVM – práce s TTF fonty v knihovně SDLJava (dokončení)
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-prace-s-ttf-fonty-v-knihovne-sdljava-dokonceni/ - Pohled pod kapotu JVM – kreslicí funkce dostupné ve třídě sdljavax.gfx.SDLGfx
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-kreslici-funkce-dostupne-ve-tride-sdljavax-gfx-sdlgfx/ - Pohled pod kapotu JVM – kreslicí funkce dostupné ve třídě sdljavax.gfx.SDLGfx (2.část)
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-kreslici-funkce-dostupne-ve-tride-sdljavax-gfx-sdlgfx-2-cast/ - Pohled pod kapotu JVM – kreslicí funkce ve třídě sdljavax.gfx.SDLGfx (3.část) a zvukový subsystém SDLJava
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-kreslici-funkce-ve-tride-sdljavax-gfx-sdlgfx-3-cast-a-zvukovy-subsystem-sdljava/ - Pohled pod kapotu JVM – přehrávání hudby s využitím knihovny SDLJava
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-prehravani-hudby-s-vyuzitim-knihovny-sdljava/ - Pohled pod kapotu JVM – přehrávání a mixování zvuků s využitím knihovny SDLJava
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-prehravani-a-mixovani-zvuku-s-vyuzitim-knihovny-sdljava/ - Pohled pod kapotu JVM – výkonnost aplikací vytvořených s využitím SDLJava v porovnání s nativními aplikacemi
https://www.root.cz/clanky/pohled-pod-kapotu-jvm-vykonnost-aplikaci-vytvorenych-s-vyuzitim-sdljava-v-porovnani-s-nativnimi-aplikacemi/
Dnes si popíšeme způsob použití SDL z jazyka Go s využitím balíčků go-sdl2.
6. Instalace vývojové verze SDL2 a balíčku go-sdl2
Před instalací rozhraní mezi knihovnou SDL2 a programovacím jazykem Go je nutné nainstalovat vývojové verze knihovny (přesněji řečeno knihoven) SDL2. To je ve skutečnosti velmi snadné a celá operace se provede (v distribuci založené na RPM, zde konkrétně na poněkud obstarožní Fedoře 27) následovně:
$ sudo yum install SDL2{,_image,_mixer,_ttf,_gfx}-devel Last metadata expiration check: 0:47:05 ago on Sun 22 Mar 2020 08:15:23 AM CET. Dependencies resolved. ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: SDL2-devel x86_64 2.0.7-3.fc27 updates 252 k SDL2_gfx-devel x86_64 1.0.3-1.fc27 updates 40 k SDL2_image-devel x86_64 2.0.2-2.fc27 updates 12 k SDL2_mixer-devel x86_64 2.0.2-1.fc27 updates 19 k SDL2_ttf-devel x86_64 2.0.14-5.fc27 fedora 12 k Installing dependencies: SDL2_gfx x86_64 1.0.3-1.fc27 updates 39 k SDL2_image x86_64 2.0.2-2.fc27 updates 80 k SDL2_mixer x86_64 2.0.2-1.fc27 updates 76 k SDL2_ttf x86_64 2.0.14-5.fc27 fedora 24 k libX11-devel x86_64 1.6.5-4.fc27 fedora 984 k libXau-devel x86_64 1.0.8-9.fc27 fedora 18 k libXdamage-devel x86_64 1.1.4-11.fc27 fedora 14 k libXext-devel x86_64 1.3.3-7.fc27 fedora 79 k libXfixes-devel x86_64 5.0.3-4.fc27 fedora 17 k libXxf86vm-devel x86_64 1.1.4-6.fc27 fedora 22 k libdrm-devel x86_64 2.4.91-1.fc27 updates 138 k libglvnd-core-devel x86_64 1:1.0.0-1.fc27 updates 22 k libglvnd-devel x86_64 1:1.0.0-1.fc27 updates 13 k libglvnd-opengl x86_64 1:1.0.0-1.fc27 updates 45 k libxcb-devel x86_64 1.12-5.fc27 fedora 1.0 M mesa-libEGL-devel x86_64 17.3.9-1.fc27 updates 45 k mesa-libGLES-devel x86_64 17.3.9-1.fc27 updates 70 k xorg-x11-proto-devel noarch 7.7-23.fc27 fedora 287 k Transaction Summary ================================================================================ Install 23 Packages Total download size: 3.3 M Installed size: 8.7 M Is this ok [y/N]:
V distribucích založených na Debianích balíčcích se instalace spustí velmi podobným způsobem (otestováno na Mintu):
$ apt-get install libsdl2{,-image,-mixer,-ttf,-gfx}-dev
Ve druhém kroku je nutné nainstalovat rozhraní mezi SDL2 a programovacím jazykem Go představované balíčkem nazvaným příznačně go-sdl2. Celý postup je v tomto případě zcela jednoduchý:
$ go get github.com/veandco/go-sdl2/sdl
7. Inicializace SDL, otevření okna a vyplnění plochy realizované v céčku
Vlastnosti a možnosti nabízené knihovnou SDL si nejlépe ukážeme na demonstračních příkladech. Všechny dnes uvedené demonstrační příklady – ty psané v C i v Go – budou velmi jednoduché a současně budou využívat jen základní grafické možnosti knihovny SDL, zatímco dalšími možnostmi (zvuky, čtení stavů klávesnice a myši atd.) se budeme zabývat v navazujících částech tohoto seriálu. První demonstrační příklad uvedený v této kapitole je velmi jednoduchý a využívá pouze několik funkcí SDL určené pro inicializaci okna, kreslicí plochy (surface), základní vykreslení a uvolnění všech zdrojů – ukazuje tedy základní typy objektů, s nimiž se v SDL dříve či později setkáme.
Inicializace knihovny SDL, resp. jejích vybraných subsystémů:
if (SDL_Init(SDL_INIT_VIDEO) < 0) { puts("Error initializing SDL"); puts(SDL_GetError()); return 1; }
Vytvoření okna zadané velikosti (lze otevřít i fullscreen okno bez okrajů):
window = SDL_CreateWindow("SDL2 example #1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN); if (!window) { puts("Error creating window"); puts(SDL_GetError()); return 1; }
Důležitý je koncept kreslicí plochy – surface. Tu lze získat i pro existující otevřené okno. Jakmile je získána kreslicí plocha, můžeme ji či její část vyplnit zadanou barvou a vynutit si překreslení obsahu okna:
primarySurface = SDL_GetWindowSurface(window); if (!primarySurface) { puts("Error getting surface"); puts(SDL_GetError()); return 1; } SDL_FillRect(primarySurface, NULL, SDL_MapRGB(primarySurface->format, 192, 255, 192)); SDL_UpdateWindowSurface(window);
Nakonec bychom neměli zapomenout na uvolnění všech prostředků (objektů) a ukončení běhu knihovny SDL:
SDL_DestroyWindow(window); SDL_Quit();
8. První demonstrační příklad v jazyce C
Úplný zdrojový kód prvního příkladu zapsaného v jazyce C může vypadat následovně:
#include <stdio.h> #include <SDL2/SDL.h> #define WIDTH 640 #define HEIGHT 480 int main(int argc, char** args) { SDL_Surface *primarySurface = NULL; SDL_Window *window = NULL; if (SDL_Init(SDL_INIT_VIDEO) < 0) { puts("Error initializing SDL"); puts(SDL_GetError()); return 1; } window = SDL_CreateWindow("SDL2 example #1", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN); if (!window) { puts("Error creating window"); puts(SDL_GetError()); return 1; } primarySurface = SDL_GetWindowSurface(window); if (!primarySurface) { puts("Error getting surface"); puts(SDL_GetError()); return 1; } SDL_FillRect(primarySurface, NULL, SDL_MapRGB(primarySurface->format, 192, 255, 192)); SDL_UpdateWindowSurface(window); SDL_Delay(5000); SDL_DestroyWindow(window); SDL_Quit(); return 0; }
9. Přepis prvního příkladu do jazyka Go
Nyní se můžeme pokusit přepsat tento demonstrační příklad do jazyka Go. Kostra a základní myšlenka zůstane pochopitelně stejná, budou se jen lišit jména funkcí, namísto některých funkcí použijeme metody a navíc s výhodou využijeme konstrukci defer.
package main import "github.com/veandco/go-sdl2/sdl" const ( width = 640 height = 480 ) func main() { if err := sdl.Init(sdl.INIT_VIDEO); err != nil { panic(err) } defer sdl.Quit() window, err := sdl.CreateWindow("Example #1", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, width, height, sdl.WINDOW_SHOWN) if err != nil { panic(err) } defer window.Destroy() primarySurface, err := window.GetSurface() if err != nil { panic(err) } primarySurface.FillRect(nil, sdl.MapRGB(primarySurface.Format, 192, 255, 192)) window.UpdateSurface() sdl.Delay(5000) }
10. Vykreslení rastrového obrázku funkcí typu blit
Ve druhém demonstračním příkladu se pokusíme o načtení rastrového obrázku uloženého ve formátu BMP. Tento formát nebyl v žádném případě zvolen proto, že by byl snadno zpracovatelný nebo dokonce úsporný, ale z toho prostého důvodu, že jeho podpora je přímo součástí základní knihovny SDL/SDL2 bez nutnosti používat sdl-image. Další formáty (PNG apod.) lze sice načítat také, ale nepatrně složitějším způsobem. Vraťme se však k demonstračnímu příkladu. Načtení obrázku v programovacím jazyce C a kontrola, zda se načtení podařilo, se provede následujícím způsobem:
SDL_Surface *tempImage; tempImage = SDL_LoadBMP("test1.bmp"); if (!tempImage) { puts("Error loading image"); return 0; }
Následně je vhodné (i když ne vždy nutné) obrázek zkonvertovat do takového formátu, který je přímo zobrazitelný na obrazovce. K tomuto účelu se používá funkce SDL_ConvertSurface, které se předá jak původní kreslicí plocha (načtený obrázek), tak i požadovaný formát:
image = SDL_ConvertSurface(tempImage, primarySurface->format, 0);
Zkonvertovaný obrázek se zobrazí funkcí nazvanou SDL_BlitSurface, které pro jednoduchost předáme pouze obrázek a primární kreslicí plochu. Obrázek tedy bude umístěn do souřadnic (0,0):
SDL_BlitSurface(image, NULL, primarySurface, NULL);
11. Druhý demonstrační příklad v jazyce C
Úplný zdrojový kód takto navrženého druhého demonstračního příkladu vypadá následovně:
#include <stdio.h> #include <SDL2/SDL.h> #define WIDTH 640 #define HEIGHT 480 SDL_Window *window; SDL_Surface *primarySurface; SDL_Surface *image; int load() { SDL_Surface *tempImage; tempImage = SDL_LoadBMP("test1.bmp"); if (!tempImage) { puts("Error loading image"); return 0; } image = SDL_ConvertSurface(tempImage, primarySurface->format, 0); SDL_FreeSurface(tempImage); if (!image) { puts("Error converting surface"); return 0; } return 1; } int init() { if (SDL_Init(SDL_INIT_VIDEO ) < 0) { puts("Error initializing SDL"); return 0; } window = SDL_CreateWindow("SDL2 example #2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN); if (!window) { puts("Error creating window"); return 0; } primarySurface = SDL_GetWindowSurface(window); if (!primarySurface) { puts("Error getting surface"); return 0; } return 1; } void destroy() { SDL_FreeSurface(image); SDL_DestroyWindow(window); SDL_Quit(); } int main(int argc, char** args) { if (!init()) { return 1; } if (!load()) { return 1; } SDL_BlitSurface(image, NULL, primarySurface, NULL); SDL_UpdateWindowSurface(window); SDL_Delay(5000); destroy(); return 0; }
12. Přepis druhého příkladu do jazyka Go
Následuje přepis předchozího céčkového příkladu do Go. Opět zde můžeme vidět určitá zjednodušení; například načtení rastrového obrázku je triviální:
surfaceImage, err := img.Load("test1.bmp") if err != nil { panic(err) } defer surfaceImage.Free()
Výsledek:
package main import ( "github.com/veandco/go-sdl2/img" "github.com/veandco/go-sdl2/sdl" ) const ( width = 640 height = 480 ) func main() { if err := sdl.Init(sdl.INIT_VIDEO); err != nil { panic(err) } defer sdl.Quit() window, err := sdl.CreateWindow("Example #2", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, width, height, sdl.WINDOW_SHOWN) if err != nil { panic(err) } defer window.Destroy() primarySurface, err := window.GetSurface() if err != nil { panic(err) } surfaceImage, err := img.Load("test1.bmp") if err != nil { panic(err) } defer surfaceImage.Free() primarySurface.FillRect(nil, sdl.MapRGB(primarySurface.Format, 192, 255, 192)) err = surfaceImage.Blit(nil, primarySurface, nil) if err != nil { panic(err) } window.UpdateSurface() sdl.Delay(5000) }
Jak jsme si již řekli výše, je užitečnější a korektnější převést obrázek na „kompatibilní formát“, což je provedeno v dalším zdrojovém kódu, který mj. obsahuje:
convertedImage, err := surfaceImage.Convert(primarySurface.Format, 0) if err != nil { panic(err) } defer convertedImage.Free()
Úplný zdrojový kód:
package main import ( "github.com/veandco/go-sdl2/img" "github.com/veandco/go-sdl2/sdl" ) const ( width = 640 height = 480 ) func main() { if err := sdl.Init(sdl.INIT_VIDEO); err != nil { panic(err) } defer sdl.Quit() window, err := sdl.CreateWindow("Example #2", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, width, height, sdl.WINDOW_SHOWN) if err != nil { panic(err) } defer window.Destroy() primarySurface, err := window.GetSurface() if err != nil { panic(err) } surfaceImage, err := img.Load("test1.bmp") if err != nil { panic(err) } defer surfaceImage.Free() convertedImage, err := surfaceImage.Convert(primarySurface.Format, 0) if err != nil { panic(err) } defer convertedImage.Free() primarySurface.FillRect(nil, sdl.MapRGB(convertedImage.Format, 192, 255, 192)) err = convertedImage.Blit(nil, primarySurface, nil) if err != nil { panic(err) } window.UpdateSurface() sdl.Delay(5000) }
13. Třetí příklad – vykreslení obrázku se změnou jeho měřítka
Ve třetím příkladu zobrazíme stejný obrázek, jako v příkladu předchozím, ovšem s odlišným měřítkem. Pro tento účel se v céčku používá funkce nazvaná SDL_BlitScaled, která ovšem pracuje korektně jen za předpokladu, že je obrázek uložen ve formátu kompatibilním s cílovou kreslicí plochou, tj. v našem případě s plochou představující obrazovku. Rozměry a umístění obrázku jsou představovány datovou strukturou Rect (obdélník):
dest.x = 160; dest.y = 120; dest.w = 250; dest.h = 250; SDL_BlitScaled(image, NULL, primarySurface, &dest);
Úplný zdrojový kód třetího příkladu v céčkové variantě:
#include <stdio.h> #include <SDL2/SDL.h> #define WIDTH 640 #define HEIGHT 480 SDL_Window *window; SDL_Surface *primarySurface; SDL_Surface *image; int load() { SDL_Surface *tempImage; tempImage = SDL_LoadBMP("test1.bmp"); if (!tempImage) { puts("Error loading image"); return 0; } image = SDL_ConvertSurface(tempImage, primarySurface->format, 0); SDL_FreeSurface(tempImage); if (!image) { puts("Error converting surface"); return 0; } return 1; } int init() { if (SDL_Init(SDL_INIT_VIDEO ) < 0) { puts("Error initializing SDL"); return 0; } window = SDL_CreateWindow("SDL2 example #3", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN ); if (!window) { puts("Error creating window"); return 0; } primarySurface = SDL_GetWindowSurface(window); if (!primarySurface) { puts("Error getting surface"); return 0; } return 1; } void destroy() { SDL_FreeSurface(image); SDL_DestroyWindow(window); SDL_Quit(); } int main(int argc, char** args) { SDL_Rect dest; if (!init()) { return 1; } if (!load()) { return 1; } SDL_FillRect(primarySurface, NULL, SDL_MapRGB(primarySurface->format, 192, 255, 192)); dest.x = 160; dest.y = 120; dest.w = 250; dest.h = 250; SDL_BlitScaled(image, NULL, primarySurface, &dest); SDL_UpdateWindowSurface(window); SDL_Delay(5000); destroy(); return 0; }
14. Přepis třetího příkladu do jazyka Go
Přepis předchozího příkladu do idiomatického Go je relativně snadný a příliš se neliší od obou příkladů předchozích:
package main import ( "github.com/veandco/go-sdl2/img" "github.com/veandco/go-sdl2/sdl" ) const ( width = 640 height = 480 ) func main() { if err := sdl.Init(sdl.INIT_VIDEO); err != nil { panic(err) } defer sdl.Quit() window, err := sdl.CreateWindow("Example #3", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, width, height, sdl.WINDOW_SHOWN) if err != nil { panic(err) } defer window.Destroy() primarySurface, err := window.GetSurface() if err != nil { panic(err) } surfaceImage, err := img.Load("test1.bmp") if err != nil { panic(err) } defer surfaceImage.Free() convertedImage, err := surfaceImage.Convert(primarySurface.Format, 0) if err != nil { panic(err) } defer convertedImage.Free() primarySurface.FillRect(nil, sdl.MapRGB(convertedImage.Format, 192, 255, 192)) var destRect sdl.Rect destRect.X = 160 destRect.Y = 120 destRect.W = 250 destRect.H = 250 err = convertedImage.BlitScaled(nil, primarySurface, &destRect) if err != nil { panic(err) } window.UpdateSurface() sdl.Delay(5000) }
15. Přesné umístění obrázku doprostřed okna
Ve čtvrtém demonstračním příkladu se seznámíme s dalšími vlastnostmi kreslicí plochy. Týká se to zejména informace o její šířce a výšce, která je v jazyku C reprezentovaná položkami nazvanými h a w. Vzhledem k tomu, že k ploše přistupujeme přes ukazatel, bude se pro přístup k položkám datové struktury používat opererátor ->. Vycentrování obrázku na střed okna a současně jeho zmenšení na polovinu zajistí následující úryvek kódu:
dest.x = primarySurface->w/2 - image->w/4; dest.y = primarySurface->h/2 - image->h/4; dest.w = image->w/2; dest.h = image->h/2; printf("%d %d %d %d\n", dest.x, dest.y, dest.w, dest.h); SDL_BlitScaled(image, NULL, primarySurface, &dest);
Opět pochopitelně následuje výpis úplného zdrojového kódu tohoto příkladu:
#include <stdio.h> #include <SDL2/SDL.h> #define WIDTH 640 #define HEIGHT 480 SDL_Window *window; SDL_Surface *primarySurface; SDL_Surface *image; int load() { SDL_Surface *tempImage; tempImage = SDL_LoadBMP("test1.bmp"); if (!tempImage) { puts("Error loading image"); return 0; } image = SDL_ConvertSurface(tempImage, primarySurface->format, 0); SDL_FreeSurface(tempImage); if (!image) { puts("Error converting surface"); return 0; } return 1; } int init() { if (SDL_Init(SDL_INIT_VIDEO ) < 0) { puts("Error initializing SDL"); return 0; } window = SDL_CreateWindow("SDL2 example #4", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_SHOWN); if (!window) { puts("Error creating window"); return 0; } primarySurface = SDL_GetWindowSurface(window); if (!primarySurface) { puts("Error getting surface"); return 0; } return 1; } void destroy() { SDL_FreeSurface(image); SDL_DestroyWindow(window); SDL_Quit(); } int main(int argc, char** args) { SDL_Rect dest; if (!init()) { return 1; } if (!load()) { return 1; } SDL_FillRect(primarySurface, NULL, SDL_MapRGB(primarySurface->format, 192, 255, 192)); dest.x = primarySurface->w/2 - image->w/4; dest.y = primarySurface->h/2 - image->h/4; dest.w = image->w/2; dest.h = image->h/2; printf("%d %d %d %d\n", dest.x, dest.y, dest.w, dest.h); SDL_BlitScaled(image, NULL, primarySurface, &dest); SDL_UpdateWindowSurface(window); SDL_Delay(5000); destroy(); return 0; }
16. Přepis čtvrtého příkladu do jazyka Go
Převod do idiomatického Go pravděpodobně není zapotřebí podrobně komentovat, protože se jedná jen o variantu na třetí demonstrační příklad:
package main import ( "github.com/veandco/go-sdl2/img" "github.com/veandco/go-sdl2/sdl" ) const ( width = 640 height = 480 ) func main() { if err := sdl.Init(sdl.INIT_VIDEO); err != nil { panic(err) } defer sdl.Quit() window, err := sdl.CreateWindow("Example #4", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, width, height, sdl.WINDOW_SHOWN) if err != nil { panic(err) } defer window.Destroy() primarySurface, err := window.GetSurface() if err != nil { panic(err) } surfaceImage, err := img.Load("test1.bmp") if err != nil { panic(err) } defer surfaceImage.Free() convertedImage, err := surfaceImage.Convert(primarySurface.Format, 0) if err != nil { panic(err) } defer convertedImage.Free() primarySurface.FillRect(nil, sdl.MapRGB(convertedImage.Format, 192, 255, 192)) var destRect sdl.Rect destRect.X = primarySurface.W/2 - convertedImage.W/4 destRect.Y = primarySurface.H/2 - convertedImage.H/4 destRect.W = convertedImage.W / 2 destRect.H = convertedImage.H / 2 err = convertedImage.BlitScaled(nil, primarySurface, &destRect) if err != nil { panic(err) } window.UpdateSurface() sdl.Delay(5000) }
17. Interaktivní prohlížeč fraktálů naprogramovaný v C
Knihovnou SDL se budeme zabývat i příště, takže si již dopředu ukažme relativně složitý zdrojový kód, v němž je realizován výpočet a vykreslení fraktálů (mix mezi Mandelbrotovou a Juliovou množinou). V tomto příkladu se používá přímý přístup do paměti kreslicí plochy, zpracování událostí (smyčka událostí) atd. Podrobnosti si řekneme v navazujícím článku:
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <SDL2/SDL.h> #define WIDTH 320 #define HEIGHT 240 #define nil NULL #define MAX(a,b) ((a)>(b) ? (a) : (b)) #define MIN(a,b) ((a)<(b) ? (a) : (b)) SDL_Surface *pixmap; SDL_Surface *screen_surface = NULL; SDL_Surface *bitmap_font_surface = NULL; SDL_Window *window = NULL; double xpos = -0.75; double ypos = 0.0; double scale = 150.0; double uhel = 45.0; int gfx_initialize(int fullscreen, int width, int height, int bpp) { window = NULL; if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError()); return 1; } else { puts("SDL_Init ok"); } window = SDL_CreateWindow( "Example", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN ); if (!window) { puts("Error creating window"); puts(SDL_GetError()); return 1; } else { puts("SDL_CreateWindow ok"); } screen_surface = SDL_GetWindowSurface(window); if (!screen_surface) { fprintf(stderr, "Error setting video mode: %s\n", SDL_GetError()); return 1; } else { puts("SDL_GetWindowSurface ok"); } return 0; } void gfx_finalize(void) { SDL_FreeSurface(screen_surface); SDL_DestroyWindow(window); } SDL_Surface* gfx_create_surface(int width, int height) { return SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000); } void putpixel(SDL_Surface *surface, int x, int y, unsigned char r, unsigned char g, unsigned char b) { if (x>=0 && x< surface->w && y>=0 && y < surface->h) { if (surface->format->BitsPerPixel == 24) { Uint8 *pixel = (Uint8 *)surface->pixels; pixel += x*3; pixel += y*surface->pitch; *pixel++ = b; *pixel++ = g; *pixel = r; } if (surface->format->BitsPerPixel == 32) { Uint8 *pixel = (Uint8 *)surface->pixels; pixel += x*4; pixel += y*surface->pitch; *pixel++ = b; *pixel++ = g; *pixel = r; } } } void hline(SDL_Surface *surface, int x1, int x2, int y, unsigned char r, unsigned char g, unsigned char b) { int x; int fromX = MIN(x1, x2); int toX = MAX(x1, x2); for (x = fromX; x <= toX; x++) { putpixel(surface, x, y, r, g, b); } } void vline(SDL_Surface *surface, int x, int y1, int y2, unsigned char r, unsigned char g, unsigned char b) { int y; int fromY = MIN(y1, y2); int toY = MAX(y1, y2); for (y = fromY; y <= toY; y++) { putpixel(surface, x, y, r, g, b); } } static void show_fractal(SDL_Surface *surface) { SDL_BlitSurface(surface, NULL, screen_surface, NULL); SDL_UpdateWindowSurface(window); } void calcCorner(double xpos, double ypos, double scale, double *xmin, double *ymin, double *xmax, double *ymax) { *xmin=xpos-WIDTH/scale; *ymin=ypos-HEIGHT/scale; *xmax=xpos+WIDTH/scale; *ymax=ypos+HEIGHT/scale; } void draw_grid(SDL_Surface *surface) { int width = surface->w; int height = surface->h; int x, y; SDL_FillRect(surface, NULL, 0xffffffff); for (x=0; x<width; x+=20) { vline(surface, x, 0, height-1, 191, 191, 255); } for (y=0; y<height; y+=20) { hline(surface, 0, width-1, y, 191, 191, 255); } } void draw_mandeljulia(SDL_Surface *surface) { double zx,zy,zx2,zy2,cx,cy; double cosu,sinu,ccxc,ccyc; int x,y,i; Uint8 *pixel = nil; double ccx = 0.0; double ccy = 0.0; double xmin, ymin, xmax, ymax; double u; calcCorner(xpos, ypos, scale, &xmin, &ymin, &xmax, &ymax); u=uhel*3.1415/180.0; cosu=cos(u); sinu=sin(u); ccxc=ccx*cosu; ccyc=ccy*cosu; cy = ymin; for (y=0;y<240;y++) { cx=xmin; pixel = (Uint8 *)surface->pixels + (y + 128) * surface->pitch + 160*4; for (x=0;x<320;x++) { i=0; zx=cx*cosu; zy=cy*cosu; do { zx2=zx*zx; zy2=zy*zy; zy=2.0*zx*zy+ccyc+cy*sinu; zx=zx2-zy2+ccxc+cx*sinu; i++; } while (i<64 && zx2+zy2<4.0); { int r = i*2; int g = i*3; int b = i*5; *pixel++ = r; *pixel++ = g; *pixel++ = b; pixel++; } cx += (xmax-xmin)/WIDTH; } cy += (ymax-ymin)/HEIGHT; } } void redraw(SDL_Surface *pixmap) { draw_grid(pixmap); draw_mandeljulia(pixmap); show_fractal(pixmap); } static void main_event_loop(void) { SDL_Event event; int done = 0; int left = 0, right = 0, up = 0, down = 0; int zoomin = 0, zoomout = 0; int perform_redraw; int angle_1 = 0, angle_2 = 0; do { /*SDL_WaitEvent(&event);*/ while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: done = 1; break; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_ESCAPE: case SDLK_q: done = 1; break; case SDLK_LEFT: left = 1; break; case SDLK_RIGHT: right = 1; break; case SDLK_UP: up = 1; break; case SDLK_DOWN: down = 1; break; case SDLK_PAGEDOWN: zoomin = 1; break; case SDLK_PAGEUP: zoomout = 1; break; case SDLK_z: angle_1 = 1; break; case SDLK_x: angle_2 = 1; break; default: break; } break; case SDL_KEYUP: switch (event.key.keysym.sym) { case SDLK_LEFT: left = 0; break; case SDLK_RIGHT: right = 0; break; case SDLK_UP: up = 0; break; case SDLK_DOWN: down = 0; break; case SDLK_PAGEDOWN: zoomin = 0; break; case SDLK_PAGEUP: zoomout = 0; break; case SDLK_z: angle_1 = 0; break; case SDLK_x: angle_2 = 0; break; default: break; } default: break; } } perform_redraw = 0; if (left) { xpos -= 10.0/scale; perform_redraw=1; } if (right) { xpos += 10.0/scale; perform_redraw=1; } if (up) { ypos -= 10.0/scale; perform_redraw=1; } if (down) { ypos += 10.0/scale; perform_redraw=1; } if (zoomin) { scale *= 0.9; perform_redraw=1; } if (zoomout) { scale *= 1.1; perform_redraw=1; } if (angle_1) { uhel--; perform_redraw=1; } if (angle_2) { uhel++; perform_redraw=1; } if (perform_redraw) { redraw(pixmap); } } while (!done); } int main(int argc, char **argv) { if (gfx_initialize(0, 640, 480, 32)) { return 1; } pixmap = gfx_create_surface(screen_surface->w, screen_surface->h); draw_grid(pixmap); draw_mandeljulia(pixmap); show_fractal(pixmap); main_event_loop(); gfx_finalize(); SDL_Quit(); return 0; }
18. Interaktivní prohlížeč fraktálů naprogramovaný v Go
Přepis předchozího příkladu do programovacího jazyka Go může vypadat následovně:
package main import ( "math" "github.com/veandco/go-sdl2/sdl" ) const ( width = 320 height = 240 ) var pixmap *sdl.Surface = nil var primarySurface *sdl.Surface = nil var window *sdl.Window = nil var xpos float64 = -0.75 var ypos float64 = 0.0 var scale float64 = 150.0 var uhel float64 = 45.0 func min(a, b int32) int32 { if a > b { return b } return a } func max(a, b int32) int32 { if a > b { return a } return b } func gfxInitialize(width int32, height int32, bpp int) { err := sdl.Init(sdl.INIT_VIDEO) if err != nil { panic(err) } window, err = sdl.CreateWindow("Fractals", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, width, height, sdl.WINDOW_SHOWN) if err != nil { panic(err) } primarySurface, err = window.GetSurface() if err != nil { panic(err) } } func gfxFinalize() { primarySurface.Free() window.Destroy() sdl.Quit() } func createSurface(width int32, height int32) *sdl.Surface { surface, err := sdl.CreateRGBSurface(sdl.SWSURFACE, width, height, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000) if err != nil { panic(err) } return surface } func putpixel(surface *sdl.Surface, x int32, y int32, r byte, g byte, b byte) { if x >= 0 && x < surface.W && y >= 0 && y < surface.H { switch surface.Format.BitsPerPixel { case 24: index := x*3 + y*surface.Pitch pixels := surface.Pixels() pixels[index] = b pixels[index+1] = g pixels[index+2] = r case 32: index := x*4 + y*surface.Pitch pixels := surface.Pixels() pixels[index] = b pixels[index+1] = g pixels[index+2] = r } } } func hline(surface *sdl.Surface, x1 int32, x2 int32, y int32, r byte, g byte, b byte) { fromX := min(x1, x2) toX := max(x1, x2) for x := fromX; x <= toX; x++ { putpixel(surface, x, y, r, g, b) } } func vline(surface *sdl.Surface, x int32, y1 int32, y2 int32, r byte, g byte, b byte) { fromY := min(y1, y2) toY := max(y1, y2) for y := fromY; y <= toY; y++ { putpixel(surface, x, y, r, g, b) } } func drawGrid(surface *sdl.Surface) { width := surface.W height := surface.H var x, y int32 surface.FillRect(nil, 0xffffffff) for x = 0; x < width; x += 20 { vline(surface, x, 0, height-1, 191, 191, 255) } for y = 0; y < height; y += 20 { hline(surface, 0, width-1, y, 191, 191, 255) } } func showFractal(surface *sdl.Surface) { err := surface.Blit(nil, primarySurface, nil) if err != nil { panic(err) } window.UpdateSurface() } func calcCorner(xpos, ypos, scale float64) (xmin, ymin, xmax, ymax float64) { xmin = xpos - width/scale ymin = ypos - height/scale xmax = xpos + width/scale ymax = ypos + height/scale return } func drawMandelJulia(surface *sdl.Surface) { ccx := 0.0 ccy := 0.0 xmin, ymin, xmax, ymax := calcCorner(xpos, ypos, scale) u := uhel * 3.1415 / 180.0 cosu := math.Cos(u) sinu := math.Sin(u) ccxc := ccx * cosu ccyc := ccy * cosu cy := ymin for y := 0; y < height; y++ { cx := xmin for x := 0; x < width; x++ { i := 0 zx := cx * cosu zy := cy * cosu for { zx2 := zx * zx zy2 := zy * zy zy = 2.0*zx*zy + ccyc + cy*sinu zx = zx2 - zy2 + ccxc + cx*sinu i++ if i >= 64 || zx2+zy2 >= 4.0 { break } } b := i * 2 g := i * 3 r := i * 5 putpixel(surface, int32(x+width/2), int32(y+height/2), byte(r), byte(g), byte(b)) cx += (xmax - xmin) / width } cy += (ymax - ymin) / height } } func redraw(pixmap *sdl.Surface) { drawGrid(pixmap) drawMandelJulia(pixmap) showFractal(pixmap) } func mainEventLoop() { var event sdl.Event done := false left := false right := false up := false down := false zoomin := false zoomout := false angle1 := false angle2 := false for !done { event = sdl.PollEvent() switch t := event.(type) { case *sdl.QuitEvent: done = true case *sdl.KeyboardEvent: keyCode := t.Keysym.Sym if t.State == sdl.PRESSED { switch keyCode { case sdl.K_ESCAPE: done = true case sdl.K_q: done = true case sdl.K_LEFT: left = true case sdl.K_RIGHT: right = true case sdl.K_UP: up = true case sdl.K_DOWN: down = true case sdl.K_PAGEDOWN: zoomin = true case sdl.K_PAGEUP: zoomout = true case sdl.K_z: angle1 = true case sdl.K_x: angle2 = true } } if t.State == sdl.RELEASED { switch keyCode { case sdl.K_LEFT: left = false case sdl.K_RIGHT: right = false case sdl.K_UP: up = false case sdl.K_DOWN: down = false case sdl.K_PAGEDOWN: zoomin = false case sdl.K_PAGEUP: zoomout = false case sdl.K_z: angle1 = false case sdl.K_x: angle2 = false } } } performRedraw := false if left { xpos -= 10.0 / scale performRedraw = true } if right { xpos += 10.0 / scale performRedraw = true } if up { ypos -= 10.0 / scale performRedraw = true } if down { ypos += 10.0 / scale performRedraw = true } if zoomin { scale *= 0.9 performRedraw = true } if zoomout { scale *= 1.1 performRedraw = true } if angle1 { uhel-- performRedraw = true } if angle2 { uhel++ performRedraw = true } if performRedraw { redraw(pixmap) sdl.Delay(20) } } } func main() { gfxInitialize(640, 480, 32) defer gfxFinalize() pixmap = createSurface(primarySurface.W, primarySurface.H) redraw(pixmap) mainEventLoop() }
19. Repositář s demonstračními příklady
Zdrojové kódy všech dnes použitých demonstračních příkladů byly uloženy do nového 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ě stovku kilobajtů), můžete namísto toho použít odkazy na jednotlivé demonstrační příklady, které naleznete v následující tabulce:
20. Odkazy na Internetu
- Stránky projektu SDL
http://www.libsdl.org/ - Simple DirectMedia Layer (Wikipedia)
https://en.wikipedia.org/wiki/Simple_DirectMedia_Layer - SDL Language Bindings
http://www.libsdl.org/languages.php - SDL version 1.2.15
http://www.libsdl.org/download-1.2.php - SDL version 2.0.1
http://www.libsdl.org/download-2.0.php - Rozhraní go-sdl2
https://github.com/veandco/go-sdl2 - Dokumentace k rozhraní go-sdl2
https://godoc.org/github.com/veandco/go-sdl2 - Dokumentace k balíčku sdl
https://godoc.org/github.com/veandco/go-sdl2/sdl - Dokumentace k balíčku gfx
https://godoc.org/github.com/veandco/go-sdl2/gfx - Cross-platform games development (part 1)
http://renatoc.wait4.org/2010/02/04/cross-platform-games-development-part-1/ - Cross-platform games development (part 2)
http://renatoc.wait4.org/tag/sdljava/ - Go Data Structures: Binary Search Tree
https://flaviocopes.com/golang-data-structure-binary-search-tree/ - Gobs of data
https://blog.golang.org/gobs-of-data - Formát BSON
http://bsonspec.org/ - Golang Guide: A List of Top Golang Frameworks, IDEs & Tools
https://blog.intelligentbee.com/2017/08/14/golang-guide-list-top-golang-frameworks-ides-tools/ - Tvorba univerzálních projevů
http://www.kyblsoft.cz/projevy - Repositář projektu Gift
https://github.com/disintegration/gift - Dokumentace k projektu Gift
https://godoc.org/github.com/disintegration/gift - Online x86 / x64 Assembler and Disassembler
https://defuse.ca/online-x86-assembler.htm#disassembly2 - The Design of the Go Assembler
https://talks.golang.org/2016/asm.slide#1 - A Quick Guide to Go's Assembler
https://golang.org/doc/asm - AssemblyPolicy
https://github.com/golang/go/wiki/AssemblyPolicy - Geohash in Golang Assembly
https://mmcloughlin.com/posts/geohash-assembly - Command objdump
https://golang.org/cmd/objdump/ - Assembly
https://goroutines.com/asm - Go & Assembly
http://www.doxsey.net/blog/go-and-assembly - A Foray Into Go Assembly Programming
https://blog.sgmansfield.com/2017/04/a-foray-into-go-assembly-programming/ - Golang Capturing log.Println And fmt.Println Output
https://medium.com/@hau12a1/golang-capturing-log-println-and-fmt-println-output-770209c791b4 - Stránka projektu plotly
https://plot.ly/ - Plotly JavaScript Open Source Graphing Library
https://plot.ly/javascript/ - Domain coloring
https://en.wikipedia.org/wiki/Domain_coloring - Michael Fogleman's projects
https://www.michaelfogleman.com/projects/tagged/graphics/ - Color Graphs of Complex Functions
https://web.archive.org/web/20120511021419/http://w.american.edu/cas/mathstat/lcrone/ComplexPlot.html - A Gallery of Complex Functions
http://wismuth.com/complex/gallery.html - package glot
https://godoc.org/github.com/Arafatk/glot - Gnuplotting: Output terminals
http://www.gnuplotting.org/output-terminals/ - Introducing Glot the plotting library for Golang
https://medium.com/@Arafat./introducing-glot-the-plotting-library-for-golang-3133399948a1 - Introducing Glot the plotting library for Golang
https://blog.gopheracademy.com/advent-2018/introducing-glot/ - Glot is a plotting library for Golang built on top of gnuplot
https://github.com/Arafatk/glot - Example plots (gonum/plot)
https://github.com/gonum/plot/wiki/Example-plots - A repository for plotting and visualizing data (gonum/plot)
https://github.com/gonum/plot - golang library to make https://chartjs.org/ plots
https://github.com/brentp/go-chartjs - Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
https://www.root.cz/clanky/gorilla-repl-interaktivni-prostredi-pro-programovaci-jazyk-clojure/ - The Gonum Numerical Computing Package
https://www.gonum.org/post/introtogonum/ - Gomacro na GitHubu
https://github.com/cosmos72/gomacro - gophernotes – Use Go in Jupyter notebooks and nteract
https://github.com/gopherdata/gophernotes - gonum
https://github.com/gonum - go-gota/gota – DataFrames and data wrangling in Go (Golang)
https://porter.io/github.com/go-gota/gota - A repository for plotting and visualizing data
https://github.com/gonum/plot - Gonum Numerical Packages
https://www.gonum.org/ - Stránky projektu MinIO
https://min.io/ - MinIO Quickstart Guide
https://docs.min.io/docs/minio-quickstart-guide.html - MinIO Go Client API Reference
https://docs.min.io/docs/golang-client-api-reference - MinIO Python Client API Reference
https://docs.min.io/docs/python-client-api-reference.html - Performance at Scale: MinIO Pushes Past 1.4 terabits per second with 256 NVMe Drives
https://blog.min.io/performance-at-scale-minio-pushes-past-1–3-terabits-per-second-with-256-nvme-drives/ - Benchmarking MinIO vs. AWS S3 for Apache Spark
https://blog.min.io/benchmarking-apache-spark-vs-aws-s3/ - MinIO Client Quickstart Guide
https://docs.min.io/docs/minio-client-quickstart-guide.html - Analýza kvality zdrojových kódů Minia
https://goreportcard.com/report/github.com/minio/minio - This is MinIO
https://www.youtube.com/watch?v=vF0lQh0XOCs - Running MinIO Standalone
https://www.youtube.com/watch?v=dIQsPCHvHoM - „Amazon S3 Compatible Storage in Kubernetes“ – Rob Girard, Principal Tech Marketing Engineer, Minio
https://www.youtube.com/watch?v=wlpn8K0jJ4U - Ginkgo
http://onsi.github.io/ginkgo/ - Gomega
https://onsi.github.io/gomega/ - Ginkgo's Preferred Matcher Library na GitHubu
https://github.com/onsi/gomega/ - Provided Matchers
http://onsi.github.io/gomega/#provided-matchers - Dokumentace k balíčku goexpect
https://godoc.org/github.com/google/goexpect - Balíček goexpect
https://github.com/google/goexpect - Balíček go-expect
https://github.com/Netflix/go-expect - Balíček gexpect
https://github.com/ThomasRooney/gexpect - Expect (originál naprogramovaný v TCL)
https://core.tcl-lang.org/expect/index - Expect (Wikipedia)
https://en.wikipedia.org/wiki/Expect - Pexpect
https://pexpect.readthedocs.io/en/stable/ - Golang SSH Client: Multiple Commands, Crypto & Goexpect Examples
http://networkbit.ch/golang-ssh-client/ - goblin na GitHubu
https://github.com/franela/goblin - Mocha framework
https://mochajs.org/ - frisby na GitHubu
https://github.com/verdverm/frisby - package frisby
https://godoc.org/github.com/verdverm/frisby - Frisby alternatives and similar packages (generováno)
https://go.libhunt.com/frisby-alternatives - Cucumber for golang
https://github.com/DATA-DOG/godog - How to Use Godog for Behavior-driven Development in Go
https://semaphoreci.com/community/tutorials/how-to-use-godog-for-behavior-driven-development-in-go - Comparative Analysis Of GoLang Testing Frameworks
https://www.slideshare.net/DushyantBhalgami/comparative-analysis-of-golang-testing-frameworks - A Quick Guide to Testing in Golang
https://caitiem.com/2016/08/18/a-quick-guide-to-testing-in-golang/ - Tom's Obvious, Minimal Language.
https://github.com/toml-lang/toml - xml.org
http://www.xml.org/ - Soubory .properties
https://en.wikipedia.org/wiki/.properties - Soubory INI
https://en.wikipedia.org/wiki/INI_file - JSON to YAML
https://www.json2yaml.com/ - Data Format Converter
https://toolkit.site/format.html - Viper na GitHubu
https://github.com/spf13/viper - GoDotEnv na GitHubu
https://github.com/joho/godotenv - The fantastic ORM library for Golang
http://gorm.io/ - Dokumentace k balíčku gorilla/mux
https://godoc.org/github.com/gorilla/mux - Gorilla web toolkitk
http://www.gorillatoolkit.org/ - Metric types
https://prometheus.io/docs/concepts/metric_types/ - Histograms with Prometheus: A Tale of Woe
http://linuxczar.net/blog/2017/06/15/prometheus-histogram-2/ - Why are Prometheus histograms cumulative?
https://www.robustperception.io/why-are-prometheus-histograms-cumulative - Histograms and summaries
https://prometheus.io/docs/practices/histograms/ - Instrumenting Golang server in 5 min
https://medium.com/@gsisimogang/instrumenting-golang-server-in-5-min-c1c32489add3 - Semantic Import Versioning in Go
https://www.aaronzhuo.com/semantic-import-versioning-in-go/ - Sémantické verzování
https://semver.org/ - Getting started with Go modules
https://medium.com/@fonseka.live/getting-started-with-go-modules-b3dac652066d - Create projects independent of $GOPATH using Go Modules
https://medium.com/mindorks/create-projects-independent-of-gopath-using-go-modules-802260cdfb51o - Anatomy of Modules in Go
https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16 - Modules
https://github.com/golang/go/wiki/Modules - Go Modules Tutorial
https://tutorialedge.net/golang/go-modules-tutorial/ - Module support
https://golang.org/cmd/go/#hdr-Module_support - Go Lang: Memory Management and Garbage Collection
https://vikash1976.wordpress.com/2017/03/26/go-lang-memory-management-and-garbage-collection/ - Golang Internals, Part 4: Object Files and Function Metadata
https://blog.altoros.com/golang-part-4-object-files-and-function-metadata.html - What is REPL?
https://pythonprogramminglanguage.com/repl/ - What is a REPL?
https://codewith.mu/en/tutorials/1.0/repl - Programming at the REPL: Introduction
https://clojure.org/guides/repl/introduction - What is REPL? (Quora)
https://www.quora.com/What-is-REPL - Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
https://www.root.cz/clanky/gorilla-repl-interaktivni-prostredi-pro-programovaci-jazyk-clojure/ - Read-eval-print loop (Wikipedia)
https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop - Vim as a Go (Golang) IDE using LSP and vim-go
https://octetz.com/posts/vim-as-go-ide - gopls
https://github.com/golang/go/wiki/gopls - IDE Integration Guide
https://github.com/stamblerre/gocode/blob/master/docs/IDE_integration.md - How to instrument Go code with custom expvar metrics
https://sysdig.com/blog/golang-expvar-custom-metrics/ - Golang expvar metricset (Metricbeat Reference)
https://www.elastic.co/guide/en/beats/metricbeat/7.x/metricbeat-metricset-golang-expvar.html - Package expvar
https://golang.org/pkg/expvar/#NewInt - Java Platform Debugger Architecture: Overview
https://docs.oracle.com/en/java/javase/11/docs/specs/jpda/jpda.html - The JVM Tool Interface (JVM TI): How VM Agents Work
https://www.oracle.com/technetwork/articles/javase/index-140680.html - JVM Tool Interface Version 11.0
https://docs.oracle.com/en/java/javase/11/docs/specs/jvmti.html - Creating a Debugging and Profiling Agent with JVMTI
http://www.oracle.com/technetwork/articles/javase/jvmti-136367.html - JVM TI (Wikipedia)
http://en.wikipedia.org/wiki/JVM_TI - IBM JVMTI extensions
http://publib.boulder.ibm.com/infocenter/realtime/v2r0/index.jsp?topic=%2Fcom.ibm.softrt.doc%2Fdiag%2Ftools%2Fjvmti_extensions.html - Go & cgo: integrating existing C code with Go
http://akrennmair.github.io/golang-cgo-slides/#1 - Using cgo to call C code from within Go code
https://wenzr.wordpress.com/2018/06/07/using-cgo-to-call-c-code-from-within-go-code/ - Package trace
https://golang.org/pkg/runtime/trace/ - Introducing HTTP Tracing
https://blog.golang.org/http-tracing - Command trace
https://golang.org/cmd/trace/ - A StreamLike, Immutable, Lazy Loading and smart Golang Library to deal with slices
https://github.com/wesovilabs/koazee - Funkce vyššího řádu v knihovně Underscore
https://www.root.cz/clanky/funkce-vyssiho-radu-v-knihovne-underscore/ - Delve: a debugger for the Go programming language.
https://github.com/go-delve/delve - Příkazy debuggeru Delve
https://github.com/go-delve/delve/tree/master/Documentation/cli - Debuggery a jejich nadstavby v Linuxu
http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu/ - Debuggery a jejich nadstavby v Linuxu (2. část)
http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-2-cast/ - Debuggery a jejich nadstavby v Linuxu (3): Nemiver
http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-3-nemiver/ - Debuggery a jejich nadstavby v Linuxu (4): KDbg
http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-4-kdbg/ - Debuggery a jejich nadstavby v Linuxu (5): ladění aplikací v editorech Emacs a Vim
http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-5-ladeni-aplikaci-v-editorech-emacs-a-vim/ - Debugging Go Code with GDB
https://golang.org/doc/gdb - Debugging Go (golang) programs with gdb
https://thornydev.blogspot.com/2014/01/debugging-go-golang-programs-with-gdb.html - GDB – Dokumentace
http://sourceware.org/gdb/current/onlinedocs/gdb/ - GDB – Supported Languages
http://sourceware.org/gdb/current/onlinedocs/gdb/Supported-Languages.html#Supported-Languages - GNU Debugger (Wikipedia)
https://en.wikipedia.org/wiki/GNU_Debugger - The LLDB Debugger
http://lldb.llvm.org/ - Debugger (Wikipedia)
https://en.wikipedia.org/wiki/Debugger - 13 Linux Debuggers for C++ Reviewed
http://www.drdobbs.com/testing/13-linux-debuggers-for-c-reviewed/240156817 - Go is on a Trajectory to Become the Next Enterprise Programming Language
https://hackernoon.com/go-is-on-a-trajectory-to-become-the-next-enterprise-programming-language-3b75d70544e - Go Proverbs: Simple, Poetic, Pithy
https://go-proverbs.github.io/ - Handling Sparse Files on Linux
https://www.systutorials.com/136652/handling-sparse-files-on-linux/ - Gzip (Wikipedia)
https://en.wikipedia.org/wiki/Gzip - Deflate
https://en.wikipedia.org/wiki/DEFLATE - 10 tools written in Go that every developer needs to know
https://gustavohenrique.net/en/2019/01/10-tools-written-in-go-that-every-dev-needs-to-know/ - Hexadecimální prohlížeče a editory s textovým uživatelským rozhraním
https://www.root.cz/clanky/hexadecimalni-prohlizece-a-editory-s-textovym-uzivatelskym-rozhranim/ - Hex dump
https://en.wikipedia.org/wiki/Hex_dump - Rozhraní io.ByteReader
https://golang.org/pkg/io/#ByteReader - Rozhraní io.RuneReader
https://golang.org/pkg/io/#RuneReader - Rozhraní io.ByteScanner
https://golang.org/pkg/io/#ByteScanner - Rozhraní io.RuneScanner
https://golang.org/pkg/io/#RuneScanner - Rozhraní io.Closer
https://golang.org/pkg/io/#Closer - Rozhraní io.Reader
https://golang.org/pkg/io/#Reader - Rozhraní io.Writer
https://golang.org/pkg/io/#Writer - Typ Strings.Reader
https://golang.org/pkg/strings/#Reader - VACUUM (SQL)
https://www.sqlite.org/lang_vacuum.html - VACUUM (Postgres)
https://www.postgresql.org/docs/8.4/sql-vacuum.html - go-cron
https://github.com/rk/go-cron - gocron
https://github.com/jasonlvhit/gocron - clockwork
https://github.com/whiteShtef/clockwork - clockwerk
https://github.com/onatm/clockwerk - JobRunner
https://github.com/bamzi/jobrunner - Rethinking Cron
https://adam.herokuapp.com/past/2010/4/13/rethinking_cron/ - In the Beginning was the Command Line
https://web.archive.org/web/20180218045352/http://www.cryptonomicon.com/beginning.html - repl.it (REPL pro různé jazyky)
https://repl.it/languages - GOCUI – Go Console User Interface (celé uživatelské prostředí, nejenom input box)
https://github.com/jroimartin/gocui - Read–eval–print loop
https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop - go-prompt
https://github.com/c-bata/go-prompt - readline
https://github.com/chzyer/readline - A pure golang implementation for GNU-Readline kind library
https://golangexample.com/a-pure-golang-implementation-for-gnu-readline-kind-library/ - go-readline
https://github.com/fiorix/go-readline - 4 Python libraries for building great command-line user interfaces
https://opensource.com/article/17/5/4-practical-python-libraries - prompt_toolkit 2.0.3 na PyPi
https://pypi.org/project/prompt_toolkit/ - python-prompt-toolkit na GitHubu
https://github.com/jonathanslenders/python-prompt-toolkit - The GNU Readline Library
https://tiswww.case.edu/php/chet/readline/rltop.html - GNU Readline (Wikipedia)
https://en.wikipedia.org/wiki/GNU_Readline - readline — GNU readline interface (Python 3.x)
https://docs.python.org/3/library/readline.html - readline — GNU readline interface (Python 2.x)
https://docs.python.org/2/library/readline.html - GNU Readline Library – command line editing
https://tiswww.cwru.edu/php/chet/readline/readline.html - gnureadline 6.3.8 na PyPi
https://pypi.org/project/gnureadline/ - Editline Library (libedit)
http://thrysoee.dk/editline/ - Comparing Python Command-Line Parsing Libraries – Argparse, Docopt, and Click
https://realpython.com/comparing-python-command-line-parsing-libraries-argparse-docopt-click/ - libedit or editline
http://www.cs.utah.edu/~bigler/code/libedit.html - WinEditLine
http://mingweditline.sourceforge.net/ - rlcompleter — Completion function for GNU readline
https://docs.python.org/3/library/rlcompleter.html - rlwrap na GitHubu
https://github.com/hanslub42/rlwrap - rlwrap(1) – Linux man page
https://linux.die.net/man/1/rlwrap - readline(3) – Linux man page
https://linux.die.net/man/3/readline - history(3) – Linux man page
https://linux.die.net/man/3/history - Dokumentace k balíčku oglematchers
https://godoc.org/github.com/jacobsa/oglematchers - 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 - Goroutine IDs
https://blog.sgmansfield.com/2015/12/goroutine-ids/ - Different ways to pass channels as arguments in function in go (golang)
https://stackoverflow.com/questions/24868859/different-ways-to-pass-channels-as-arguments-in-function-in-go-golang - justforfunc #22: using the Go execution tracer
https://www.youtube.com/watch?v=ySy3sR1LFCQ - 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 - The zero value of a slice is not nil
https://stackoverflow.com/questions/30806931/the-zero-value-of-a-slice-is-not-nil - Go-tcha: When nil != nil
https://dev.to/pauljlucas/go-tcha-when-nil–nil-hic - Nils in Go
https://www.doxsey.net/blog/nils-in-go