Obsah
1. Nástroje pro kontrolu kvality zdrojových kódů psaných v Go
3. Překladač programovacího jazyka Go
4. Jaké potenciální problémy překladač Go nenalezne?
6. Příklady problémů zachycených nástrojem go vet
8. Příklady problémů zachycených nástrojem errcheck
10. Příklady problémů zachycených nástrojem golint
12. Příklady problémů zachycených nástrojem gocyclo
14. Příklady problémů zachycených nástrojem ineffassign
15. Zobrazení výsledků kontrol přímo v repositáři
18. Obsah následujícího článku
19. Repositář s demonstračními příklady
1. Nástroje pro kontrolu kvality zdrojových kódů psaných v Go
Samotný programovací jazyk Go je navržen velmi konzervativně, což bylo ostatně patrné i z předchozího článku o (ne)používaní generických datových typů, funkcí a metod. To pochopitelně některým vývojářům nemusí vyhovovat, na čemž ale ve skutečnosti nemusí být nic špatného – ideální univerzálně přijímaný programovací jazyk neexistuje a pravděpodobně ani nikdy existovat nebude, protože některé vlastnosti jazyků jsou protichůdné. Ovšem samotný programovací jazyk je jen jednou (i když pochopitelně velmi důležitou) součástí celého ekosystému, který kromě překladače (někdy interpretru) obsahuje i vývojová prostředí a ladicí nástroje, ale i další pomocné nástroje a utility. Mezi tyto nástroje patří i utility určené pro kontrolu kvality zdrojových kódů, odhalování různých chyb nerozpoznaných překladačem, potenciálních chyb, špatně strukturovaného kódu, nedodržování zavedených idiomů atd. A právě těmito mnohdy velmi užitečnými nástroji se budeme zabývat v dnešním článku.
Samostatnou kapitolu tvoří nástroje sloužící k odhalení potenciálních bezpečnostních problémů. I těchto nástrojů existuje relativně velké množství a budeme se jimi zabývat v navazujícím článku.
2. Nástroj gofmt
Jednou z poměrně častých otázek mnoha programátorů, kteří na programovací jazyk Go přechází z jiných jazyků, je, jakým způsobem je možné zkontrolovat syntaxi zdrojových kódů bez provedení jejich překladu či dokonce spuštění. Takový nástroj nabízí například jazyk Ruby, Perl či Python:
$ ruby -c test.rb $ perl -c test.pl $ python -m py_compile test.py
V sadě základních nástrojů jazyka Go se nachází i nástroj gofmt, jehož primárním úkolem je naformátování zdrojových kódů podle poměrně striktních pravidel, která jsou testována například tímto testem. Ovšem gofmt, na rozdíl od mnoha dalších formátovačů, pracuje s kódem reprezentovaným AST (abstraktním syntaktickým stromem). To mj. znamená, že kód je zapotřebí parsovat a převést do AST, takže i gofmt dokáže provádět kontrolu syntaxe.
Program bez uvedení balíčku:
func main() { }
Odhalená chyba:
01_missing_package.go:1:1: expected 'package', found 'func
Špatně umístěná otevírací bloková závorka:
package main func main() { }
Příklad problematického zdrojového kódu, v němž nejsou použity blokové (složené) závorky na stejném řádku s programovým kódem:
package main func classify_char(c rune) string { if c >= 'a' && c <= 'z' { return "male pismeno" } else if c >= 'A' && c <= 'Z' { return "velke pismeno" } else { return "neco jineho" } } func main() { println(classify_char('a')) println(classify_char('Z')) println(classify_char('?')) }
Většina těchto chyb je odhalena:
bad_syntax.go:13:25: unexpected newline, expecting { after if clause bad_syntax.go:17:2: expected statement, found 'else' bad_syntax.go:20:2: expected statement, found 'else' bad_syntax.go:24:1: expected declaration, found '}'
Kromě toho dokáže gofmt provádět i zjednodušení některých výrazů:
Původní podoba | Zjednodušená podoba |
---|---|
[]T{T{}, T{}} | []T{{}, {}} |
s[a:len(s)] | s[a:] |
for x, _ = range v {…} | for x = range v {…} |
for _ = range v {…} | for range v {…} |
Navíc je možné specifikovat i vlastní transformace či zjednodušování. Následující příklad je převzat z reálných zdrojových kódů:
package main import "fmt" import "bytes" func main() { a := []byte{1, 2, 3} b := []byte{3, 4, 5} c := bytes.Compare(a, b) == 0 fmt.Println(c) c = bytes.Compare(a, a) == 0 fmt.Println(c) }
Tento zdrojový kód lze příkazem:
$ gofmt -r 'bytes.Compare(a, b) == 0 -> bytes.Equal(a, b)'
Transformovat na:
package main import "fmt" import "bytes" func main() { a := []byte{1, 2, 3} b := []byte{3, 4, 5} c := bytes.Equal(a, b) fmt.Println(c) c = bytes.Equal(a, a) fmt.Println(c) }
3. Překladač programovacího jazyka Go
The boy is smoking and leaving smoke rings into the air. The girl gets irritated with the smoke and says to her lover: „Can't you see the warning written on the cigarettes packet, smoking is injurious to health!“ The boy replies back: „Darling, I am a programmer. We don't worry about warnings, we only worry about errors.“
I když se to možná bude zdát překvapivé, na druhém místě v seznamu nástrojů pro kontrolu kvality stojí přímo překladač programovacího jazyka Go. Ten se vyznačuje mj. i tím, že při parsování, kontrole a překladu zdrojových kódů nikdy negeneruje varování – zdrojový kód je buď přeložen bez dalších doplňujících zpráv nebo se vypíšou nalezené chyby (resp. přesněji řečeno několik prvních chyb, aby nebyl vývojář polekán a nemusel scrollovat o několik obrazovek). Navíc není možné kontrolu chyb ani vypnout ani naopak zapínat obdobu režimu „pedantic“, kterou můžeme znát například z céčka (ve skutečnosti vlastně překladač Go vždy pracuje právě v režimu „pedantic“). Díky těmto vlastnostem je samotný překladač skutečně prvním nástrojem, který dokáže odhalit poměrně značné množství různých potenciálních chyb. Kromě běžných problémů typu chybějící závorka, špatně zapsané klíčové slovo, nekorektní programová konstrukce lze odhalit například i:
- prakticky všechny prohřešky vůči typovému systému jazyka Go (typový systém je striktnější, než například v případě C či Javy)
- nepoužívané importované balíčky
- cyklická závislost mezi balíčky
- deklarované proměnné, které nejsou použity
- chybějící příkaz return ve všech větvích funkce či metody
- použití operátoru = namísto == v podmínkách, a to ve všech případech, protože taková konstrukce není v programovacím jazyce Go povolena (v C, C++ i Javě je tato chyba odhalena jen někdy – viz příklad pod tímto seznamem)
- kontrola, zda typ předávané hodnoty implementuje očekávané rozhraní
- kontrola, zda je skok realizovaný pomocí goto proveden na korektní místo či nikoli
- cyklická závislost rozhraní
- nesprávné použití parametrů ve variadických funkcích
- kontrola konstant používaných u bitových posunů
- kontrola, zda jsou příkazy ++ a – skutečně použity jako příkazy a nikoli jako operátory (to Go z mnoha dobrých důvodů neumožňuje)
class BooleanAssign { void foobar() { boolean a=true; boolean b=false; if (a=b) { } if (a==b) { } } }
Uveďme si nyní příklady některých striktnějších kontrol prováděných překladačem jazyka Go.
Konstanty, jejichž hodnoty neodpovídají typům proměnných, do kterých jsou přiřazovány:
package main import "fmt" func main() { var a int8 = -1000 var b int16 = -100000 var c int32 = -10000000000 var d int32 = -10000000000000000 fmt.Println(a) fmt.Println(b) fmt.Println(c) fmt.Println(d) }
Chybová hlášení:
./integer_signed_types_checks.go:15:15: constant -1000 overflows int8 ./integer_signed_types_checks.go:16:16: constant -100000 overflows int16 ./integer_signed_types_checks.go:17:16: constant -10000000000 overflows int32 ./integer_signed_types_checks.go:18:16: constant -10000000000000000 overflows int32
Striktní typové kontroly (silnější, než v mnoha dalších jazycích):
package main import "fmt" func main() { var a uint8 = 255 var b uint16 = a fmt.Println(a) fmt.Println(b) }
Chybové hlášení:
./05_improper_conversion.go:16:6: cannot use a (type uint8) as type uint16 in assignment
Podobné typové kontroly, ovšem u typů s plovoucí řádovou čárkou:
package main func main() { var c float32 = 1e300 var d float32 = -1e300 var g float64 = 1e3000 var h float64 = -1e3000 }
Chybová hlášení:
./fp_types_checks.go:13:18: constant 1e+300 overflows float32 ./fp_types_checks.go:14:18: constant -1e+300 overflows float32 ./fp_types_checks.go:16:18: constant 1e+3000 overflows float64 ./fp_types_checks.go:17:18: constant -1e+3000 overflows float64
4. Jaké potenciální problémy překladač Go nenalezne?
Na druhou stranu je však nutné upozornit na to, že některé typické a často se vyskytující chyby samotný překladač neodhalí, což může způsobit problémy. Jen pro příklad:
- kontrola chybových stavů
- práce s neinicializovanou mapou
- přístup přes ukazatel obsahující nil
- zda jsou deklarovány všechny větve v příkazu switch
- kontrola parametrů funkce fmt.Printf atd.
Některé z těchto problémů dokážou odhalit nástroje popsané v navazujících kapitolách.
Pro zajímavost si ukažme dvě chyby, které nejsou překladačem odhaleny. Prvním z problémů je přístup do neinicializované mapy, což je chyba, kterou udělal snad každý programátor, který ke Go přešel z jiného jazyka, v němž mapy (asociativní pole) existují:
package main func main() { var m map[string]string m["foo"] = "bar" }
Tento problém je odhalen až za běhu aplikace:
panic: assignment to entry in nil map goroutine 1 [running]: main.main() /home/tester/m.go:5 +0x4b exit status 2
Ve druhém chybném příkladu se pracuje s ukazatelem nastaveným na nulovou hodnotu, tedy na nil:
package main import "fmt" import "math" type Vector struct { X, Y float64 } func (v *Vector) Length() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) } func main() { var v *Vector fmt.Println(v.Length()) }
I tato chyba je objevena až po spuštění programu:
panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x484bb3] goroutine 1 [running]: main.(*Vector).Length(...) /home/tester/p.go:11 main.main() /home/tester/p.go:16 +0x23 exit status 2
5. Standardní nástroj go vet
Dalším (dnes již posledním jmenovaným) standardním nástrojem dodávaným v instalaci programovacího jazyka Go je nástroj nazvaný vet, který je z příkazové řádky volán následovně:
$ go vet parametry
Tento nástroj slouží k odhalení dalších typů potenciálních chyb a problémů, například:
- kontrola typů parametrů funkce fmt.Pritnf na základě formátovacího řetězce
- dtto u podobných funkcí (fmt.Sprintf apod.)
- bitové posuny prováděné mimo rozsah daného datového typu (8 bitů u uint8 atd.)
- kontrola signatur metod u nejpoužívanějších rozhraní (tj. zda uživatelem definované metody mají shodné signaturami s metodami předepsanými ve standardních rozhraních – ukážeme si na demonstračním příkladu)
- kontrola, zda kód psaný v assembleru odpovídá deklaracím v jazyku Go
- nepotřebná přiřazení
- problémy s použitím atomických operací
- nepoužité výsledky (vracené hodnoty) volaných funkcí
- nedostupný kód
Jak jsme si již řekli v předchozím odstavci, je go vet součástí základních nástrojů programovacího jazyka Go, takže by měl být vždy dostupný:
$ go help vet usage: go vet [-n] [-x] [build flags] [vet flags] [packages] Vet runs the Go vet command on the packages named by the import paths. For more about vet and its flags, see 'go doc cmd/vet'. For more about specifying packages, see 'go help packages'. The -n flag prints commands that would be executed. The -x flag prints commands as they are executed. The build flags supported by go vet are those that control package resolution and execution, such as -n, -x, -v, -tags, and -toolexec. For more about these flags, see 'go help build'. See also: go fmt, go fix.
6. Příklady problémů zachycených nástrojem go vet
Podívejme se nyní na některé problémy, které odhalí právě nástroj go vet, ovšem nikoli překladač programovacího jazyka Go.
V prvním příkladu se nachází příkazy za konstrukcí return. K těmto příkazům není pochopitelně možné se žádným způsobem dostat:
package main import "fmt" func main() { return i := 10 fmt.Println(i) }
Chybová hlášení nástroje go vet:
./t.go:7: unreachable code
Ve druhém příkladu se pokoušíme o bitový posun proměnné typu int (32bitová či 64bitová) o 70 bitů doleva:
package main import "fmt" func main() { i := 1 i <<= 70 fmt.Println(i) }
Chybová hlášení nástroje go vet:
./t.go:7: i (64 bits) too small for shift of 70
V příkladu třetím je kontrolováno, jaké parametry se předávají funkci fmt.Printf a zda tyto parametry odpovídají formátovacímu řetězci:
package main import "fmt" func main() { fmt.Printf("foo") fmt.Printf("foo", "bar") fmt.Printf("%d", "bar") fmt.Printf("%s %s", "bar") fmt.Printf("%d", 3.14) fmt.Printf("%p", nil) }
Chybová hlášení nástroje go vet odhalí většinu problémů s funkcí fmt.Printf:
./t.go:7: Printf call has arguments but no formatting directives ./t.go:8: Printf format %d has arg "bar" of wrong type string ./t.go:9: Printf format %s reads arg #2, but call has 1 arg ./t.go:10: Printf format %d has arg 3.14 of wrong type float64 ./t.go:11: Printf format %p has arg nil of wrong type untyped nil
Existuje i podobná funkce fmt.Sprintf, která ovšem vrací hodnotu (naformátovaný řetězec), který kvůli chybě programátora ignorujeme:
package main import "fmt" func main() { fmt.Sprintf("foo") fmt.Sprintf("foo", "bar") fmt.Sprintf("%d", "bar") fmt.Sprintf("%s %s", "bar") fmt.Sprintf("%d", 3.14) fmt.Sprintf("%p", nil) }
Z chybových hlášení je patrné, že go vet i tyto problémy korektně odhalil, zatímco překladač tento kód bez problémů přeložil:
./s.go:6: result of fmt.Sprintf call not used ./s.go:7: result of fmt.Sprintf call not used ./s.go:7: Sprintf call has arguments but no formatting directives ./s.go:8: result of fmt.Sprintf call not used ./s.go:8: Sprintf format %d has arg "bar" of wrong type string ./s.go:9: result of fmt.Sprintf call not used ./s.go:9: Sprintf format %s reads arg #2, but call has 1 arg ./s.go:10: result of fmt.Sprintf call not used ./s.go:10: Sprintf format %d has arg 3.14 of wrong type float64 ./s.go:11: result of fmt.Sprintf call not used ./s.go:11: Sprintf format %p has arg nil of wrong type untyped nil
Konečně kontrola, jestli metody nazvané ReadByte odpovídají signatuře metody předepsané v rozhraní Reader:
package main type X struct { } type Y struct { } type Z struct { } func (x X) ReadByte() (byte, error) { return 0, nil } func (y Y) ReadByte() error { return nil } func (z Z) ReadByte() byte { return 0 } func main() { }
./t.go:16: method ReadByte() error should have signature ReadByte() (byte, error) ./t.go:20: method ReadByte() byte should have signature ReadByte() (byte, error)
7. Nástroj errcheck
Nyní si pojďme popsat některé užitečné nástroje, které nejsou (alespoň prozatím) součástí standardní instalace nástrojů programovacího jazyka Go. První z těchto nástrojů se jmenuje jednoduše errcheck a jak již název této utility napovídá, jedná se o nástroj provádějící kontrolu, zda se zpracovávají všechny chybové kódy vrácené různými funkcemi. Vychází se přitom z předpokladu, že jakmile je chybový kód uložen do lokální proměnné, je nutné s ním dále pracovat, protože jazyk Go neumožňuje vytvořit proměnnou bez jejího dalšího použití (ovšem tento předpoklad ne vždy platí, což si ostatně ukážeme na příkladech v navazující kapitole).
Instalace tohoto nástroje se provede příkazem:
$ go get -u github.com/kisielk/errcheck
Vlastní kontrolu (v rámci celého projektu) zajistí příkaz:
$ errcheck ./...
8. Příklady problémů zachycených nástrojem errcheck
Úloha nástroje errcheck je tedy jednoznačná – detekovat, ve kterých místech zdrojového kódu ignorujeme návratovou hodnotu s informací o chybě. Ukažme si tedy, jak a kde se tyto problémy mohou nalézt.
Prvním příkladem je implementace jednoduchého serveru reagujícího na zprávy přicházející na port 1234. Zdánlivě ošetřujeme všechny chybové stavy:
package main import ( "fmt" "net" ) func main() { l, err := net.Listen("tcp", "localhost:1234") if err != nil { println("Can't open the port!") } defer l.Close() for { conn, err := l.Accept() if err != nil { println("Connection refused!") } go func(c net.Conn) { fmt.Fprintf(c, "Holla\n") c.Close() }(conn) } }
Nástroj errcheck ukáže, které chyby ignorujeme:
$ errcheck 16_simple_server.go 16_simple_server.go:13:15: defer l.Close() 16_simple_server.go:20:15: fmt.Fprintf(c, "Holla\n") 16_simple_server.go:21:11: c.Close()
Ve druhém příkladu vytváříme rastrový obrázek ve formátu PNG:
package main import ( "image" "image/color" "image/png" "os" ) const width = 256 const height = 256 func main() { img := image.NewRGBA(image.Rect(0, 0, width, height)) for x := 0; x < width; x++ { for y := 0; y < height; y++ { var red uint8 = uint8(x) var green uint8 = uint8((x + y) >> 1) var blue uint8 = uint8(y) c := color.RGBA{red, green, blue, 255} img.SetRGBA(x, y, c) } } outfile, err := os.Create("test.png") if err != nil { panic(err) } defer outfile.Close() png.Encode(outfile, img) }
Opět se podívejme na ignorované chyby:
$ errcheck 17_png_output.go 17_png_output.go:29:21: defer outfile.Close() 17_png_output.go:30:12: png.Encode(outfile, img)
9. Nástroj golint
Druhým nástrojem, který je zapotřebí explicitně nainstalovat (není tedy součástí standardního toolingu), je nástroj pojmenovaný golint. Jedná se o nástroj, který dokáže vyhledávat problémy související se stylem zápisu zdrojových kódů (coding style), což je odlišný typ problémů, než který vyhledává například go vet či výše zmíněný nástroj errcheck. Typické problémy, které lze odhalit, jsou – špatné názvy proměnných, použití „tečkového“ importu, exportování symbolu bez dokumentačního řetězce, zbytečné větve else apod. Tento potenciálně velmi užitečný nástroj nainstalujeme příkazem:
$ go get -u golang.org/x/lint/golint
10. Příklady problémů zachycených nástrojem golint
Kód s exportovanými symboly bez dokumentačních řetězců:
type StringHeap []string func (h StringHeap) Len() int { return len(h) } func (h StringHeap) Less(i, j int) bool { return h[i] < h[j] } func (h StringHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func (h *StringHeap) Push(x interface{}) { *h = append(*h, x.(string)) }
Špatné dokumentační řetězce:
// Encode func (ge *GobEncoder) Encode(subject string, v interface{}) ([]byte, error) { b := new(bytes.Buffer) enc := gob.NewEncoder(b) if err := enc.Encode(v); err != nil { return nil, err } return b.Bytes(), nil } // This function encodes... func (ge *GobEncoder) Encode(subject string, v interface{}) ([]byte, error) { b := new(bytes.Buffer) enc := gob.NewEncoder(b) if err := enc.Encode(v); err != nil { return nil, err } return b.Bytes(), nil }
Zbytečné použití else:
if _, cur := nc.currentServer(); cur == nil { return ErrNoServers } else { return SomethingElse }
11. Nástroj gocyclo
Při vývoji nových aplikací, popř. při analýze již existujících aplikací je možné sledovat různé metriky popisující kvalitu celé aplikace. Kromě klasických metrik, které jsou zaměřeny spíše na výsledný produkt a na jeho chování při běhu (výkonnost, doba odezvy, střední doba selhání, …) či na procesy související s vývojem a údržbou produktu (cena, produktivita, …) se v některých případech používají i metriky, které se nějakým způsobem snaží popsat složitost zdrojových kódů a tím pádem i pracnost opravy chyb či přidávání nových vlastností. Z hlediska implementace je jednou z nejjednodušších metrik tohoto typu takzvaná cyklomatická složitost neboli cyclomatic complexity. Zjednodušeně řešeno se jedná o číslo, kterým se snažíme vyjádřit složitost programu nebo jednotlivých logických bloků, typicky funkcí, tříd a metod (popř. celých balíků). Obecně platí, že čím větší je cyklomatická složitost daného bloku (například funkce), tím více jednotkových testů je zapotřebí vytvořit a tím složitější jsou případné další úpravy kódu (či jen jeho prosté pochopení).
Ve vybrané části programu se cyklomatická složitost počítá pomocí grafu toku řízení toho programu: uzly grafu odpovídají neoddělitelným skupinám v programu (například tělu cyklu, podmínky). Orientované hrany odpovídají tomu, v jakém pořadí se skupiny příkazů budou provádět. Cyklomatickou složitost je možné aplikovat individuálně na vybrané funkce, moduly, metody nebo třídy [1].
Implementace měření cyklomatické složitosti je relativně snadná díky tomu, že se pouze zjišťuje počet možných cest ve zdrojovém kódu, tj. provádí se statická analýza, která nevyžaduje měření prováděné v běžící aplikaci. Typicky se nástroje pro měření cyklomatické složitosti zaměřují na zjišťování počtu rozhodovacích konstrukcí (if-then, if-then-else, switch) a programových smyček (for. Tyto informace lze velmi snadno zjistit z abstraktního syntaktického stromu (AST – Abstract Syntax Tree), což je i případ nástroje nazvaného gocyclo.
Tento nástroj se nainstaluje příkazem:
$ go get github.com/fzipp/gocyclo
A zavolá se (v adresáři s projektem):
$ gocyclo parametry
Existují i některé parametry, které lze nastavit:
$ gocyclo -top 10 src/ $ gocyclo -over 25 docker $ gocyclo -avg .
12. Příklady problémů zachycených nástrojem gocyclo
Následující programový kód obsahuje mnoho podmínek v jediné funkci a proto bude mít relativně vysokou cyklomatickou komplexitu (ostatně sami se zamyslete, kolik jednotkových testů bude nutné napsat, aby se prošlo všemi větvemi):
package main import ( "fmt" "log" "os" "runtime/pprof" "strconv" ) func main() { f, err := os.Create("mandelbrot2.prof") if err != nil { log.Fatalf("failed to create profiler output file: %v", err) } defer func() { if err := f.Close(); err != nil { log.Fatalf("failed to close profiler file: %v", err) } }() if err := pprof.StartCPUProfile(f); err != nil { log.Fatalf("failed to start profle: %v", err) } defer pprof.StopCPUProfile() if len(os.Args) < 4 { println("usage: ./mandelbrot width height maxiter") os.Exit(1) } width, err := strconv.Atoi(os.Args[1]) if err != nil { fmt.Printf("Improper width parameter: '%s'\n", os.Args[1]) os.Exit(1) } height, err := strconv.Atoi(os.Args[2]) if err != nil { fmt.Printf("Improper height parameter: '%s'\n", os.Args[2]) os.Exit(1) } maxiter, err := strconv.Atoi(os.Args[3]) if err != nil { fmt.Printf("Improper maxiter parameter: '%s'\n", os.Args[3]) os.Exit(1) } renderer.Start(width, height, maxiter) }
Spočtená cyklomatická komplexita:
8 main main 18_cyclomatic_complexity.go:11:1
Ve druhém kódu je deklarováno několik funkcí a cyklomatická komplexita bude spočtena a vypsána pro všechny tyto funkce:
package renderer import ( "image" "image/png" "log" "os" ) func writeImage(width uint, height uint, pixels []byte) { img := image.NewNRGBA(image.Rect(0, 0, int(width), int(height))) pixel := 0 for y := 0; y < int(height); y++ { offset := img.PixOffset(0, y) for x := uint(0); x < width; x++ { img.Pix[offset] = pixels[pixel] img.Pix[offset+1] = pixels[pixel+1] img.Pix[offset+2] = pixels[pixel+2] img.Pix[offset+3] = 0xff pixel += 3 offset += 4 } } outputFile, err := os.Create("mandelbrot.png") if err != nil { log.Fatal(err) } defer outputFile.Close() png.Encode(outputFile, img) } func iterCount(cx float64, cy float64, maxiter uint) uint { var zx float64 = 0.0 var zy float64 = 0.0 var i uint = 0 for i < maxiter { zx2 := zx * zx zy2 := zy * zy if zx2+zy2 > 4.0 { break } zy = 2.0*zx*zy + cy zx = zx2 - zy2 + cx i++ } return i } func calcMandelbrot(width uint, height uint, maxiter uint, palette [][3]byte, image []byte, cy float64, done chan bool) { var cx float64 = -2.0 for x := uint(0); x < width; x++ { i := iterCount(cx, cy, maxiter) color := palette[i] image[3*x] = color[0] image[3*x+1] = color[1] image[3*x+2] = color[2] cx += 3.0 / float64(width) } done <- true } func Start(width int, height int, maxiter int) { done := make(chan bool, height) pixels := make([]byte, width*height*3) offset := 0 delta := width * 3 var cy float64 = -1.5 for y := 0; y < height; y++ { go calcMandelbrot(uint(width), uint(height), uint(maxiter), mandmap[:], pixels[offset:offset+delta], cy, done) offset += delta cy += 3.0 / float64(height) } for i := 0; i < height; i++ { <-done } writeImage(uint(width), uint(height), pixels) }
Vypočtené a zobrazené výsledky:
4 renderer writeImage 19_cyclomatic_complexity.go:10:1 3 renderer Start 19_cyclomatic_complexity.go:65:1 3 renderer iterCount 19_cyclomatic_complexity.go:35:1 2 renderer calcMandelbrot 19_cyclomatic_complexity.go:52:1
Reálná funkce s velkou cyklomatickou složitostí: https://github.com/gordonklaus/ineffassign/blob/master/ineffassign.go#L126 nebo https://github.com/minio/minio/blob/master/cmd/gateway/gcs/gateway-gcs.go#L556.
Další příklad s příliš velkou cyklomatickou komplexitou:
package main func main() { for x := 1; x < 10; x++ { for y := 1; y < 10; y++ { for z := 1; z < 10; z++ { if x > 5 && x < 8 && y > 5 && y < 8 && z > 5 && z < 8 { break } } } } for u := 1; u < 10; u++ { for v := 1; v < 10; v++ { for w := 1; w < 10; w++ { if u > 5 && u < 8 && v > 5 && v < 8 && w > 5 && w < 8 { break } } } } }
13. Nástroj ineffassign
Další nástroj nese název ineffassign a slouží je zjišťování neefektivních přiřazení, tj. přiřazení nulové hodnoty (první příklad) nebo dvojí (popř. vícenásobné) přiřazení do stejné proměnné bez čtení přiřazené hodnoty (druhý příklad). Tyto problémy sice samy o sobě nemusí nutně znamenat pády aplikace, ale mohou značit problémy vzniklé například refaktoringem apod.:
d := dch select { case d <- time.Now(): default: d = nil }
err := encoder.Encode(&a) decoder := gob.NewDecoder(&buffer) err = decoder.Decode(&x) if err != nil { fmt.Println(err) return }
14. Příklady problémů zachycených nástrojem ineffassign
Pravděpodobně všechny problémy, které jsou detekovatelné nástrojem ineffassign, naleznete přímo v testovacích datech tohoto nástroje na adrese https://github.com/gordonklaus/ineffassign/blob/master/testdata/testdata.go, například:
func _() { var x int x = 0 _ = x } func _() { var x int x = 0 if b { _ = x } } func _() { var x int _ = x x = 0 //x } func _() { var x int for x = range []int{} { _ = x x = 0 if b { continue } else { break } } _ = x } func _() { var x int for { if b { x = 0 //x break } _ = x } } func _() { var x int if b { x = 0 } else if b { x = 0 } _ = x }
15. Zobrazení výsledků kontrol přímo v repositáři
Poměrně velké množství projektů vytvořených v programovacím jazyce Go (ale ostatně i v mnoha dalších programovacích jazycích) obsahuje přímo ve svém souboru README.md odkazy na takzvané odznaky/visačky (badge), což jsou většinou malé obrázky (reprezentované buď ve vektorové nebo v rastrové podobě), které reprezentují nějakou metriku vztaženou k projektu. Může se například jednat o výsledky jednotkových testů, pokrytí kódu testy (vyjadřované v procentech), výsledky překladu projektu atd. Tyto visačky jsou většinou přímo poskytovány k tomu určenými službami, například Codecov.io (viz navazující kapitoly), Travis CI, Go Report Card atd. atd. V navazující kapitole se zmíníme o poslední jmenované službě, tedy Go Report Card, jejíž výhodou je, že není nutné se registrovat, pouze postačuje znát URL s repositářem obsahujícím zdrojové kódy aplikace.
16. Služba Go Report Card
Pro aplikace vytvářené v programovacím jazyku Go existuje online služba nazvaná Go Report Card. Tato služba nejenom zkontroluje zvolený repositář několika nástroji, z nichž většinu jsme si popsali v předchozích kapitolách, ale dokáže vygenerovat visačku (badge) s celkovým ohodnocením kvality zdrojových kódů projektu. Odkaz na tuto visačku lze vložit přímo do souboru README.md, který je viditelný při procházení repositáře se zdrojovými kódy. Jen pro zajímavost se podívejme na některé příklady:
# | Projekt | Stručný popis |
---|---|---|
1 | Minio | projekt Minio popsaný zde |
2 | NATS | message broker NATS popsaný zde |
3 | Kubernetes | jedna z nejdůležitějších platforem naprogramovaná v Go |
4 | go-root | repositář s příklady používanými v seriálu o Go |
17. Služba Codecov
Druhou službou, o níž se v dnešním článku alespoň ve stručnosti zmíníme, je poměrně známá služba Codecov.io (či zkráceně jen Codecov). Tato služba umožňuje sbírat informace o pokrytí zdrojového kódu jednotkovými testy s tím, že tyto informace jsou následně zobrazeny v grafické podobě, v tabulkové podobě (po balíčcích i souborech) a dokonce i pro jednotlivé pull requesty. Repositář se zdrojovými kódy je nejdříve nutné do této služby zaregistrovat (což je pro open source projekty zdarma) a následně využít vygenerované UID pro posílání informací o pokrytí kódu jednotkovými testy, což se typicky provádí na CI (například v Jenkinsu, na Travis CI atd.). A naopak – Codecov může posílat informace o pokrytí zpět do GitLabu či GitHubu a zobrazit tak změnu v pokrytí testy přímo u daného pull requestu.
18. Obsah následujícího článku
V navazujícím článku se seznámíme s některými projekty, které se zaměřují na nalezení potenciálních bezpečnostních chyb. I tyto projekty bývají založeny na analýze zdrojového kódu převedeného do AST.
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/wccode (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:
# | Příklad | Stručný popis | Cesta |
---|---|---|---|
1 | 01_missing_package.go | nekorektní zdrojový kód, v němž chybí deklarace balíčku | https://github.com/tisnik/wccode/blob/master/01_missing_package.go |
2 | 02_parenthesis.go | chybně umístěná otevírací bloková závorka | https://github.com/tisnik/wccode/blob/master/02_parenthesis.go |
3 | 03_bad_syntax.go | chybně umístěné otevírací i uzavírací blokové závorky | https://github.com/tisnik/wccode/blob/master/03_bad_syntax.go |
4 | 04_before_transform.go | zdrojový kód před transformací nástrojem gofmt | https://github.com/tisnik/wccode/blob/master/04_before_transform.go |
5 | 05_after_transform.go | zdrojový kód po transformaci nástrojem gofmt | https://github.com/tisnik/wccode/blob/master/05_after_transform.go |
6 | 06_integer_signed_types_checks.go | kontrola celočíselných konstant překladačem | https://github.com/tisnik/wccode/blob/master/06_integer_signed_types_checks.go |
7 | 07_improper_conversion.go | kontrola prováděná při typových konverzích (celočíselné datové typy) | https://github.com/tisnik/wccode/blob/master/07_improper_conversion.go |
8 | 08_fp_types_checks.go | kontrola prováděná při typových konverzích (typy s plovoucí řádovou čárkou) | https://github.com/tisnik/wccode/blob/master/08_fp_types_checks.go |
9 | 09_nil_map.go | pokus o zápis do takzvané nulové mapy (nil map) | https://github.com/tisnik/wccode/blob/master/09_nil_map.go |
10 | 10_nil_pointer.go | pokus o přístup do struktury přes nulový ukazatel (nil pointer) | https://github.com/tisnik/wccode/blob/master/10_nil_pointer.go |
11 | 11_unreachable_code.go | zdrojový kód, jehož části nejsou dosažitelné | https://github.com/tisnik/wccode/blob/master/11_unreachable_code.go |
12 | 12_shift.go | použití bitového posunu o 70 bitů v 64bitové proměnné | https://github.com/tisnik/wccode/blob/master/12_shift.go |
13 | 13_printf_checks.go | kontrola parametrů funkce fmt.Printf | https://github.com/tisnik/wccode/blob/master/13_printf_checks.go |
14 | 14_sprintf_checks.go | kontrola parametrů funkce fmt.Sprintf i její návratové hodnoty | https://github.com/tisnik/wccode/blob/master/14_sprintf_checks.go |
15 | 15_read_byte_methods.go | kontrola signatury metody ze známého rozhraní | https://github.com/tisnik/wccode/blob/master/15_read_byte_methods.go |
16 | 16_simple_server.go | jednoduchý HTTP server, ne všechny chybové kódy jsou ošetřeny | https://github.com/tisnik/wccode/blob/master/16_simple_server.go |
17 | 17_png_output.go | zápis do PNG, opět ne všechny chybové kódy jsou ošetřeny | https://github.com/tisnik/wccode/blob/master/17_png_output.go |
18 | 18_cyclomatic_complexity.go | kód pro měření cyklomatické složitosti | https://github.com/tisnik/wccode/blob/master/18_cyclomatic_complexity.go |
19 | 19_cyclomatic_complexity.go | kód pro měření cyklomatické složitosti | https://github.com/tisnik/wccode/blob/master/19_cyclomatic_complexity.go |
20. Odkazy na Internetu
- 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