Hlavní navigace

Kooperace mezi kódem psaným v Go a C: cgo

Pavel Tišnovský

Dnes si vysvětlíme, jak je možné z Go volat funkce vytvořené v jazyku C. Jedná se o relativně komplikovanou problematiku, protože je například nutné korektně uvolňovat paměť, provádět přetypování proměnných atd.

Doba čtení: 35 minut

Sdílet

11. Uvolnění paměti před jejím použitím

12. Dvojí zavolání funkce C.free()

13. Nepřímé čtení proměnné errno

14. Deklarace céčkovské funkce v komentáři

15. Práce s řetězci alokovanými funkcemi jazyka C

16. Prohlédnutí kódu generovaného překladačem jazyka Go

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

18. Odkazy na Internetu

1. Kooperace mezi kódem psaným v Go a C: cgo

Prozatím jsme se v seriálu o programovacím jazyce Go zabývali především samotným programovacím jazykem Go, jeho knihovnami a dostupnými pomocnými nástroji. V předchozích dvou částech [1] [2] jsme si navíc připomenuli některé poměrně zásadní rozdíly mezi jazyky C a Go, které mohou zajímat především ty programátory, kteří na Go přechází právě z jazyka C. A dnes na toto téma nepřímo navážeme, protože si na několika demonstračních příkladech ukážeme kooperaci mezi programovým kódem napsaným v Go na jedné straně a kódem vyvinutým v jazyku C na straně druhé.

Již v základní sadě nástrojů programovacího jazyka Go mají vývojáři k dispozici prakticky všechny utility a knihovny potřebné proto, aby se z kódu vyvíjeného v jazyce Go mohly volat funkce naprogramované v C a uložené například v linkovaných knihovnách. Díky tomu je kooperace mezi Go a C relativně snadná, resp. přesněji řečeno nám existence potřebných nástrojů umožní se soustředit na složitější a pro běh aplikací i podstatnější problémy – zejména jak správně konvertovat parametry volaných funkcí, jak zpracovat jejich návratové hodnoty popř. chybové hodnoty a především pak, jak korektně pracovat s operační pamětí. Při kooperaci mezi Go a C totiž zásadní problém spočívá v tom, že v jazyce Go se alokovaná paměť uvolňuje automaticky správcem paměti (garbage collector – GC), zatímco v jazyce C se pochopitelně o alokaci i dealokaci paměti musí postarat sám programátor.

2. Speciální balíček nazvaný „C“

Při práci s funkcemi vytvořenými v programovacím jazyku C nebo i s celými knihovnami musíme být schopni tyto funkce nějakým způsobem volat z kódu napsaného v jazyku Go. Připomeňme si, že v Go platí následující pravidla pro volání funkcí (tato pravidla jsem zjednodušil a poněkud zkrátil):

  1. Funkce deklarované v rámci toho samého balíčku se volají přímým zápisem jejich jména. Přitom nezáleží na tom, zda je první písmeno v názvu funkce velké či malé. Tatáž pravidla platí i pro metody, akorát je u nich nutné uvést i jejích příjemce (receiver).
  2. Funkce deklarované v jiném balíčku se volají zápisemjméno_balíčku.JménoFunkce, přičemž jméno funkce musí začínat velkým písmenem. Pokud jméno funkce začíná písmenem malým, je funkce považována za privátní v rámci svého balíčku (kde je deklarována) a nebude ji možné z jiného balíčku přímo zavolat. Tímto způsobem se v Go řídí viditelnost funkcí a popř. i povolují či zakazují některé optimalizace prováděné překladačem.
  3. Balíčky s volanými funkcemi musí být explicitně importovány a v rámci importu je možné zadat i alias jména balíčku. Platí to i naopak – importovat je možné pouze ty balíčky, které jsou skutečně použity, ovšem s výjimkou dále zmíněného pseudobalíčku „C“.

V programovacím jazyku C však platí dosti odlišná pravidla. Zejména se zde nepoužívá koncept balíčků, ale namísto toho bývá (podle nastavení projektu) každý zdrojový soubor samostatně překládanou jednotkou, v níž lze deklarovat, které funkce mají být viditelné (exportované) z jiných modulů a které nikoli (static, ovšem toto klíčové slovo má více významů). Navíc zde neexistuje pravidlo, že se viditelnost funkcí určuje podle prvního písmene v jejich názvu.

Aby bylo možné i ze zdrojového kódu napsaného v Go volat céčkovské funkce, je překladačem jazyka Go podporován speciální balíček (spíše pseudobalíček) nazvaný „C“, jehož vlastnosti a chování jsou odlišné od standardních balíčků programovacího jazyka Go. S podrobnějšími informacemi o tomto pseudobalíčku se seznámíme v navazujících kapitolách.

Poznámka: v dalším textu sice budeme stále mluvit o céčkových funkcích, ovšem ve skutečnosti mohou být knihovny (.dll, .so, …) vygenerovány i z dalších jazyků, a to například včetně Fortranu.

3. Speciální balíček nazvaný „C“

Podívejme se nyní na základní vlastnost pseudobalíčku „C“. Tento balíček můžeme importovat (syntaxe je shodná s běžnými balíčky), a to dokonce bez toho, aby byl vůbec ve zdrojovém kódu reálně použit. To znamená, že následující zdrojový kód je zcela korektní a může být bez chyb přeložen překladačem jazyka Go:

package main
 
import "C"
 
func main() {
}

Tato výjimka ovšem platí jen a pouze pro pseudobalíček „C“. Pokud se totiž pokusíme naimportovat běžný balíček jazyka Go, který nakonec nepoužijeme, vypíše překladač chybu:

package main
 
import "fmt"
 
func main() {
}

Při pokusu o překlad se (správně) detekuje, že se importuje baliček, který není v kódu použit:

# command-line-arguments
./02_import_fmt.go:3:8: imported and not used: "fmt"

4. Volání funkcí deklarovaných v C z kódu psaného v Go

Funkce, které byly vytvořené v céčku popř. funkce uložené v některé céčkové (nativní) knihovně, se v programovacím jazyce Go volají následujícím způsobem:

C.jméno_funkce(parametry_funkce)
Poznámka: povšimněte si použití jména balíčku C před jménem funkce. Osobně na tuto nutnost poměrně často zapomínám, což je samozřejmě chyba snadno detekovatelná překladačem.

Další z odlišností mezi pseudobalíčkem „C“ a ostatními balíčky spočívá v tom, že z balíčku „C“ je možné volat i ty funkce, které začínají malým písmenem (což jsou prakticky všechny funkce ze standardní knihovny). Teoreticky se tedy můžeme pokusit zavolat funkci puts() ze standardní céčkové knihovny (viz též man 3 puts):

package main
 
import "C"
 
func main() {
        C.puts("Hello world!")
}

Pokus o překlad se ovšem v tomto případě nezdaří, protože překladač nedokáže zjistit žádné podrobnější informace o volané funkci puts() (počet a typ parametrů atd.):

# command-line-arguments
./03_missing_include.go:6:2: could not determine kind of name for C.puts

Stojíme tedy před tímto problémem: máme zavolat funkci deklarovanou mimo samotný jazyk Go o které tedy překladač nemá k dispozici žádné podrobnější informace. Na tomto místě je nutné použít poněkud špinavý trik – vložit příkaz céčkového preprocesoru #include do poznámky umístěné před příkaz pro import pseudobalíčku „C“:

package main
 
// #include <stdio.h>
import "C"
 
func main() {
        C.puts("Hello world!")
}
Poznámka: s použitím komentářů pro další účely jsme se již setkali, například při práci s formátem JSON (deserializace) atd. V každém případě je nutno podotknout, že se nejedná o nejlépe navržený rys programovacího jazyka Go.

5. Konverze řetězce z Go do C

Nyní již překladač programovacího jazyka Go volanou funkci správně rozpozná (a zná i její parametry), ovšem při pokusu o překlad vypíše odlišnou chybu, která se týká toho, že se snažíme zkombinovat řetězec deklarovaný v jazyce Go s funkcí akceptující céčkovský řetězec (ukončený nulou):

# command-line-arguments
./04_puts_go_string.go:7:16: cannot use "Hello world!" (type string) as type *_Ctype_char in argument to _Cfunc_puts

Řetězce v jazyce Go se v mnoha ohledech odlišují od céčkovských řetězců; nejedná se o stejný datový typ. Musíme tedy být schopni provést převod mezi neměnným řetězcem v jazyce Go a nulou ukončeným řetězcem jazyka C. Pro tuto konverzi lze použít funkci nazvanou CString, která je deklarovaná v rámci pseudobalíčku „C“:

cs := C.CString("Hello world!")

Upravený program, který po svém spuštění vypíše na standardní výstup řetězec „Hello world!“ tedy může vypadat takto:

package main
 
// #include <stdio.h>
import "C"
 
func main() {
        cs := C.CString("Hello world!")
        C.puts(cs)
}

Tento program je již přeložitelný a spustitelný:

Hello world!
Poznámka: ve skutečnosti ovšem není chování programu zcela korektní, protože funkce CString() skutečně vytvoří céčkovský řetězec se všemi vlastnostmi takového řetězce. A jednou z důležitých vlastností céčkovských řetězců je fakt, že se o jejich uvolnění z operační paměti musí postarat programátor a nikoli automatický správce paměti. Typicky se používá funkce free(), pokud ovšem není alokace provedena například funkcí alloca(). Toto uvolnění jsme v našem demonstračním příkladu (alespoň prozatím) neprovedli, ovšem k tomuto důležitému tématu se později vrátíme v navazujících kapitolách.

6. Převody celočíselných datových typů mezi Go a C

Vyzkoušejme si nyní zavolat odlišnou céčkovskou funkci, konkrétně funkci nazvanou abs (viz též man 3 abs). Tato funkce akceptuje jeden parametr typu int a vrací taktéž hodnotu typu int. I zde musíme provést přetypování (int v Go na int v C, což pro překladač nejsou shodné typy). Konkrétně se převod Go int → C int provede s využitím funkce C.int(), opět patřící do pseudobalíčku „C“:

y := C.abs(C.int(x))

Výsledek céčkovské funkce abs můžeme použít přímo (alespoň v některých případech), a to díky automatickému odvození typu lokální proměnné y:

package main
 
// #include <stdlib.h>
import "C"
import "fmt"
 
func main() {
        x := -10
        y := C.abs(C.int(x))
        fmt.Printf("%v\n", y)
}

Tento příklad po svém překladu a spuštění správně vypíše hodnotu 10:

10

Pokud ovšem budeme chtít použít výsledek (návratovou hodnotu) céčkovské funkce abs v jazyce Go, je výhodnější provést explicitní převod vrácené hodnoty na typ int. To lze provést například takto:

var y int = int(C.abs(C.int(x)))
Poznámka: připomeňme si, že programovací jazyk Go nikdy neprovádí automatické konverze mezi různými datovými typy, a to ani v případě, kdy se jedná o triviální operaci.

Upravený zdrojový kód demonstračního příkladu vypadá následovně:

package main
 
// #include <stdlib.h>
import "C"
import "fmt"
 
func main() {
        x := -10
        var y int = int(C.abs(C.int(x)))
        fmt.Printf("%v\n", y)
}

I tento demonstrační příklad po svém překladu a spuštění správně vypíše hodnotu 10:

10

7. Přilinkování další nativní knihovny

Nyní již víme, jakým způsobem je možné volat funkce ze základní knihovny programovacího jazyka C (stdlib, stdio, string atd.). Vyzkoušejme si tedy poněkud odlišný příklad, konkrétně volání funkce sinf() z knihovny math (viz též man 3 sinf). Tato funkce akceptuje parametr typu float, který snadno získáme konverzní funkcí C.float(). Výsledek budeme konvertovat zpět standardní konverzní funkcí float32:

y := float32(C.sinf(C.float(x)))

První verze příkladu by tedy mohla vypadat následovně:

package main
 
// #include <math.h>
import "C"
import "fmt"
 
func main() {
        x := 3.1415927 / 6.0
        y := float32(C.sinf(C.float(x)))
        fmt.Printf("%v\n", y)
}

Pokud se předchozí příklad pokusíme přeložit, vypíše se chybové hlášení informující o tom, že funkce sinf nebyla nalezena, a to konkrétně linkerem (to tedy znamená, že překladač neměl s voláním této funkce problémy, ovšem linker neví, kde se tato funkce nachází):

# command-line-arguments
/tmp/ramdisk/go-build217505370/b001/_x002.o: In function `_cgo_15d71de7baa2_Cfunc_sinf':
/tmp/go-build/cgo-gcc-prolog:45: undefined reference to `sinf'
collect2: error: ld returned 1 exit status

Podobné chybové hlášení by se vypsalo i při pokusu o překlad a slinkování běžného programu psaného v jazyce C, který by funkci sinf() volal. Důvod je jednoduchý – linkeru musíme oznámit, že má při sestavování výsledného binárního souboru použít i knihovnu m, která je na disku uložena v souboru libm.verze.so. V případě programovacího jazyka C je to jednoduché, protože máme přístup k příkazovému řádku, z něhož voláme cpp, cc a ld (popř. gcc), ovšem pokud budeme chtít knihovnu m použít i z Go, musíme parametry předávané linkeru přímo vložit do poznámky před import pseudobalíčku „C“:

// #cgo LDFLAGS: -lm

Upravený zdrojový kód bude vypadat následovně:

package main
 
// #include <math.h>
// #cgo LDFLAGS: -lm
import "C"
import "fmt"
 
func main() {
        x := 3.1415927 / 6.0
        y := float32(C.sinf(C.float(x)))
        fmt.Printf("%v\n", y)
}

Nyní je již možné program přeložit i spustit:

0.5

8. Manuální uvolňování paměti

Dalším problémem, který je nutné vyřešit, je manuální uvolňování paměti. Týká se to především céčkových řetězců popř. céčkových polí vzniklých konverzí z řetězců/polí napsaných v programovacím jazyku Go.

Podívejme se na následující příklad, v němž se v nekonečné smyčce vypisuje zpráva na standardní výstup. Zpráva je získána konverzí původního řetězce v Go do nulou ukončeného céčkového řetězce. Tento řetězec není z paměti uvolněn, a to ani automaticky (leží mimo dosah GC) ani manuálně:

package main
 
// #include <stdio.h>
import "C"
 
func main() {
        for {
                cs := C.CString("Hello world!")
                C.puts(cs)
        }
}

Příklad je vhodné spustit tak, aby se zprávy zahazovaly (je to rychlejší, než jejích zobrazení na terminálu):

$ go run 10_oom.go < /dev/null

S využitím nástroje top se lze snadno přesvědčit, že paměť alokovaná novým procesem bude neustále růst; na konci většinou proces ukončí OOM killer (podle nastavení systému).

Pokud ovšem program upravíme takovým způsobem, že se řetězec bude uvolňovat, bude paměť alokovaná procesem prakticky stále konstantní:

package main
 
// #include <stdio.h>
// #include <stdlib.h>
import "C"
import "unsafe"
 
func main() {
        for {
                cs := C.CString("Hello world!")
                C.puts(cs)
                C.free(unsafe.Pointer(cs))
        }
}
Poznámka: opět je vhodné se o výše uvedeném tvrzení přesvědčit, typicky s využitím nástroje top.

9. Upravený příklad pro tisk řetězce na standardní výstup

Demonstrační příklad, který jsme si uvedli v páté kapitole, je tedy vhodné upravit takovým způsobem, aby se céčkový řetězec po použití funkcí puts() explicitně uvolnil z paměti:

package main
 
// #include <stdio.h>
// #include <stdlib.h>
import "C"
import "unsafe"
 
func main() {
        cs := C.CString("Hello world!")
        C.puts(cs)
        C.free(unsafe.Pointer(cs))
}

Výsledek bude shodný s předchozím příkladem:

Hello world!
Poznámka: ve skutečnosti se zrovna v tomto případě nestane nic vážného pokud nebude řetězec explicitně z paměti uvolněn, protože se dealokace provede při ukončování procesu. Ovšem obecně je dobré na tuto problematiku nezapomínat – jedná se o jedno z mála oblastí, v nichž se Go používá a v nichž je nutné správu paměti provádět ručně.

10. Použití deklarace defer při uvolňování paměti

Jednou z velmi dobrých vlastností programovacího jazyka Go je deklarace defer, která nám umožňuje specifikovat programový kód, který se provede při návratu z aktuálně prováděné funkce. Nic nám samozřejmě nebrání použít defer i pro uvolnění céčkového řetězce (či jiné céčkové paměťové struktury) z operační paměti. Navíc bude zaručeno, že se funkce free() zavolá ve všech větvích funkce (pokud má funkce více výstupních bodů) a navíc že se nezavolá vícekrát (například omylem):

package main
 
// #include <stdio.h>
// #include <stdlib.h>
import "C"
import "unsafe"
 
func main() {
        cs := C.CString("Hello world!")
        defer C.free(unsafe.Pointer(cs))
        C.puts(cs)
}

Výsledek běhu tohoto příkladu bude shodný s příkladem předchozím:

Hello world!

11. Uvolnění paměti před jejím použitím

Kvůli tomu, že se o paměť používanou na straně céčka musíme explicitně starat, může nastat situace, kdy se do kódu zanesou poměrně typické „céčkovské“ chyby, například dealokace paměti ještě předtím, než je obsah této paměti použit. Výsledek je v tomto případě nedefinovaný – program může zhavarovat, může zdánlivě běžet bez chyby nebo bude obsah paměti změněn (což je u Go pravděpodobnější, než v čistém céčku):

package main
 
// #include <stdio.h>
// #include <stdlib.h>
import "C"
import "unsafe"
 
func main() {
        cs := C.CString("Hello world!")
        C.free(unsafe.Pointer(cs))
        C.puts(cs)
}

Může se stát, že tento program zhavaruje, ovšem pravděpodobněji na standardní výstup vypíše náhodný řetězec (a záleží jen na náhodě, jak bude dlouhý, tj. kdy se narazí na první nulový bajt):

@#@

12. Dvojí zavolání funkce C.free()

Druhou poměrně typickou chybou je dvojí volání funkce free(), přičemž první volání provede korektní dealokaci, ale druhé volání se pokusí dealokovat stejný blok paměti. Ani tento problém nedokáže překladač jazyka Go detekovat:

package main
 
// #include <stdio.h>
// #include <stdlib.h>
import "C"
import "unsafe"
 
func main() {
        cs := C.CString("Hello world!")
        C.puts(cs)
        C.free(unsafe.Pointer(cs))
        C.free(unsafe.Pointer(cs))
}

V tomto případě většinou dojde k okamžitému pádu aplikace:

SIGABRT: abort
PC=0x7f4cc7251c37 m=0 sigcode=18446744073709551610
 
goroutine 0 [idle]:
runtime: unknown pc 0x7f4cc7251c37
stack: frame={sp:0x7ffe1f450d08, fp:0x0} stack=[0x7ffe1ec52188,0x7ffe1f4511b0)
 
00007ffe1f450db8:  0000000000000000  0000000000000000
00007ffe1f450dc8:  000000770000006e  0000000000000000
00007ffe1f450dd8:  00007ffe1f450dff  000000000043bc5f <runtime.findfunc+47>
00007ffe1f450de8:  000000000044ab31 <runtime.goexit+1>  000000000000007c
00007ffe1f450df8:  00007ffe1f451100  00000000004405e8 <runtime.gentraceback+6184>
 
goroutine 1 [syscall]:
runtime.cgocall(0x451a20, 0xc000038730, 0xc000de3040)
        /opt/go/src/runtime/cgocall.go:128 +0x5e fp=0xc000038700 sp=0xc0000386c8 pc=0x403c3e
main._Cfunc_free(0xde31a0)
        _cgo_gotypes.go:59 +0x41 fp=0xc000038730 sp=0xc000038700 pc=0x4516d1
main.main.func2(0xde31a0)
        /home/tester/temp/go-root/article_36/18_double_free.go:12 +0x56 fp=0xc000038768 sp=0xc000038730 pc=0x451966
main.main()
        /home/tester/temp/go-root/article_36/18_double_free.go:12 +0x65 fp=0xc000038798 sp=0xc000038768 pc=0x451885
runtime.main()
        /opt/go/src/runtime/proc.go:201 +0x207 fp=0xc0000387e0 sp=0xc000038798 pc=0x425727
runtime.goexit()
        /opt/go/src/runtime/asm_amd64.s:1333 +0x1 fp=0xc0000387e8 sp=0xc0000387e0 pc=0x44ab31
Poznámka: možná si říkáte, že takto nápadná chyba se ve zdrojovém kódu snadno objeví a opraví. Ovšem aplikace bývají složité a pokud se ukazatele na pole/struktury/řetězce předávají do jiných funkcí a není zřejmé, kdo je „vlastník“ dané paměti, může relativně snadno i k této chybě dojít.

13. Nepřímé čtení proměnné errno

Další velmi užitečnou funkcí pseudobalíčku „C“ je práce s proměnnou errno (viz též man 3 errno). Tato proměnná, kterou céčkoví programátoři dobře znají, obsahuje kód poslední chyby, přičemž pro každý celočíselný kód chyby existuje i příslušná symbolická konstanta: EACCES, ECANCELED, ENOENT atd.

Kód poslední chyby můžeme přečíst i idiomatickým kódem v Go – získáním většího množství návratových kódů funkce. Ukažme si konkrétní příklad, a to volání matematické funkce pro výpočet druhé odmocniny. Tato céčková funkce vrací vypočtený výsledek a současně může nastavit proměnnou errno v případě, kdy se snažíme o výpočet druhé odmocniny ze záporného čísla (s komplexními čísly se zde nepracuje). V Go ovšem můžeme z této funkce získat dvě hodnoty – jak vypočtenou druhou odmocninu, tak i objekt představující chybu (popř. nil pokud k chybě nedošlo):

y, err := C.sqrt(C.double(nějaké číslo))

Z následujícího úryvku kódu je zřejmé, že se jedná o kratší a lépe čitelný kód, než explicitní přístup k proměnné errno:

package main
 
// #include <math.h>
// #cgo LDFLAGS: -lm
import "C"
import "fmt"
 
func main() {
        y, err := C.sqrt(C.double(100.0))
        fmt.Printf("result=%v err=%v\n", y, err)
 
        y, err = C.sqrt(C.double(-1.0))
        fmt.Printf("result=%v err=%v\n", y, err)
 
        y, err = C.sqrt(C.double(100.0))
        fmt.Printf("result=%v err=%v\n", y, err)
}

Výsledek běhu tohoto demonstračního příkladu:

result=10 err=<nil.h>
result=NaN err=numerical argument out of domain
result=10 err=<nil.h>
Poznámka: povšimněte si, že se ve druhém případě skutečně správně detekovala a vyhodnotila chyba při výpočtu.

14. Deklarace céčkovské funkce v komentáři

Podívejme se ještě na jednu možnost, kterou nám jazyk Go (a nástroj cgo) nabízí. V komentáři uvedeném před importem pseudobalíčku „C“ je možné deklarovat jak céčkovské datové typy pomocí typedef, tak i celé funkce. Tyto funkce jsou ihned volatelné z dalšího programového kódu. Můžeme se o tom velmi snadno přesvědčit:

package main
 
// int add(int a, int b) {
//     return a+b;
// }
import "C"
import "fmt"
 
func main() {
        x := C.add(C.int(1), C.int(2))
        fmt.Printf("result=%x\n", x)
}

15. Práce s řetězci alokovanými funkcemi jazyka C

Ukažme si na závěr, jak vlastně můžeme (explicitně) pracovat s řetězci alokovanými funkcemi programovacího jazyka C. Pro alokaci řetězce můžeme použít buď funkci malloc nebo calloc. V případě, že se má jednat o řetězec s maximálně devatenácti znaky a ukončující nulou, použijeme volání:

s := C.calloc(20, 1)
Poznámka: ideální a korektnější by bylo nahradit hodnotu 1 za sizeof(char), ovšem dnes je Go podporováno na architekturách, kde je tato velikost rovna jedné.

Takový řetězec je možné předat například funkci fgets, ovšem po správném přetypování:

char_ptr := (*C.char)(s)
C.fgets(char_ptr, 20, C.stdin)
Poznámka: přetypování je zde vyžadováno, protože v Go je rozdíl mezi typem unsafe.Pointer (což odpovídá void *) a ukazatelem na první znak řetězce, což je datový typ vyžadovaný funkcí fgets.

Samozřejmě nesmíme zapomenout ani na uvolnění řetězce z paměti (zde nám ovšem void * naopak vyhovuje):

C.free(s)

Úplný zdrojový kód, který přečte řetězec ze standardního vstupu a následně vypíše jeho obsah, může vypadat takto:

package main
 
// #include <stdio.h>
// #include <stdlib.h>
import "C"
import "fmt"
 
func main() {
        fmt.Print("? ")
        s := C.calloc(20, 1)
        char_ptr := (*C.char)(s)
        C.fgets(char_ptr, 20, C.stdin)
        fmt.Printf("result=%v\n", C.GoString(char_ptr))
        C.free(s)
}

16. Prohlédnutí kódu generovaného překladačem jazyka Go

V některých případech může být zajímavé si prohlédnout céčkový kód generovaný překladačem jazyka Go před jeho předáním do céčkového překladače. Pro tento účel můžeme zavolat nástroj cgo přímo, a to následujícím způsobem (namísto go build):

$ go tool cgo filename.go

Po spuštění tohoto nástroje by se měl vytvořit podadresář _obj, do něhož jsou uloženy zdrojové kódy generované překladačem jazyka C. Skutečně se jedná o zdrojové kódy, které mohou být předány překladači céčka:

$ ls -1 _obj
 
16_c_function.cgo1.go
16_c_function.cgo2.c
_cgo_export.c
_cgo_export.h
_cgo_flags
_cgo_gotypes.go
_cgo_main.c
_cgo_.o

17. 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 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ě tři megabajty), můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující tabulce:

# Příklad Stručný popis Cesta
1 01_import_c.go import pseudobalíčku „C“ do programu psaného v Go https://github.com/tisnik/go-root/blob/master/article36/01_im­port_c.go
2 02_import_fmt.go import standardního balíčku „fmt“ bez jeho dalšího použití https://github.com/tisnik/go-root/blob/master/article36/02_im­port_fmt.go
3 03_missing_include.go chybějící komentář s příkazem preprocesoru include https://github.com/tisnik/go-root/blob/master/article36/03_mis­sing_include.go
4 04_puts_go_string.go volání funkce C.puts() s předáním Go řetězce https://github.com/tisnik/go-root/blob/master/article36/04_put­s_go_string.go
5 05_puts_c_string.go explicitní převod Go řetězce na C řetězec https://github.com/tisnik/go-root/blob/master/article36/05_put­s_c_string.go
6 06_abs.go volání funkce C.abs() bez konverze návratové hodnoty https://github.com/tisnik/go-root/blob/master/article36/06_abs.go
7 07_conversion.go konverze návratové hodnoty funkce C.abs() https://github.com/tisnik/go-root/blob/master/article36/07_con­version.go
8 08_math.go použití standardní matematické knihovny libm bez jejího linkování https://github.com/tisnik/go-root/blob/master/article36/08_mat­h.go
9 09_math_link.go slinkování matematické knihovny libm https://github.com/tisnik/go-root/blob/master/article36/09_mat­h_link.go
10 10_oom.go OOM – neuvolňování paměti a dopad na běh aplikace https://github.com/tisnik/go-root/blob/master/article36/10_oom.go
11 11_no_oom.go explicitní uvolňování paměti s řetězcem https://github.com/tisnik/go-root/blob/master/article36/11_no_o­om.go
12 12_free_string.go korektní explicitní uvolnění paměti s řetězcem https://github.com/tisnik/go-root/blob/master/article36/12_fre­e_string.go
13 13_better_free_string.go korektní uvolnění paměti v defer https://github.com/tisnik/go-root/blob/master/article36/13_bet­ter_free_string.go
14 14_free_before_use.go volání C.free() předtím, než byla paměť použita https://github.com/tisnik/go-root/blob/master/article36/14_fre­e_before_use.go
15 15_errno.go získání hodnoty proměnné errno https://github.com/tisnik/go-root/blob/master/article36/15_e­rrno.go
16 16_c_function.go C funkce definovaná přímo v komentáři https://github.com/tisnik/go-root/blob/master/article36/16_c_fun­ction.go
17 17_c_strings.go práce s C řetězci, konverze na Go řetězce atd. https://github.com/tisnik/go-root/blob/master/article36/17_c_strin­gs.go
18 18_double_free.go dvojí zavolání funkce C.free() a vliv tohoto volání na chování aplikace https://github.com/tisnik/go-root/blob/master/article36/18_dou­ble_free.go

18. Odkazy na Internetu

  1. Semantic Import Versioning in Go
    https://www.aaronzhuo.com/semantic-import-versioning-in-go/
  2. Sémantické verzování
    https://semver.org/
  3. Getting started with Go modules
    https://medium.com/@fonse­ka.live/getting-started-with-go-modules-b3dac652066d
  4. Create projects independent of $GOPATH using Go Modules
    https://medium.com/mindorks/create-projects-independent-of-gopath-using-go-modules-802260cdfb51o
  5. Anatomy of Modules in Go
    https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16
  6. Modules
    https://github.com/golang/go/wi­ki/Modules
  7. Go Modules Tutorial
    https://tutorialedge.net/golang/go-modules-tutorial/
  8. Module support
    https://golang.org/cmd/go/#hdr-Module_support
  9. Go Lang: Memory Management and Garbage Collection
    https://vikash1976.wordpres­s.com/2017/03/26/go-lang-memory-management-and-garbage-collection/
  10. Golang Internals, Part 4: Object Files and Function Metadata
    https://blog.altoros.com/golang-part-4-object-files-and-function-metadata.html
  11. What is REPL?
    https://pythonprogramminglan­guage.com/repl/
  12. What is a REPL?
    https://codewith.mu/en/tu­torials/1.0/repl
  13. Programming at the REPL: Introduction
    https://clojure.org/guides/re­pl/introduction
  14. What is REPL? (Quora)
    https://www.quora.com/What-is-REPL
  15. Gorilla REPL: interaktivní prostředí pro programovací jazyk Clojure
    https://www.root.cz/clanky/gorilla-repl-interaktivni-prostredi-pro-programovaci-jazyk-clojure/
  16. Read-eval-print loop (Wikipedia)
    https://en.wikipedia.org/wi­ki/Read%E2%80%93eval%E2%80%93prin­t_loop
  17. Vim as a Go (Golang) IDE using LSP and vim-go
    https://octetz.com/posts/vim-as-go-ide
  18. gopls
    https://github.com/golang/go/wi­ki/gopls
  19. IDE Integration Guide
    https://github.com/stamble­rre/gocode/blob/master/doc­s/IDE_integration.md
  20. How to instrument Go code with custom expvar metrics
    https://sysdig.com/blog/golang-expvar-custom-metrics/
  21. Golang expvar metricset (Metricbeat Reference)
    https://www.elastic.co/gu­ide/en/beats/metricbeat/7­.x/metricbeat-metricset-golang-expvar.html
  22. Package expvar
    https://golang.org/pkg/expvar/#NewInt
  23. Java Platform Debugger Architecture: Overview
    https://docs.oracle.com/en/ja­va/javase/11/docs/specs/jpda/jpda­.html
  24. The JVM Tool Interface (JVM TI): How VM Agents Work
    https://www.oracle.com/technet­work/articles/javase/index-140680.html
  25. JVM Tool Interface Version 11.0
    https://docs.oracle.com/en/ja­va/javase/11/docs/specs/jvmti­.html
  26. Creating a Debugging and Profiling Agent with JVMTI
    http://www.oracle.com/technet­work/articles/javase/jvmti-136367.html
  27. JVM TI (Wikipedia)
    http://en.wikipedia.org/wiki/JVM_TI
  28. IBM JVMTI extensions
    http://publib.boulder.ibm­.com/infocenter/realtime/v2r0/in­dex.jsp?topic=%2Fcom.ibm.sof­trt.doc%2Fdiag%2Ftools%2Fjvmti_ex­tensions.html
  29. Go & cgo: integrating existing C code with Go
    http://akrennmair.github.io/golang-cgo-slides/#1
  30. Using cgo to call C code from within Go code
    https://wenzr.wordpress.com/2018/06/07/u­sing-cgo-to-call-c-code-from-within-go-code/
  31. Package trace
    https://golang.org/pkg/runtime/trace/
  32. Introducing HTTP Tracing
    https://blog.golang.org/http-tracing
  33. Command trace
    https://golang.org/cmd/trace/
  34. A StreamLike, Immutable, Lazy Loading and smart Golang Library to deal with slices
    https://github.com/wesovilabs/koazee
  35. Funkce vyššího řádu v knihovně Underscore
    https://www.root.cz/clanky/funkce-vyssiho-radu-v-knihovne-underscore/
  36. Delve: a debugger for the Go programming language.
    https://github.com/go-delve/delve
  37. Příkazy debuggeru Delve
    https://github.com/go-delve/delve/tree/master/Do­cumentation/cli
  38. Debuggery a jejich nadstavby v Linuxu
    http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu/
  39. Debuggery a jejich nadstavby v Linuxu (2. část)
    http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-2-cast/
  40. Debuggery a jejich nadstavby v Linuxu (3): Nemiver
    http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-3-nemiver/
  41. Debuggery a jejich nadstavby v Linuxu (4): KDbg
    http://mojefedora.cz/debuggery-a-jejich-nadstavby-v-linuxu-4-kdbg/
  42. 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/
  43. Debugging Go Code with GDB
    https://golang.org/doc/gdb
  44. Debugging Go (golang) programs with gdb
    https://thornydev.blogspot­.com/2014/01/debugging-go-golang-programs-with-gdb.html
  45. GDB – Dokumentace
    http://sourceware.org/gdb/cu­rrent/onlinedocs/gdb/
  46. GDB – Supported Languages
    http://sourceware.org/gdb/cu­rrent/onlinedocs/gdb/Suppor­ted-Languages.html#Supported-Languages
  47. GNU Debugger (Wikipedia)
    https://en.wikipedia.org/wi­ki/GNU_Debugger
  48. The LLDB Debugger
    http://lldb.llvm.org/
  49. Debugger (Wikipedia)
    https://en.wikipedia.org/wi­ki/Debugger
  50. 13 Linux Debuggers for C++ Reviewed
    http://www.drdobbs.com/testing/13-linux-debuggers-for-c-reviewed/240156817
  51. 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
  52. Go Proverbs: Simple, Poetic, Pithy
    https://go-proverbs.github.io/
  53. Handling Sparse Files on Linux
    https://www.systutorials.com/136652/han­dling-sparse-files-on-linux/
  54. Gzip (Wikipedia)
    https://en.wikipedia.org/wiki/Gzip
  55. Deflate
    https://en.wikipedia.org/wiki/DEFLATE
  56. 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/
  57. Hexadecimální prohlížeče a editory s textovým uživatelským rozhraním
    https://www.root.cz/clanky/he­xadecimalni-prohlizece-a-editory-s-textovym-uzivatelskym-rozhranim/
  58. Hex dump
    https://en.wikipedia.org/wi­ki/Hex_dump
  59. Rozhraní io.ByteReader
    https://golang.org/pkg/io/#ByteReader
  60. Rozhraní io.RuneReader
    https://golang.org/pkg/io/#RuneReader
  61. Rozhraní io.ByteScanner
    https://golang.org/pkg/io/#By­teScanner
  62. Rozhraní io.RuneScanner
    https://golang.org/pkg/io/#Ru­neScanner
  63. Rozhraní io.Closer
    https://golang.org/pkg/io/#Closer
  64. Rozhraní io.Reader
    https://golang.org/pkg/io/#Reader
  65. Rozhraní io.Writer
    https://golang.org/pkg/io/#Writer
  66. Typ Strings.Reader
    https://golang.org/pkg/strin­gs/#Reader
  67. VACUUM (SQL)
    https://www.sqlite.org/lan­g_vacuum.html
  68. VACUUM (Postgres)
    https://www.postgresql.or­g/docs/8.4/sql-vacuum.html
  69. go-cron
    https://github.com/rk/go-cron
  70. gocron
    https://github.com/jasonlvhit/gocron
  71. clockwork
    https://github.com/whiteShtef/cloc­kwork
  72. clockwerk
    https://github.com/onatm/clockwerk
  73. JobRunner
    https://github.com/bamzi/jobrunner
  74. Rethinking Cron
    https://adam.herokuapp.com/pas­t/2010/4/13/rethinking_cron/
  75. In the Beginning was the Command Line
    https://web.archive.org/web/20180218045352/htt­p://www.cryptonomicon.com/be­ginning.html
  76. repl.it (REPL pro různé jazyky)
    https://repl.it/languages
  77. GOCUI – Go Console User Interface (celé uživatelské prostředí, nejenom input box)
    https://github.com/jroimartin/gocui
  78. Read–eval–print loop
    https://en.wikipedia.org/wi­ki/Read%E2%80%93eval%E2%80%93prin­t_loop
  79. go-prompt
    https://github.com/c-bata/go-prompt
  80. readline
    https://github.com/chzyer/readline
  81. A pure golang implementation for GNU-Readline kind library
    https://golangexample.com/a-pure-golang-implementation-for-gnu-readline-kind-library/
  82. go-readline
    https://github.com/fiorix/go-readline
  83. 4 Python libraries for building great command-line user interfaces
    https://opensource.com/article/17/5/4-practical-python-libraries
  84. prompt_toolkit 2.0.3 na PyPi
    https://pypi.org/project/prom­pt_toolkit/
  85. python-prompt-toolkit na GitHubu
    https://github.com/jonathan­slenders/python-prompt-toolkit
  86. The GNU Readline Library
    https://tiswww.case.edu/php/chet/re­adline/rltop.html
  87. GNU Readline (Wikipedia)
    https://en.wikipedia.org/wi­ki/GNU_Readline
  88. readline — GNU readline interface (Python 3.x)
    https://docs.python.org/3/li­brary/readline.html
  89. readline — GNU readline interface (Python 2.x)
    https://docs.python.org/2/li­brary/readline.html
  90. GNU Readline Library – command line editing
    https://tiswww.cwru.edu/php/chet/re­adline/readline.html
  91. gnureadline 6.3.8 na PyPi
    https://pypi.org/project/gnureadline/
  92. Editline Library (libedit)
    http://thrysoee.dk/editline/
  93. Comparing Python Command-Line Parsing Libraries – Argparse, Docopt, and Click
    https://realpython.com/comparing-python-command-line-parsing-libraries-argparse-docopt-click/
  94. libedit or editline
    http://www.cs.utah.edu/~bi­gler/code/libedit.html
  95. WinEditLine
    http://mingweditline.sourceforge.net/
  96. rlcompleter — Completion function for GNU readline
    https://docs.python.org/3/li­brary/rlcompleter.html
  97. rlwrap na GitHubu
    https://github.com/hanslub42/rlwrap
  98. rlwrap(1) – Linux man page
    https://linux.die.net/man/1/rlwrap
  99. readline(3) – Linux man page
    https://linux.die.net/man/3/readline
  100. history(3) – Linux man page
    https://linux.die.net/man/3/history
  101. Dokumentace k balíčku oglematchers
    https://godoc.org/github.com/ja­cobsa/oglematchers
  102. Balíček oglematchers
    https://github.com/jacobsa/o­glematchers
  103. Dokumentace k balíčku ogletest
    https://godoc.org/github.com/ja­cobsa/ogletest
  104. Balíček ogletest
    https://github.com/jacobsa/ogletest
  105. Dokumentace k balíčku assert
    https://godoc.org/github.com/stret­chr/testify/assert
  106. Testify – Thou Shalt Write Tests
    https://github.com/stretchr/testify/
  107. package testing
    https://golang.org/pkg/testing/
  108. Golang basics – writing unit tests
    https://blog.alexellis.io/golang-writing-unit-tests/
  109. An Introduction to Programming in Go / Testing
    https://www.golang-book.com/books/intro/12
  110. An Introduction to Testing in Go
    https://tutorialedge.net/golang/intro-testing-in-go/
  111. Advanced Go Testing Tutorial
    https://tutorialedge.net/go­lang/advanced-go-testing-tutorial/
  112. GoConvey
    http://goconvey.co/
  113. Testing Techniques
    https://talks.golang.org/2014/tes­ting.slide
  114. 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
  115. Afinní transformace
    https://cs.wikibooks.org/wi­ki/Geometrie/Afinn%C3%AD_tran­sformace_sou%C5%99adnic
  116. package gg
    https://godoc.org/github.com/fo­gleman/gg
  117. Generate an animated GIF with Golang
    http://tech.nitoyon.com/en/blog/2016/01/07/­go-animated-gif-gen/
  118. Generate an image programmatically with Golang
    http://tech.nitoyon.com/en/blog/2015/12/31/­go-image-gen/
  119. The Go image package
    https://blog.golang.org/go-image-package
  120. Balíček draw2D: 2D rendering for different output (raster, pdf, svg)
    https://github.com/llgcode/draw2d
  121. Draw a rectangle in Golang?
    https://stackoverflow.com/qu­estions/28992396/draw-a-rectangle-in-golang
  122. YAML
    https://yaml.org/
  123. edn
    https://github.com/edn-format/edn
  124. Smile
    https://github.com/FasterXML/smile-format-specification
  125. Protocol-Buffers
    https://developers.google.com/protocol-buffers/
  126. Marshalling (computer science)
    https://en.wikipedia.org/wi­ki/Marshalling_(computer_sci­ence)
  127. Unmarshalling
    https://en.wikipedia.org/wi­ki/Unmarshalling
  128. Introducing JSON
    http://json.org/
  129. Package json
    https://golang.org/pkg/encoding/json/
  130. The Go Blog: JSON and Go
    https://blog.golang.org/json-and-go
  131. Go by Example: JSON
    https://gobyexample.com/json
  132. Writing Web Applications
    https://golang.org/doc/articles/wiki/
  133. Golang Web Apps
    https://www.reinbach.com/blog/golang-webapps-1/
  134. Build web application with Golang
    https://legacy.gitbook.com/bo­ok/astaxie/build-web-application-with-golang/details
  135. Golang Templates – Golang Web Pages
    https://www.youtube.com/wat­ch?v=TkNIETmF-RU
  136. Simple Golang HTTPS/TLS Examples
    https://github.com/denji/golang-tls
  137. Playing with images in HTTP response in golang
    https://www.sanarias.com/blog/1214Pla­yingwithimagesinHTTPrespon­seingolang
  138. MIME Types List
    https://www.freeformatter.com/mime-types-list.html
  139. Go Mutex Tutorial
    https://tutorialedge.net/golang/go-mutex-tutorial/
  140. Creating A Simple Web Server With Golang
    https://tutorialedge.net/go­lang/creating-simple-web-server-with-golang/
  141. Building a Web Server in Go
    https://thenewstack.io/building-a-web-server-in-go/
  142. How big is the pipe buffer?
    https://unix.stackexchange­.com/questions/11946/how-big-is-the-pipe-buffer
  143. How to turn off buffering of stdout in C
    https://stackoverflow.com/qu­estions/7876660/how-to-turn-off-buffering-of-stdout-in-c
  144. setbuf(3) – Linux man page
    https://linux.die.net/man/3/setbuf
  145. setvbuf(3) – Linux man page (stejný obsah jako předchozí stránka)
    https://linux.die.net/man/3/setvbuf
  146. Select waits on a group of channels
    https://yourbasic.org/golang/select-explained/
  147. Rob Pike: Simplicity is Complicated (video)
    http://www.golang.to/posts/dotgo-2015-rob-pike-simplicity-is-complicated-youtube-16893
  148. Algorithms to Go
    https://yourbasic.org/
  149. Využití knihovny Pygments (nejenom) pro obarvení zdrojových kódů
    https://www.root.cz/clanky/vyuziti-knihovny-pygments-nejenom-pro-obarveni-zdrojovych-kodu/
  150. 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/
  151. Go Defer Simplified with Practical Visuals
    https://blog.learngoprogram­ming.com/golang-defer-simplified-77d3b2b817ff
  152. 5 More Gotchas of Defer in Go — Part II
    https://blog.learngoprogramming.com/5-gotchas-of-defer-in-go-golang-part-ii-cc550f6ad9aa
  153. The Go Blog: Defer, Panic, and Recover
    https://blog.golang.org/defer-panic-and-recover
  154. The defer keyword in Swift 2: try/finally done right
    https://www.hackingwithswift.com/new-syntax-swift-2-defer
  155. Swift Defer Statement
    https://andybargh.com/swift-defer-statement/
  156. Modulo operation (Wikipedia)
    https://en.wikipedia.org/wi­ki/Modulo_operation
  157. Node.js vs Golang: Battle of the Next-Gen Languages
    https://www.hostingadvice­.com/blog/nodejs-vs-golang/
  158. The Go Programming Language (home page)
    https://golang.org/
  159. GoDoc
    https://godoc.org/
  160. Go (programming language), Wikipedia
    https://en.wikipedia.org/wi­ki/Go_(programming_langua­ge)
  161. Go Books (kniha o jazyku Go)
    https://github.com/dariubs/GoBooks
  162. The Go Programming Language Specification
    https://golang.org/ref/spec
  163. Go: the Good, the Bad and the Ugly
    https://bluxte.net/musings/2018/04/10/go-good-bad-ugly/
  164. Package builtin
    https://golang.org/pkg/builtin/
  165. Package fmt
    https://golang.org/pkg/fmt/
  166. The Little Go Book (další kniha)
    https://github.com/dariubs/GoBooks
  167. The Go Programming Language by Brian W. Kernighan, Alan A. A. Donovan
    https://www.safaribookson­line.com/library/view/the-go-programming/9780134190570/e­book_split010.html
  168. Learning Go
    https://www.miek.nl/go/
  169. Go Bootcamp
    http://www.golangbootcamp.com/
  170. Programming in Go: Creating Applications for the 21st Century (další kniha o jazyku Go)
    http://www.informit.com/sto­re/programming-in-go-creating-applications-for-the-21st-9780321774637
  171. Introducing Go (Build Reliable, Scalable Programs)
    http://shop.oreilly.com/pro­duct/0636920046516.do
  172. Learning Go Programming
    https://www.packtpub.com/application-development/learning-go-programming
  173. The Go Blog
    https://blog.golang.org/
  174. Getting to Go: The Journey of Go's Garbage Collector
    https://blog.golang.org/ismmkeynote
  175. Go (programovací jazyk, Wikipedia)
    https://cs.wikipedia.org/wi­ki/Go_(programovac%C3%AD_ja­zyk)
  176. Rychle, rychleji až úplně nejrychleji s jazykem Go
    https://www.root.cz/clanky/rychle-rychleji-az-uplne-nejrychleji-s-jazykem-go/
  177. Installing Go on the Raspberry Pi
    https://dave.cheney.net/2012/09/25/in­stalling-go-on-the-raspberry-pi
  178. 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
  179. Niečo málo o Go – Golang (slovensky)
    http://golangsk.logdown.com/
  180. How Many Go Developers Are There?
    https://research.swtch.com/gop­hercount
  181. Most Popular Technologies (Stack Overflow Survery 2018)
    https://insights.stackover­flow.com/survey/2018/#most-popular-technologies
  182. Most Popular Technologies (Stack Overflow Survery 2017)
    https://insights.stackover­flow.com/survey/2017#techno­logy
  183. JavaScript vs. Golang for IoT: Is Gopher Winning?
    https://www.iotforall.com/javascript-vs-golang-iot/
  184. The Go Programming Language: Release History
    https://golang.org/doc/de­vel/release.html
  185. Go 1.11 Release Notes
    https://golang.org/doc/go1.11
  186. Go 1.10 Release Notes
    https://golang.org/doc/go1.10
  187. Go 1.9 Release Notes (tato verze je stále používána)
    https://golang.org/doc/go1.9
  188. Go 1.8 Release Notes (i tato verze je stále používána)
    https://golang.org/doc/go1.8
  189. Go on Fedora
    https://developer.fedorapro­ject.org/tech/languages/go/go-installation.html
  190. Writing Go programs
    https://developer.fedorapro­ject.org/tech/languages/go/go-programs.html
  191. The GOPATH environment variable
    https://tip.golang.org/doc/co­de.html#GOPATH
  192. Command gofmt
    https://tip.golang.org/cmd/gofmt/
  193. The Go Blog: go fmt your code
    https://blog.golang.org/go-fmt-your-code
  194. C? Go? Cgo!
    https://blog.golang.org/c-go-cgo
  195. 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/
  196. 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
  197. Gofmt No Longer Allows Spaces. Tabs Only
    https://news.ycombinator.com/i­tem?id=7914523
  198. Why does Go „go fmt“ uses tabs instead of whitespaces?
    https://www.quora.com/Why-does-Go-go-fmt-uses-tabs-instead-of-whitespaces
  199. Interactive: The Top Programming Languages 2018
    https://spectrum.ieee.org/sta­tic/interactive-the-top-programming-languages-2018
  200. Go vs. Python
    https://www.peterbe.com/plog/govspy
  201. PackageManagementTools
    https://github.com/golang/go/wi­ki/PackageManagementTools
  202. A Tour of Go: Type inference
    https://tour.golang.org/basics/14
  203. Go Slices: usage and internals
    https://blog.golang.org/go-slices-usage-and-internals
  204. Go by Example: Slices
    https://gobyexample.com/slices
  205. What is the point of slice type in Go?
    https://stackoverflow.com/qu­estions/2098874/what-is-the-point-of-slice-type-in-go
  206. The curious case of Golang array and slices
    https://medium.com/@hackintoshrao/the-curious-case-of-golang-array-and-slices-2565491d4335
  207. Introduction to Slices in Golang
    https://www.callicoder.com/golang-slices/
  208. Golang: Understanding ‚null‘ and nil
    https://newfivefour.com/golang-null-nil.html
  209. What does nil mean in golang?
    https://stackoverflow.com/qu­estions/35983118/what-does-nil-mean-in-golang
  210. nils In Go
    https://go101.org/article/nil.html
  211. Go slices are not dynamic arrays
    https://appliedgo.net/slices/
  212. Go-is-no-good (nelze brát doslova)
    https://github.com/ksimka/go-is-not-good
  213. Rust vs. Go
    https://news.ycombinator.com/i­tem?id=13430108
  214. Seriál Programovací jazyk Rust
    https://www.root.cz/seria­ly/programovaci-jazyk-rust/
  215. Modern garbage collection: A look at the Go GC strategy
    https://blog.plan99.net/modern-garbage-collection-911ef4f8bd8e
  216. Go GC: Prioritizing low latency and simplicity
    https://blog.golang.org/go15gc
  217. Is Golang a good language for embedded systems?
    https://www.quora.com/Is-Golang-a-good-language-for-embedded-systems
  218. Running GoLang on an STM32 MCU. A quick tutorial.
    https://www.mickmake.com/post/running-golang-on-an-mcu-a-quick-tutorial
  219. Go, Robot, Go! Golang Powered Robotics
    https://gobot.io/
  220. Emgo: Bare metal Go (language for programming embedded systems)
    https://github.com/ziutek/emgo
  221. UTF-8 history
    https://www.cl.cam.ac.uk/~mgk25/uc­s/utf-8-history.txt
  222. Less is exponentially more
    https://commandcenter.blog­spot.com/2012/06/less-is-exponentially-more.html
  223. Should I Rust, or Should I Go
    https://codeburst.io/should-i-rust-or-should-i-go-59a298e00ea9
  224. Setting up and using gccgo
    https://golang.org/doc/install/gccgo
  225. Elastic Tabstops
    http://nickgravgaard.com/elastic-tabstops/
  226. Strings, bytes, runes and characters in Go
    https://blog.golang.org/strings
  227. Datový typ
    https://cs.wikipedia.org/wi­ki/Datov%C3%BD_typ
  228. Seriál o programovacím jazyku Rust: Základní (primitivní) datové typy
    https://www.root.cz/clanky/pro­gramovaci-jazyk-rust-nahrada-c-nebo-slepa-cesta/#k09
  229. 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
  230. Seriál o programovacím jazyku Rust: Řezy (slice) vektoru
    https://www.root.cz/clanky/prace-s-vektory-v-programovacim-jazyku-rust/#k05
  231. Printf Format Strings
    https://www.cprogramming.com/tu­torial/printf-format-strings.html
  232. Java: String.format
    https://docs.oracle.com/ja­vase/8/docs/api/java/lang/Strin­g.html#format-java.lang.String-java.lang.Object…-
  233. Java: format string syntax
    https://docs.oracle.com/ja­vase/8/docs/api/java/util/For­matter.html#syntax
  234. Selectors
    https://golang.org/ref/spec#Selectors
  235. Calling Go code from Python code
    http://savorywatt.com/2015/09/18/ca­lling-go-code-from-python-code/
  236. Go Data Structures: Interfaces
    https://research.swtch.com/interfaces
  237. How to use interfaces in Go
    http://jordanorelli.com/pos­t/32665860244/how-to-use-interfaces-in-go
  238. Interfaces in Go (part I)
    https://medium.com/golangspec/in­terfaces-in-go-part-i-4ae53a97479c
  239. Part 21: Goroutines
    https://golangbot.com/goroutines/
  240. Part 22: Channels
    https://golangbot.com/channels/
  241. [Go] Lightweight eventbus with async compatibility for Go
    https://github.com/asaske­vich/EventBus
  242. What about Trait support in Golang?
    https://www.reddit.com/r/go­lang/comments/8mfykl/what_a­bout_trait_support_in_golan­g/
  243. 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/
  244. Control Flow
    https://en.wikipedia.org/wi­ki/Control_flow
  245. Structured programming
    https://en.wikipedia.org/wi­ki/Structured_programming
  246. Control Structures
    https://www.golang-book.com/books/intro/5
  247. Control structures – Go if else statement
    http://golangtutorials.blog­spot.com/2011/06/control-structures-if-else-statement.html
  248. Control structures – Go switch case statement
    http://golangtutorials.blog­spot.com/2011/06/control-structures-go-switch-case.html
  249. Control structures – Go for loop, break, continue, range
    http://golangtutorials.blog­spot.com/2011/06/control-structures-go-for-loop-break.html
  250. Goroutine IDs
    https://blog.sgmansfield.com/2015/12/go­routine-ids/
  251. Different ways to pass channels as arguments in function in go (golang)
    https://stackoverflow.com/qu­estions/24868859/different-ways-to-pass-channels-as-arguments-in-function-in-go-golang
  252. justforfunc #22: using the Go execution tracer
    https://www.youtube.com/wat­ch?v=ySy3sR1LFCQ
  253. Single Function Exit Point
    http://wiki.c2.com/?Single­FunctionExitPoint
  254. Entry point
    https://en.wikipedia.org/wi­ki/Entry_point
  255. Why does Go have a GOTO statement?!
    https://www.reddit.com/r/go­lang/comments/kag5q/why_do­es_go_have_a_goto_statemen­t/
  256. Effective Go
    https://golang.org/doc/ef­fective_go.html
  257. GoClipse: an Eclipse IDE for the Go programming language
    http://goclipse.github.io/
  258. GoClipse Installation
    https://github.com/GoClip­se/goclipse/blob/latest/do­cumentation/Installation.md#in­stallation
  259. The zero value of a slice is not nil
    https://stackoverflow.com/qu­estions/30806931/the-zero-value-of-a-slice-is-not-nil
  260. Go-tcha: When nil != nil
    https://dev.to/pauljlucas/go-tcha-when-nil–nil-hic
  261. Nils in Go
    https://www.doxsey.net/blog/nils-in-go