Obsah
1. Programovací jazyk Go pro skalní céčkaře
2. Základní rozdíly v syntaxi jazyků Go a C i ve struktuře programů
3. Klíčová slova programovacího jazyka Go
7. Zřetězené podmínky a jejich náhrada za switch
8. Programová smyčka typu while
9. Programová smyčka typu do-while
10. Počítaná programová smyčka typu for, více řídicích proměnných smyčky
11. Programová smyčka s podmínkou uprostřed
15. Funkce s proměnným počtem parametrů
18. Obsah následující části seriálu
19. Repositář s demonstračními příklady
1. Programovací jazyk Go pro skalní céčkaře
Poměrně často se uvádí, že na programovací jazyk Go přechází vývojáři, kteří používají programovací jazyk Python (což je téma popsané v knize [1]). To je na první pohled poněkud překvapivé zjištění, ovšem na druhou stranu se niky těchto dvou programovacích jazyků skutečně částečně překrývají, a to konkrétně u síťových a administrativních nástrojů. Přechod ke Go může pro nově vyvíjené projekty z této oblasti přinášet některé výhody [2] [3]. Ovšem existuje i velké množství vývojářů, kteří začínají Go používat i v těch oblastech, ve kterých se již po několik desetiletí používají programovací jazyky C a C++. Dnešní článek je zaměřen právě na céčkaře, protože se v něm snažím upozornit na ty vlastnosti jazyka Go, které mohou být překvapující nebo odlišné od toho, s čím se setkáme v céčku.
V dalších kapitolách (i v navazující části tohoto seriálu) se budeme zabývat především tím, jaké existují ekvivalentní náhrady původních céčkových jazykových konstrukcí popř. funkcí ze standardní knihovny v programovacím jazyce Go. To mj. znamená, že se nebudeme soustředit na ty vlastnosti programovacího jazyka Go, které v klasickém C nemají přímou obdobu. Jedná se například o gorutiny a kanály. Pro ty sice existují v céčku příslušné knihovny (jimiž se taktéž budeme zabývat, ale až mnohem později), ovšem přímé porovnání s konstrukcemi jazyka Go nebude uvedeno.
Další informace o této problematice je možné najít na stránce GoForCPPProgrammers, stručné porovnání jednotlivých vlastností obou programovacích jazyků pak na stránce Hyperpolyglot: C, Go.
2. Základní rozdíly v syntaxi jazyků Go a C i ve struktuře programů
Nejprve se podívejme na to, jak se liší základní struktura programů vytvořených v programovacím jazyce Go a C. Nejjednodušší program, který po svém spuštění pouze nastaví návratový kód a ihned skončí, vypadá v C (konkrétně v ANSI C) takto:
int main(void) { return 0; }
V jazyku Go je struktura nepatrně odlišná. Především je nutné uvést jméno balíčku pomocí deklarace package. Dále se funkce main (jméno se nezměnilo) deklaruje s využitím klíčového slova func, tato funkce nemá žádné parametry (ani void – koncept void v Go ostatně vůbec neexistuje) a ani návratovou hodnotu; tudíž se nemusí použít ani příkaz return:
package main func main() { }
Nepatrně složitější program typu „Hello world“ již vyžaduje použití knihovních funkcí, jejichž hlavičky se načtou příkazem preprocesoru #include a o slinkování knihovny se musí postarat až linker. V céčku se může jednat o funkci puts, příkaz pro její zavolání povinně končí středníkem:
#include <stdio.h> int main(void) { puts("Hello world!"); return 0; }
V případě jazyka Go se namísto příkazu preprocesoru #include používá deklarace import zajišťující jak načtení funkcí, tak i jejich slinkování do výsledného spustitelného souboru. Jméno volané funkce se zapisuje včetně jména balíčku a externě viditelné funkce začínají velkým písmenem. Za příkazem pro volání funkce se nemusí zapisovat středník (a ani to prakticky nikdo nedělá):
package main import "fmt" func main() { fmt.Println("Hello world!") }
3. Klíčová slova programovacího jazyka Go
V programovacím jazyce Go existuje celkem 25 klíčových slov, z nichž některé jsou odlišné od céčka. V praxi to znamená, že se při přepisu některých programů z C do Go může narazit na identifikátory, které je zapotřebí přejmenovat, protože není možné změnit význam klíčových slov (pravděpodobně se bude jednat o slova map a interface):
break | default | func | interface | select |
case | defer | go | map | struct |
chan | else | goto | package | switch |
const | fallthrough | if | range | type |
continue | for | import | return | var |
Kromě těchto klíčových slov se v Go setkáme s několika identifikátory, které mají pevný význam. Typicky se jedná o konstanty, v jednom případě o „automaticky měněnou konstantu“ a o pojmenování standardních datových typů. Jedná se o následující slova:
Identifikátor | Typ | Stručný popis |
---|---|---|
true | konstanta | pravdivostní hodnota |
false | konstanta | pravdivostní hodnota |
iota | konstanta | celočíselný automaticky zvyšovaný čítač |
nil | konstanta | prázdná hodnota, prázdné rozhraní |
bool | datový typ | logický/pravdivostní typ |
byte | datový typ | alias pro typ uint8 |
int | datový typ | odpovídá buď typu int32 nebo int64 |
int8 | datový typ | osmibitové celé číslo se znaménkem |
int16 | datový typ | šestnáctibitové celé číslo se znaménkem |
int32 | datový typ | 32bitové celé číslo se znaménkem |
int64 | datový typ | 64bitové celé číslo se znaménkem |
uint | datový typ | odpovídá buď typu uint32 nebo uint64 |
uint8 | datový typ | osmibitové celé číslo bez znaménka |
uint16 | datový typ | 16bitové celé číslo bez znaménka |
uint32 | datový typ | 32bitové celé číslo bez znaménka |
uint64 | datový typ | 64bitové celé číslo bez znaménka |
float32 | datový typ | číslo s jednoduchou přesností podle IEEE 754 |
float64 | datový typ | číslo s dvojitou přesností podle IEEE 754 |
complex64 | datový typ | dvojice hodnot s jednoduchou přesností |
complex128 | datový typ | dvojice hodnot s dvojitou přesností |
error | datový typ | rozhraní s předpisem metody Error |
rune | datový typ | alias pro typ int32 |
string | datový typ | |
uintptr | datový typ | používáno pro uložení adresy (ukazatele) |
Tyto identifikátory je sice možné použít i v jiném kontextu, ovšem silně nedoporučuji to dělat. Nicméně z hlediska překladače je následující program zcela korektní (z ostatních hledisek se jedná o programátorskou zvrhlost :-):
package main func main() { true := 42 false := "foobarbaz" println(true) println(false) }
4. Deklarace proměnných
Poměrně velké rozdíly mezi oběma jazyky nalezneme při deklaraci proměnných, ať již se jedná o proměnné globální či lokální. V céčku existují poměrně sofistikovaná (a pochopitelně jednoznačná) pravidla, kterými se deklarace proměnných řídí, a to i v případě, že je typ proměnné netriviální – ukazatel na funkci, pole ukazatelů, ukazatel na ukazatel atd, I přesto, že jsou pravidla jednoznačná, nemusí být jejich zápis a čtení snadné:
int x; unsigned char *y; int a[10]; int *px; int *py[10]; int (*pz)[10]; int *(*pw)[10]; float **m;
V programovacím jazyce Go se pravidla pro zápis deklarace proměnných do značné míry zjednodušila, a to takovým způsobem, aby byla deklarace (relativně) snadno čitelná zleva doprava (a to i v případě proměnných, jejichž hodnotou může být funkce):
var x int var x2 int = 1 var a [10]int var px *int var py *[10]int var f1 func() var f2 func(int, int) int
Navíc se v jazyce Go objevuje i možnost deklarace proměnné s její inicializací a automatickým odvozením jejího typu. Pro tento účel se používá operátor :=, a to následujícím způsobem:
i := 10 f := 3.14 s := "foobar"
5. Základní datové typy
Nabídka základních datových typů je jak v jazyku C, tak i v Go poměrně rozsáhlá a do značné míry shodná, ovšem v Go je (především u celočíselných datových typů) přesně definována bitová šířka většiny typů a tím pádem i rozsah povolených hodnot. V C tomu tak u obecných datových typů int, long, float atd. z dobrých důvodů není, a to mj. i z toho důvodu, že je tento jazyk používán na mnohdy dosti „obskurních“ platformách typu DSP se šířkou datové sběrnice a aritmeticko-logické jednotky 20 bitů (někdy navíc s 21bitovým mezivýsledkem).
V následující tabulce jsou uvedeny ekvivalentní či většinou ekvivalentní datové typy mezi C99 a Go (blíže viz https://en.cppreference.com/w/c/types/integer):
Typ v C99 | Typ v Go |
---|---|
_Bool/bool | bool |
signed char | int8 (ovšem klasické znaky jsou rune) |
unsigned char | uint8 |
int8_t | int8 |
int16_t | int16 |
int32_t | int32 |
int64_t | int64 |
intptr_t | uintptr (viz níže) |
uint8_t | uint8 |
uint16_t | uint16 |
uint32_t | uint32 |
uint64_t | uint64 |
uintptr_t | uintptr |
float | float32 (platí na většině platforem) |
double | float64 (platí na většině platforem) |
long double | není podporováno (pokud se jedná o 80bitovou šířku) |
float _Complex/float complex | complex64 |
double _Complex/double complex | complex128 |
long double _Complex/long double complex | není podporováno |
Poměrně často se v céčkovských programech setkáme s použitím operátoru sizeof:
#include <stdio.h> int main(void) { printf("sizeof char = %lu byte(s)\n", sizeof(char)); printf("sizeof short = %lu byte(s)\n", sizeof(short)); printf("sizeof int = %lu byte(s)\n", sizeof(int)); printf("sizeof long = %lu byte(s)\n", sizeof(long)); printf("sizeof long long = %lu byte(s)\n", sizeof(long long)); printf("sizeof float = %lu byte(s)\n", sizeof(float)); printf("sizeof double = %lu byte(s)\n", sizeof(double)); return 0; }
Přepis do Go je v tomto případě nepatrně složitější, neboť je nutné použít funkce z balíčku unsafe, kterým se ovšem nepředává datový typ, ale přímo hodnota určitého typu:
package main import ( "fmt" "unsafe" ) func main() { fmt.Printf("sizeof int8 = %d byte(s)\n", unsafe.Sizeof(int8(0))) fmt.Printf("sizeof int16 = %d byte(s)\n", unsafe.Sizeof(int16(0))) fmt.Printf("sizeof int32 = %d byte(s)\n", unsafe.Sizeof(int32(0))) fmt.Printf("sizeof int64 = %d byte(s)\n", unsafe.Sizeof(int64(0))) fmt.Printf("sizeof int = %d byte(s)\n", unsafe.Sizeof(int(0))) fmt.Printf("sizeof float32 = %d byte(s)\n", unsafe.Sizeof(float32(0))) fmt.Printf("sizeof float64 = %d byte(s)\n", unsafe.Sizeof(float64(0))) fmt.Printf("sizeof complex64 = %d byte(s)\n", unsafe.Sizeof(complex64(0))) fmt.Printf("sizeof complex128 = %d byte(s)\n", unsafe.Sizeof(complex128(0))) fmt.Printf("sizeof uintptr = %d byte(s)\n", unsafe.Sizeof(uintptr(0))) }
6. Podmínky
V této kapitole se zaměříme na popis základních rozdílů mezi programovými konstrukcemi určenými pro řízení běhu programu. V první řadě se pochopitelně jedná o podmínky a s nimi souvisejícím rozvětvením běhu programu. V programovacím jazyku C máme k dispozici podmíněnou konstrukci s jednou větví if i plné rozvětvení realizované konstrukcí typu if-else. Jednotlivé větve mohou být tvořeny jedním příkazem popř. blokem příkazů uzavřených do složených závorek. Samotná testovaná podmínka, což je většinou celočíselný výraz, musí být vždy umístěna do kulatých závorek:
#include <stdio.h> int main(void) { int x = 10; if (x > 0) { puts("x is positive number"); } return 0; }
alternativně též bez použití bloku:
#include <stdio.h> int main(void) { int x = 10; if (x > 0) puts("x is positive number"); return 0; }
Naproti tomu v programovacím jazyku Go platí nepatrně odlišná pravidla. Především se výraz představující podmínku musí vyhodnotit na pravdivostní hodnotu true nebo false. Dále se tento výraz nemusí uzavírat do kulatých závorek. Samotné větve jsou vždy tvořeny bloky, tj. nemusíme se bát, že se přidáním dalšího příkazu do původně jednopříkazové větvě celá struktura programu změní (chyba typu Apple GOTO fail):
package main import "fmt" func main() { x := 10 if x > 0 { fmt.Println("x is positive number") } }
Plné rozvětvení typu if-else je v céčku realizováno takto:
#include <stdio.h> int main(void) { int x = 10; if (x > 0) { puts("x is positive number"); } else { puts("x is negative number or zero"); } return 0; }
Popř. bez bloků:
#include <stdio.h> int main(void) { int x = 10; if (x > 0) puts("x is positive number"); else puts("x is negative number or zero"); return 0; }
V jazyku Go jsou bloky povinné a navíc je vyžadováno, aby klíčové slovo else leželo na stejném řádku, jako pravá uzavírací závorka:
package main import "fmt" func main() { x := 10 if x > 0 { fmt.Println("x is positive number") } else { fmt.Println("x is negative number or zero") } }
Kromě toho lze v programovacím jazyku Go deklarovat proměnné, které jsou lokální pouze v rámci konstrukce if popř. úplného rozvětvení if-else. Mimo tuto konstrukci není proměnná viditelná:
if result, err := compute(x,y); err != nil { ... ... ... } else { ... ... ... }
V tomto příkladu jsou deklarovány dvě proměnné nazvané result a err, které jsou viditelné pouze uvnitř rozhodovací konstrukce. Na základě hodnoty proměnné err se aplikace rozhoduje, zda vstoupit do větve if nebo naopak do větve else. Pokud bychom nevyžadovali použití lokálně viditelných proměnných, můžeme samozřejmě psát:
result, err := compute(x,y) if err != nil { ... ... ... } else { ... ... ... }
7. Zřetězené podmínky a jejich náhrada za switch
V programovacím jazyku C je možné podmínky zřetězit, popř. vnořit. Podívejme se na jednoduchý demonstrační příklad, v němž se provádí test, jestli je obsahem celočíselné proměnné kladné číslo, číslo záporné nebo nula:
#include <stdio.h> int main(void) { int x = 0; if (x > 0) { puts("x is positive number"); } else if (x == 0) { puts("x is zero"); } else { puts("x is negative number"); } return 0; }
Přepis do Go je v tomto případě přímočarý, samozřejmě s tím rozdílem, že se podmínky nemusí zapisovat do kulatých závorek a příkazy se neukončují středníkem:
package main import "fmt" func main() { x := 10 if x > 0 { fmt.Println("x is positive number") } else if x == 0 { fmt.Println("x is zero") } else { fmt.Println("x is negative number") } }
Tento příklad lze přepsat takovým způsobem, že se namísto zřetězení konstrukcí typu if-else použije konstrukce typu switch. V programovacím jazyku Go je totiž možné do jednotlivých větví case zapisovat plnohodnotné podmínky a v tomto případě se za samotné klíčové slovo switch nezapisuje žádný výraz. Jednotlivé větve se neukončují slovem break:
package main import "fmt" func main() { x := 10 switch { case x > 0: fmt.Println("x is positive number") case x == 0: fmt.Println("x is zero") default: fmt.Println("x is negative number") } }
8. Programová smyčka typu while
V programovacím jazyku C existují tři typy programových smyček: while, do-while a počítaná smyčka for. Nejprve si ukažme nejjednodušší způsob použití smyčky while, v níž se podmínka testuje na začátku každé iterace, tedy před vstupem do smyčky:
#include <stdio.h> int main(void) { int x = 1; while (x <= 10) { printf("%d\n", x); x++; } return 0; }
V programovacím jazyce Go je nutné tento typ smyčky realizovat s využitím klíčového slova for, za které se napíše pouze podmínka. Ta je opět testována před vstupem do těla smyčky a tudíž se tento typ programové smyčky nemusí provést ani jednou:
package main import "fmt" func main() { x := 1 for x <= 10 { fmt.Printf("%d\n", x) x++ } }
#include <stdio.h> int main(void) { int x = 0; while (x++ < 10) { printf("%d\n", x); } return 0; }
9. Programová smyčka typu do-while
Druhým typem programové smyčky v programovacím jazyku C je smyčka typu do-while, v níž je test, zda provést či neprovést další iteraci, vyhodnocen až na konci každého cyklu:
#include <stdio.h> int main(void) { int x = 1; do { printf("%d\n", x); x++; } while (x <= 10); return 0; }
V jazyku Go v tomto případě budeme muset použít pomocnou proměnnou a použít plnou podobu programové smyčky for s inicializačním výrazem, podmínkou a výrazem spuštěným na konci těla smyčky:
package main import "fmt" func main() { x := 1 for cond := true; cond; cond = x <= 10 { fmt.Printf("%d\n", x) x++ } }
V tomto příkladu byla vytvořena lokální proměnná cond, která je na konci každé iterace znovu nastavena na pravdivostní hodnotu vyjádřenou podmínkou. Na základě této hodnoty je smyčka buď ukončena nebo je provedena další iterace.
10. Počítaná programová smyčka typu for, více řídicích proměnných smyčky
V programovacím jazyku C se velmi často setkáme s počítanou programovou smyčkou, v níž je použita jedna řídicí proměnná fungující jako počitadlo smyčky:
#include <stdio.h> int main(void) { int x; for (x=1; x <= 10; x++) { printf("%d\n", x); } return 0; }
Popř. v C99:
#include <stdio.h> int main(void) { for (int x=1; x <= 10; x++) { printf("%d\n", x); } return 0; }
Přepis do jazyka Go je v tomto případě přímočarý a můžeme (podobně jako v C99) použít lokální proměnnou jako počitadlo (proměnná bude viditelná a platná jen v rámci smyčky). Povšimněte si, že se všechny tři výrazy za klíčovým slovem for neuzavírají do závorek:
package main import "fmt" func main() { for x := 1; x <= 10; x++ { fmt.Printf("%d\n", x) } }
Samozřejmě není nutné, aby se počitadlo smyčky zvyšovalo či snižovalo o jedničku, ale můžeme použít složitější výpočet:
#include <stdio.h> int main(void) { int x; for (x=1; x <= 10000; x<<=1) { printf("%d\n", x); } return 0; }
Přepis do Go je i zde přímočarý:
package main import "fmt" func main() { for x := 1; x <= 10000; x<<=1 { fmt.Printf("%d\n", x) } }
V posledním příkladu jsou použity dvě proměnné, z nichž jedna se zvyšuje o jedničku (jako běžné počitadlo) a druhá se s každou iterací zdvojnásobí:
#include <stdio.h> int main(void) { int i,x; for (i=0, x=1; i <= 10; i++, x<<=1) { printf("2^%d = %d\n", i, x); } return 0; }
Tento příklad není možné v Go zapsat stejným způsobem, protože Go nepodporuje operátor čárky. Ovšem můžeme zde použít malého triku – vícenásobného přiřazení, a to jak v prvním výrazu (inicializace obou proměnných), tak i v iteračním výrazu:
package main import "fmt" func main() { for i, x := 0, 1; x <= 10000; i, x = i+1, x<<1 { fmt.Printf("%d\n", x) } }
11. Programová smyčka s podmínkou uprostřed
Programovou smyčku s podmínkou vyhodnocovanou uprostřed těla smyčky lze realizovat různým způsobem. V céčku se často můžeme setkat s následujícím postupem, v němž je smyčka na základě podmínky ukončena příkazem break:
#include <stdio.h> int main(void) { int x = 1; while (1) { printf("%d\n", x); x++; if (x > 10) break; } return 0; }
Prakticky stejným způsobem, jen s nepatrnými rozdíly v syntaxi, se může provést zápis v jazyce Go. Povšimněte si, že v tomto případě není za klíčovým slovem for uvedena žádná podmínka:
package main import "fmt" func main() { x := 1 for { fmt.Printf("%d\n", x) x++ if x > 10 { break } } }
Pokud ovšem preferujete, aby byla proměnná x lokální v rámci smyčky, musí se podmínka zapsat, ovšem postačuje použít hodnotu true, která se vyhodnotí opět na true. Poslední výraz za středníkem lze zcela vynechat, ovšem středník je zde nutné ponechat:
package main import "fmt" func main() { for x := 1; true; { fmt.Printf("%d\n", x) x++ if x > 10 { break } } }
12. Konstrukce switch
Ještě větší rozdíly mezi oběma programovacími jazyky nalezneme v rozhodovací konstrukci switch. Ta se ve standardním cečku používá pro rozeskok na základě hodnoty celočíselného výrazu, jehož výsledek je postupně porovnáván s celočíselnými konstantami. Pokud mají být jednotlivé větve rozeskoku odděleny, musí být každá větev explicitně ukončena příkazem break popř. příkazem return (některé lintery ovšem vyžadují zápis break i za return což je přinejmenším nadbytečné). V následujícím příkladu využíváme toho, že bez ukončení větve příkazy break/return je řízení běhu programu automaticky předáno do následující větve, takže se například všechna sudá čísla v rozsahu od 0 do 9 zpracují jediným společným příkazem:
#include <stdio.h> const char *classify(int x) { switch (x) { case 0: return "nula"; case 2: case 4: case 6: case 8: return "sudé číslo"; case 1: case 3: case 5: case 7: case 9: return "liché číslo"; default: return "?"; } } int main(void) { int x; for (x = 0; x <= 10; x++) { printf("%d: %s\n", x, classify(x)); } return 0; }
V programovacím jazyku Go se příkaz break v konstrukci switch nepoužívá, protože je proveden skutečný rozeskok. Pokud je nutné, aby se pro dvě či více podmínek vykonala společná část kódu, musí se použít klíčové slovo fallthrough, ovšem v reálných programech se s ním příliš často nesetkáme. Nejvíce rozdílů ovšem nalezneme u podmínek zapisovaných za klíčovým slovem case; nemusí se totiž jednat o pouhé celočíselné konstanty, ale o složitější výrazy, včetně seznamu (přesněji řečeno výčtu) hodnot:
package main import "fmt" func classify(x int) string { switch x { case 0: return "nula" case 2, 4, 6, 8: return "sudé číslo" case 1, 3, 5, 7, 9: return "liché číslo" default: return "?" } } func main() { for x := 0; x <= 10; x++ { fmt.Printf("%d: %s\n", x, classify(x)) } }
Otrocký přepis předchozího céčkového programu do programovacího jazyka Go bude delší a méně čitelný:
package main import "fmt" func classify(x int) string { switch x { case 0: return "nula" case 2: fallthrough case 4: fallthrough case 6: fallthrough case 8: return "sudé číslo" case 1: fallthrough case 3: fallthrough case 5: fallthrough case 7: fallthrough case 9: return "liché číslo" default: return "?" } } func main() { for x := 0; x <= 10; x++ { fmt.Printf("%d: %s\n", x, classify(x)) } }
13. Deklarace a volání funkcí
Každý céčkový program obsahuje deklaraci funkcí a jejich volání. Jen pro úplnost si uveďme, jak taková deklarace vypadá v případě funkce bez parametrů a bez návratové hodnoty:
#include <stdio.h> void printHello(void) { puts("Hello world!"); } int main(void) { printHello(); return 0; }
Přepis do Go bude v tomto případě snadný, protože použijeme klíčové slovo func, funkce bez parametrů obsahuje za svým jménem prázdné závorky (což má v C odlišný význam!) a případný návratový typ/typy je uveden až za těmito závorkami:
package main import "fmt" func printHello() { fmt.Println("Hello world!") } func main() { printHello() }
Příklad funkce s parametrem zapsané v C:
#include <stdio.h> void printHello(const char *message) { puts(message); } int main(void) { printHello("Hello world!"); return 0; }
Ekvivalentní zápis v Go:
package main import "fmt" func printMessage(message string) { fmt.Println(message) } func main() { printMessage("Hello world!") }
14. Návratové hodnoty funkcí
Funkce getMessage s návratovou hodnotou zapsaná v C:
#include <stdio.h> const char *getMessage(void) { return "Hello world!"; } void printMessage(const char *message) { puts(message); } int main(void) { printMessage(getMessage()); return 0; }
Přepis do Go; v tomto případě se návratový typ zapisuje mezi uzavírací kulatou závorku a otevírací závorku s tělem funkce:
package main import "fmt" func getMessage() string { return "Hello world!" } func printMessage(message string) { fmt.Println(message) } func main() { printMessage(getMessage()) }
15. Funkce s proměnným počtem parametrů
V některých aplikacích se setkáme s funkcemi s proměnným počtem parametrů. Skutečný počet parametrů musí být volané funkci nějakým způsobem sdělen, například předáním počtu ve zvláštním parametru, použitím formátovacího řetězce či jeho obdoby (printf) nebo například tím, že poslední parametr bude mít určitou předem známou hodnotu (0, –1, NULL atd.). Ukažme si první popsaný způsob, tj. explicitní předání počtu parametrů u funkcí f2 a f3:
#include <stdio.h> #include <stdarg.h> void f1(const char *msg) { printf("%s\n", msg); } void f2(int count, ...) { int i; va_list args; va_start(args, count); for (i = 0; i < count; i++) { char *msg = va_arg(args, char *); printf("%s ", msg); } putchar('\n'); va_end(args); } void f3(char *prefix, int count, ...) { int i; va_list args; printf("%s ", prefix); va_start(args, count); for (i = 0; i < count; i++) { char *msg = va_arg(args, char *); printf("%s ", msg); } putchar('\n'); va_end(args); } int main(void) { f1("Hello"); f2(3, "Hello", "world", "!"); f3("Message:", 4, "Hello", "world", "again", "!"); return 0; }
Můžeme vidět, že celé zpracování proměnného počtu parametrů je řešeno knihovními funkcemi va_start, va_arg a va_end.
V případě programovacího jazyka Go se používá poněkud odlišný přístup, kdy je určen typ parametrů, ovšem jejich počet se získá automaticky při průchodu všemi parametry:
package main import "fmt" func f1(msg string) { fmt.Printf("%s\n", msg) } func f2(parts ...string) { for _, val := range parts { fmt.Printf("%s ", val) } fmt.Println() } func f3(prefix string, parts ...string) { fmt.Printf("%s ", prefix) for _, val := range parts { fmt.Printf("%s ", val) } fmt.Println() } func main() { f1("Hello") f2("Hello", "world", "!") f3("Message:", "Hello", "world", "again", "!") }
16. Konstanty
V programovacím jazyku C lze konstanty vytvořit buď s využitím preprocesoru (#define), což zajistí textovou substituci jména konstanty za její obsah, nebo s využitím klíčového slova const společně s deklarací a inicializací proměnné. V programovacím jazyku Go lze konstanty taktéž vytvářet s využitím klíčového slova const, které zde ovšem nepředstavuje modifikátor, ale začátek deklarace. Typ konstanty je buď odvozen automaticky z přiřazované hodnoty (může se jednat i o konstantní výraz), nebo je alternativně možné typ konstanty uvést explicitně:
package main import "fmt" const Pi float64 = 3.1415927 const E = 2.71828 const z0 int = 0 const z1 = 0 const z2 = z0 + z1 func main() { fmt.Printf("Pi = %f\n", Pi) fmt.Printf("e = %f\n", E) fmt.Printf("z0 = %d\n", z0) fmt.Printf("z1 = %d\n", z1) fmt.Printf("z2 = %d\n", z2) }
To, že const v Go znamená začátek deklarace a ne „pouhý“ modifikátor datového typu, je zřejmé z následujícího příkladu, v němž jsou konstanty vytvořeny v jediném bloku:
package main import "fmt" const ( Pi float64 = 3.1415927 E = 2.71828 z0 int = 0 z1 = 0 z2 = z0 + z1 ) func main() { fmt.Printf("Pi = %f\n", Pi) fmt.Printf("e = %f\n", E) fmt.Printf("z0 = %d\n", z0) fmt.Printf("z1 = %d\n", z1) fmt.Printf("z2 = %d\n", z2) }
17. Náhrada za výčtový typ
V jazyku C mají programátoři k dispozici datový typ výčet (enum), v němž je jednotlivým položkám automaticky či manuálně přiřazena nějaká celočíselná hodnota (ve výchozím nastavení index položky):
#include <stdio.h> enum { Pondeli, Utery, Streda, Ctvrtek, Patek, Sobota, Nedele }; int main(void) { printf("%d\n", Pondeli); printf("%d\n", Streda); printf("%d\n", Patek); return 0; }
Tuto možnost sice v Go přímo nemáme, ovšem existuje částečně ekvivalentní řešení postavené na použití „automaticky měněné konstanty“ iota, kterou lze považovat za počitadlo položky:
package main import "fmt" const ( Pondeli = iota Utery Streda Ctvrtek Patek Sobota Nedele ) func main() { fmt.Printf("%d\n", Pondeli) fmt.Printf("%d\n", Streda) fmt.Printf("%d\n", Patek) }
18. Obsah následující části seriálu
V následující části tohoto seriálu se opět zaměříme na porovnání možností jazyků C a Go. Popíšeme si tato témata:
- Aritmetické výpočty, knihovna s matematickými funkcemi
- Zpracování řetězců
- Funkce pro práci s řetězci
- Datum a čas
- Práce se soubory
- Uživatelsky definované datové typy
- Zpracování chyb (praktické ukázky a porovnání)
- Interakce aplikace s okolním systémem
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 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:
20. Odkazy na Internetu
- 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