Obsah
1. Formátovaný tisk obsahu tabulek a dalších datových struktur
2. Načtení tabulky z formátu CSV balíčkem olekukonko/tablewriter
3. Nastavení zarovnání hodnot ve sloupcích
4. Tabulka vložitelná do souboru ve formátu Markdown
5. Horizontální oddělovače mezi řádky tabulky
6. Automatické spojení buněk se shodným obsahem
7. Specifikace sloupců, ve kterých má ke spojení buněk dojít
8. Získání řetězce reprezentujícího celou vykreslenou tabulku
10. Nepracuje se pouze s tabulkami: pokročilá knihovna go-pretty
11. Zobrazení jednoduché tabulky knihovnou go-pretty
14. Ostatní styly okrajů tabulek
15. Styly se změnou barvy tabulky či její části
16. Ostatní připravené barevné styly
17. Obsah následující části seriálu
18. Příloha: často používané formáty tabulek vykreslených neproporcionálním písmem
19. Repositář s demonstračními příklady
1. Formátovaný tisk obsahu tabulek a dalších datových struktur
V předchozím článku jsme se seznámili s několika možnostmi formátování tabulek (resp. přesněji řečeno dat organizovaných do formy dvojrozměrné tabulky) tak, aby se naformátovaná tabulka mohla zobrazit na běžném terminálu (konzoli) s neproporcionálním fontem. Připomeňme si ve stručnosti, že popsáno bylo hned několik balíčků určených pro programovací jazyk Go, které tvorbu naformátovaných tabulek podporují. Především se jedná o standardní balíček text/tabwriter, který dokáže naformátovat prakticky jakýkoli text, v němž jsou jednotlivé buňky výsledné tabulky ukončeny (nikoli ovšem rozděleny) zadaným znakem, jímž je typicky znak Tab (v řetězci je reprezentován symbolem ‚\t‘. Tento standardní balíček má poměrně široké možnosti využití, ovšem nemusí se hodit pro všechny situace. Na druhou stranu je jeho použití triviální a spočívá (poněkud zjednodušeně řečeno) v náhradě funkcí fmt.Print??? za funkce tabwriter.Fprint???, a to z toho důvodu, že balíček text/tabwriter splňuje standardní rozhraní io.Writer.
Příklad zobrazení tabulky tímto balíčkem. Povšimněte si možnosti specifikace vodicích znaků:
1..........1..........1 22.........22.........22 333........333........333 4444.......4444.......4444
Další způsob zobrazení tabulky:
N1| N2| N3| 1| 1| 1| 22| 22| 22| 333| 333| 333| 4444| 4444| 4444|
Minule jsme se, i když prozatím ve stručnosti, věnovali i dalším dvěma balíčkům nazvaným tablewriter a tableprinter. Základem je balíček tablewriter, resp. přesněji olekukonko/tablewriter, jenž umožňuje tabulku nejdříve postupně zkonstruovat z jednotlivých řádků (metoda Append) a posléze celou tabulku naformátovat a zobrazit metodou Render. Viz též následující demonstrační příklad:
package main import ( "os" "github.com/olekukonko/tablewriter" ) func main() { data := [][]string{ []string{"A", "The Good", "500"}, []string{"B", "The Very very Bad Man", "288"}, []string{"C", "The Ugly", "120"}, []string{"D", "The Gopher", "800"}, } table := tablewriter.NewWriter(os.Stdout) table.SetHeader([]string{"Name", "Sign", "Rating"}) for _, v := range data { table.Append(v) } table.Render() }
Výsledná tabulka vypadá značně odlišně od předchozích tabulek, mj. i díky tomu, že obsahuje hlavičku, patičku, okraje sloupců atd:
+------+-----------------------+--------+ | NAME | SIGN | RATING | +------+-----------------------+--------+ | A | The Good | 500 | | B | The Very very Bad Man | 288 | | C | The Ugly | 120 | | D | The Gopher | 800 | +------+-----------------------+--------+ | SUM | 1708 | +------+-----------------------+--------+
Další možnosti nabízené knihovnou tablewriter jsou ukázány v navazujících kapitolách.
2. Načtení tabulky z formátu CSV balíčkem olekukonko/tablewriter
Knihovna tablewriter dokáže načítat data ve formátu CSV, a to jak tabulky bez hlavičky, tak i tabulky s hlavičkou. Pro otestování této možnosti použijeme CSV soubor s následujícím obsahem:
"Sep 2019","Change","Language","Ratings","Changep" "2","change","C","15.95","0.74" "1","change","Java","13.48","-3.18" "3","","Python","10.47","0.59" "4","","C++","7.11","1.48" "5","","C#","4.58","1.18" "6","","Visual Basic","4.12","0.83" "7","","JavaScript","2.54","0.41" "9","change","PHP","2.49","0.62" "19","change","R","2.37","1.33" "8","change","SQL","1.76","-0.19" "14","change","Go","1.46","0.24" "16","change","Swift","1.38","0.28" "20","change","Perl","1.30","0.26" "12","change","Assembly language","1.30","-0.08" "15","","Ruby","1.24","0.03"
V dalším příkladu je ukázáno, jak se takový soubor načte: použije se odlišný konstruktor tabulky nazvaný NewCSV, kterému se předá jak objekt splňující rozhraní io.Writer, tak i jméno tabulky a příznak, zda tabulka obsahuje hlavičky:
package main import ( "log" "os" "github.com/olekukonko/tablewriter" ) func main() { table, err := tablewriter.NewCSV(os.Stdout, "tiobe.csv", false) if err != nil { log.Fatal(err) } table.Render() }
Výsledkem je tabulka neobsahující hlavičku:
+----------+--------+-------------------+---------+---------+ | Sep 2019 | Change | Language | Ratings | Changep | | 2 | change | C | 15.95 | 0.74 | | 1 | change | Java | 13.48 | -3.18 | | 3 | | Python | 10.47 | 0.59 | | 4 | | C++ | 7.11 | 1.48 | | 5 | | C# | 4.58 | 1.18 | | 6 | | Visual Basic | 4.12 | 0.83 | | 7 | | JavaScript | 2.54 | 0.41 | | 9 | change | PHP | 2.49 | 0.62 | | 19 | change | R | 2.37 | 1.33 | | 8 | change | SQL | 1.76 | -0.19 | | 14 | change | Go | 1.46 | 0.24 | | 16 | change | Swift | 1.38 | 0.28 | | 20 | change | Perl | 1.30 | 0.26 | | 12 | change | Assembly language | 1.30 | -0.08 | | 15 | | Ruby | 1.24 | 0.03 | +----------+--------+-------------------+---------+---------+
Načtení tabulky s hlavičkou se liší pouze v podržené části kódu:
package main import ( "log" "os" "github.com/olekukonko/tablewriter" ) func main() { table, err := tablewriter.NewCSV(os.Stdout, "tiobe.csv", true) if err != nil { log.Fatal(err) } table.Render() }
Nyní je již výsledek zcela korektní:
+----------+--------+-------------------+---------+---------+ | SEP 2019 | CHANGE | LANGUAGE | RATINGS | CHANGEP | +----------+--------+-------------------+---------+---------+ | 2 | change | C | 15.95 | 0.74 | | 1 | change | Java | 13.48 | -3.18 | | 3 | | Python | 10.47 | 0.59 | | 4 | | C++ | 7.11 | 1.48 | | 5 | | C# | 4.58 | 1.18 | | 6 | | Visual Basic | 4.12 | 0.83 | | 7 | | JavaScript | 2.54 | 0.41 | | 9 | change | PHP | 2.49 | 0.62 | | 19 | change | R | 2.37 | 1.33 | | 8 | change | SQL | 1.76 | -0.19 | | 14 | change | Go | 1.46 | 0.24 | | 16 | change | Swift | 1.38 | 0.28 | | 20 | change | Perl | 1.30 | 0.26 | | 12 | change | Assembly language | 1.30 | -0.08 | | 15 | | Ruby | 1.24 | 0.03 | +----------+--------+-------------------+---------+---------+
3. Nastavení zarovnání hodnot ve sloupcích
Z výsledku vytištěného příkladem z předchozí kapitoly je patrné, že textové hodnoty jsou implicitně zarovnány doleva a číselné hodnoty doprava. Ovšem zarovnání je možné v případě potřeby specifikovat explicitně – ovšem pro tabulku jako celek. To je ukázáno na dalším příkladu:
package main import ( "log" "os" "github.com/olekukonko/tablewriter" ) func main() { table, err := tablewriter.NewCSV(os.Stdout, "tiobe.csv", true) if err != nil { log.Fatal(err) } table.SetAlignment(tablewriter.ALIGN_LEFT) table.Render() }
S výsledkem, který sice odpovídá kódu, ale není tak přehledný, jako předchozí výsledek:
+----------+--------+-------------------+---------+---------+ | SEP 2019 | CHANGE | LANGUAGE | RATINGS | CHANGEP | +----------+--------+-------------------+---------+---------+ | 2 | change | C | 15.95 | 0.74 | | 1 | change | Java | 13.48 | -3.18 | | 3 | | Python | 10.47 | 0.59 | | 4 | | C++ | 7.11 | 1.48 | | 5 | | C# | 4.58 | 1.18 | | 6 | | Visual Basic | 4.12 | 0.83 | | 7 | | JavaScript | 2.54 | 0.41 | | 9 | change | PHP | 2.49 | 0.62 | | 19 | change | R | 2.37 | 1.33 | | 8 | change | SQL | 1.76 | -0.19 | | 14 | change | Go | 1.46 | 0.24 | | 16 | change | Swift | 1.38 | 0.28 | | 20 | change | Perl | 1.30 | 0.26 | | 12 | change | Assembly language | 1.30 | -0.08 | | 15 | | Ruby | 1.24 | 0.03 | +----------+--------+-------------------+---------+---------+
Zarovnání doprava:
package main import ( "log" "os" "github.com/olekukonko/tablewriter" ) func main() { table, err := tablewriter.NewCSV(os.Stdout, "tiobe.csv", true) if err != nil { log.Fatal(err) } table.SetAlignment(tablewriter.ALIGN_RIGHT) table.Render() }
S výsledkem:
+----------+--------+-------------------+---------+---------+ | SEP 2019 | CHANGE | LANGUAGE | RATINGS | CHANGEP | +----------+--------+-------------------+---------+---------+ | 2 | change | C | 15.95 | 0.74 | | 1 | change | Java | 13.48 | -3.18 | | 3 | | Python | 10.47 | 0.59 | | 4 | | C++ | 7.11 | 1.48 | | 5 | | C# | 4.58 | 1.18 | | 6 | | Visual Basic | 4.12 | 0.83 | | 7 | | JavaScript | 2.54 | 0.41 | | 9 | change | PHP | 2.49 | 0.62 | | 19 | change | R | 2.37 | 1.33 | | 8 | change | SQL | 1.76 | -0.19 | | 14 | change | Go | 1.46 | 0.24 | | 16 | change | Swift | 1.38 | 0.28 | | 20 | change | Perl | 1.30 | 0.26 | | 12 | change | Assembly language | 1.30 | -0.08 | | 15 | | Ruby | 1.24 | 0.03 | +----------+--------+-------------------+---------+---------+
4. Tabulka vložitelná do souboru ve formátu Markdown
Často se setkáme s požadavkem na vytvoření tabulky ve formátech podporovaných dalšími různými nástroji. Některé často používané formáty tabulek jsou uvedeny v osmnácté kapitole. Zde si ukážeme, jak lze specifikací okrajů i způsobů zobrazení oddělovačů na rozích buněk vytvořit tabulku ve formátu, který je kompatibilní s některými realizacemi Markdownu (i když samotný Markdown tabulky oficiálně nepodporuje, některá jeho rozšíření ano):
package main import ( "log" "os" "github.com/olekukonko/tablewriter" ) func main() { table, err := tablewriter.NewCSV(os.Stdout, "tiobe.csv", true) if err != nil { log.Fatal(err) } table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) table.SetCenterSeparator("|") table.Render() }
V příkladu bylo specifikováno, které okraje se mají zobrazit. Dále jsme uvedli znak použitý v místě, kde se střetávají rohy buněk (což může být zobrazeno odlišně od samotných okrajů):
| SEP 2019 | CHANGE | LANGUAGE | RATINGS | CHANGEP | |----------|--------|-------------------|---------|---------| | 2 | change | C | 15.95 | 0.74 | | 1 | change | Java | 13.48 | -3.18 | | 3 | | Python | 10.47 | 0.59 | | 4 | | C++ | 7.11 | 1.48 | | 5 | | C# | 4.58 | 1.18 | | 6 | | Visual Basic | 4.12 | 0.83 | | 7 | | JavaScript | 2.54 | 0.41 | | 9 | change | PHP | 2.49 | 0.62 | | 19 | change | R | 2.37 | 1.33 | | 8 | change | SQL | 1.76 | -0.19 | | 14 | change | Go | 1.46 | 0.24 | | 16 | change | Swift | 1.38 | 0.28 | | 20 | change | Perl | 1.30 | 0.26 | | 12 | change | Assembly language | 1.30 | -0.08 | | 15 | | Ruby | 1.24 | 0.03 |
Odlišné nastavení:
package main import ( "log" "os" "github.com/olekukonko/tablewriter" ) func main() { table, err := tablewriter.NewCSV(os.Stdout, "tiobe.csv", true) if err != nil { log.Fatal(err) } table.SetBorders(tablewriter.Border{Left: false, Top: true, Right: false, Bottom: true}) table.SetCenterSeparator("*") table.Render() }
S výsledkem:
-----------*--------*-------------------*---------*---------- SEP 2019 | CHANGE | LANGUAGE | RATINGS | CHANGEP -----------*--------*-------------------*---------*---------- 2 | change | C | 15.95 | 0.74 1 | change | Java | 13.48 | -3.18 3 | | Python | 10.47 | 0.59 4 | | C++ | 7.11 | 1.48 5 | | C# | 4.58 | 1.18 6 | | Visual Basic | 4.12 | 0.83 7 | | JavaScript | 2.54 | 0.41 9 | change | PHP | 2.49 | 0.62 19 | change | R | 2.37 | 1.33 8 | change | SQL | 1.76 | -0.19 14 | change | Go | 1.46 | 0.24 16 | change | Swift | 1.38 | 0.28 20 | change | Perl | 1.30 | 0.26 12 | change | Assembly language | 1.30 | -0.08 15 | | Ruby | 1.24 | 0.03 -----------*--------*-------------------*---------*----------
5. Horizontální oddělovače mezi řádky tabulky
V případě, že je tabulka krátká, popř. se používá terminál s volným místem ve vertikálním směru (ovšem tohoto místa je vždy málo), je možné mezi jednotlivé řádky tabulky vložit horizontální oddělovače. Ty se zapnou metodou SetRowLine tak, jak je to ukázáno v dalším demonstračním příkladu:
package main import ( "log" "os" "github.com/olekukonko/tablewriter" ) func main() { table, err := tablewriter.NewCSV(os.Stdout, "tiobe.csv", true) if err != nil { log.Fatal(err) } table.SetRowLine(true) table.Render() }
Výsledkem je tabulka se stejnými údaji, jako je tomu v předchozích příkladech, ovšem zabírající prakticky dvojnásobnou plochu:
+----------+--------+-------------------+---------+---------+ | SEP 2019 | CHANGE | LANGUAGE | RATINGS | CHANGEP | +----------+--------+-------------------+---------+---------+ | 2 | change | C | 15.95 | 0.74 | +----------+--------+-------------------+---------+---------+ | 1 | change | Java | 13.48 | -3.18 | +----------+--------+-------------------+---------+---------+ | 3 | | Python | 10.47 | 0.59 | +----------+--------+-------------------+---------+---------+ | 4 | | C++ | 7.11 | 1.48 | +----------+--------+-------------------+---------+---------+ | 5 | | C# | 4.58 | 1.18 | +----------+--------+-------------------+---------+---------+ | 6 | | Visual Basic | 4.12 | 0.83 | +----------+--------+-------------------+---------+---------+ | 7 | | JavaScript | 2.54 | 0.41 | +----------+--------+-------------------+---------+---------+ | 9 | change | PHP | 2.49 | 0.62 | +----------+--------+-------------------+---------+---------+ | 19 | change | R | 2.37 | 1.33 | +----------+--------+-------------------+---------+---------+ | 8 | change | SQL | 1.76 | -0.19 | +----------+--------+-------------------+---------+---------+ | 14 | change | Go | 1.46 | 0.24 | +----------+--------+-------------------+---------+---------+ | 16 | change | Swift | 1.38 | 0.28 | +----------+--------+-------------------+---------+---------+ | 20 | change | Perl | 1.30 | 0.26 | +----------+--------+-------------------+---------+---------+ | 12 | change | Assembly language | 1.30 | -0.08 | +----------+--------+-------------------+---------+---------+ | 15 | | Ruby | 1.24 | 0.03 | +----------+--------+-------------------+---------+---------+
6. Automatické spojení buněk se shodným obsahem
Sousední buňky se shodným obsahem, což je ostatně poměrně častý případ, se mohou automaticky spojit. Pro tento účel se používá metoda pojmenovaná SetAutoMergeCells tak, jak je to ukázáno v tomto příkladu:
package main import ( "log" "os" "github.com/olekukonko/tablewriter" ) func main() { table, err := tablewriter.NewCSV(os.Stdout, "tiobe.csv", true) if err != nil { log.Fatal(err) } table.SetAutoMergeCells(true) table.SetRowLine(true) table.Render() }
Výsledkem je tato tabulka:
+----------+--------+-------------------+---------+---------+ | SEP 2019 | CHANGE | LANGUAGE | RATINGS | CHANGEP | +----------+--------+-------------------+---------+---------+ | 2 | change | C | 15.95 | 0.74 | +----------+ +-------------------+---------+---------+ | 1 | | Java | 13.48 | -3.18 | +----------+--------+-------------------+---------+---------+ | 3 | | Python | 10.47 | 0.59 | +----------+--------+-------------------+---------+---------+ | 4 | | C++ | 7.11 | 1.48 | +----------+--------+-------------------+---------+---------+ | 5 | | C# | 4.58 | 1.18 | +----------+--------+-------------------+---------+---------+ | 6 | | Visual Basic | 4.12 | 0.83 | +----------+--------+-------------------+---------+---------+ | 7 | | JavaScript | 2.54 | 0.41 | +----------+--------+-------------------+---------+---------+ | 9 | change | PHP | 2.49 | 0.62 | +----------+ +-------------------+---------+---------+ | 19 | | R | 2.37 | 1.33 | +----------+ +-------------------+---------+---------+ | 8 | | SQL | 1.76 | -0.19 | +----------+ +-------------------+---------+---------+ | 14 | | Go | 1.46 | 0.24 | +----------+ +-------------------+---------+---------+ | 16 | | Swift | 1.38 | 0.28 | +----------+ +-------------------+---------+---------+ | 20 | | Perl | 1.30 | 0.26 | +----------+ +-------------------+ +---------+ | 12 | | Assembly language | | -0.08 | +----------+--------+-------------------+---------+---------+ | 15 | | Ruby | 1.24 | 0.03 | +----------+--------+-------------------+---------+---------+
7. Specifikace sloupců, ve kterých má ke spojení buněk dojít
Automatické spojování sousedních buněk se shodným obsahem je možné omezit pouze na vybrané sloupce. K tomuto účelu slouží metoda pojmenovaná SetAutoMergeCellsByColumnIndex, které se předává pole, resp. řez s indexy sloupců, jichž se má spojování týkat. Jak je v programovacím jazyce Go zvykem, jsou sloupce číslovány od jedničky (na rozdíl od tabulkových procesorů):
package main import ( "fmt" "log" "os" "github.com/olekukonko/tablewriter" ) func main() { table, err := tablewriter.NewCSV(os.Stdout, "tiobe.csv", true) if err != nil { log.Fatal(err) } table.SetRowLine(true) table.SetAutoMergeCellsByColumnIndex([]int{1, 2}) table.Render() fmt.Println() fmt.Println() table.SetAutoMergeCellsByColumnIndex([]int{3}) table.Render() }
Výše uvedený demonstrační příklad po svém spuštění zobrazí dvojici tabulek, pokaždé s jinými buňkami, které jsou sloučeny:
+----------+--------+-------------------+---------+---------+ | SEP 2019 | CHANGE | LANGUAGE | RATINGS | CHANGEP | +----------+--------+-------------------+---------+---------+ | 2 | change | C | 15.95 | 0.74 | +----------+ +-------------------+---------+---------+ | 1 | | Java | 13.48 | -3.18 | +----------+--------+-------------------+---------+---------+ | 3 | | Python | 10.47 | 0.59 | +----------+--------+-------------------+---------+---------+ | 4 | | C++ | 7.11 | 1.48 | +----------+--------+-------------------+---------+---------+ | 5 | | C# | 4.58 | 1.18 | +----------+--------+-------------------+---------+---------+ | 6 | | Visual Basic | 4.12 | 0.83 | +----------+--------+-------------------+---------+---------+ | 7 | | JavaScript | 2.54 | 0.41 | +----------+--------+-------------------+---------+---------+ | 9 | change | PHP | 2.49 | 0.62 | +----------+ +-------------------+---------+---------+ | 19 | | R | 2.37 | 1.33 | +----------+ +-------------------+---------+---------+ | 8 | | SQL | 1.76 | -0.19 | +----------+ +-------------------+---------+---------+ | 14 | | Go | 1.46 | 0.24 | +----------+ +-------------------+---------+---------+ | 16 | | Swift | 1.38 | 0.28 | +----------+ +-------------------+---------+---------+ | 20 | | Perl | 1.30 | 0.26 | +----------+ +-------------------+---------+---------+ | 12 | | Assembly language | 1.30 | -0.08 | +----------+--------+-------------------+---------+---------+ | 15 | | Ruby | 1.24 | 0.03 | +----------+--------+-------------------+---------+---------+ +----------+--------+-------------------+---------+---------+ | SEP 2019 | CHANGE | LANGUAGE | RATINGS | CHANGEP | +----------+--------+-------------------+---------+---------+ | 2 | change | C | 15.95 | 0.74 | +----------+--------+-------------------+---------+---------+ | 1 | change | Java | 13.48 | -3.18 | +----------+--------+-------------------+---------+---------+ | 3 | | Python | 10.47 | 0.59 | +----------+--------+-------------------+---------+---------+ | 4 | | C++ | 7.11 | 1.48 | +----------+--------+-------------------+---------+---------+ | 5 | | C# | 4.58 | 1.18 | +----------+--------+-------------------+---------+---------+ | 6 | | Visual Basic | 4.12 | 0.83 | +----------+--------+-------------------+---------+---------+ | 7 | | JavaScript | 2.54 | 0.41 | +----------+--------+-------------------+---------+---------+ | 9 | change | PHP | 2.49 | 0.62 | +----------+--------+-------------------+---------+---------+ | 19 | change | R | 2.37 | 1.33 | +----------+--------+-------------------+---------+---------+ | 8 | change | SQL | 1.76 | -0.19 | +----------+--------+-------------------+---------+---------+ | 14 | change | Go | 1.46 | 0.24 | +----------+--------+-------------------+---------+---------+ | 16 | change | Swift | 1.38 | 0.28 | +----------+--------+-------------------+---------+---------+ | 20 | change | Perl | 1.30 | 0.26 | +----------+--------+-------------------+ +---------+ | 12 | change | Assembly language | | -0.08 | +----------+--------+-------------------+---------+---------+ | 15 | | Ruby | 1.24 | 0.03 | +----------+--------+-------------------+---------+---------+
8. Získání řetězce reprezentujícího celou vykreslenou tabulku
Podívejme se nyní na další potenciálně užitečnou vlastnost knihovny tablewriter. Relativně snadno totiž můžeme získat řetězec s obsahem celé vykreslené tabulky. Jinými slovy – tabulku není nutné pouze vytisknout, ale získat lze i její podobu. Toto chování, které je zajištěno díky tomu, že je knihovna postavena na rozhraní io.Writer, je možné využít v testech atd.:
package main import ( "fmt" "log" "strings" "github.com/olekukonko/tablewriter" ) func main() { asString := &strings.Builder{} table, err := tablewriter.NewCSV(asString, "tiobe.csv", true) if err != nil { log.Fatal(err) } table.SetRowLine(true) table.SetAutoMergeCellsByColumnIndex([]int{1, 2}) table.Render() fmt.Println(asString.String()) }
Tento demonstrační příklad nejdříve získá celou textovou podobu tabulky, kterou může dále zpracovat. V tomto jednoduchém případě jí vytiskne na standardní výstup:
+----------+--------+-------------------+---------+---------+ | SEP 2019 | CHANGE | LANGUAGE | RATINGS | CHANGEP | +----------+--------+-------------------+---------+---------+ | 2 | change | C | 15.95 | 0.74 | +----------+ +-------------------+---------+---------+ | 1 | | Java | 13.48 | -3.18 | +----------+--------+-------------------+---------+---------+ | 3 | | Python | 10.47 | 0.59 | +----------+--------+-------------------+---------+---------+ | 4 | | C++ | 7.11 | 1.48 | +----------+--------+-------------------+---------+---------+ | 5 | | C# | 4.58 | 1.18 | +----------+--------+-------------------+---------+---------+ | 6 | | Visual Basic | 4.12 | 0.83 | +----------+--------+-------------------+---------+---------+ | 7 | | JavaScript | 2.54 | 0.41 | +----------+--------+-------------------+---------+---------+ | 9 | change | PHP | 2.49 | 0.62 | +----------+ +-------------------+---------+---------+ | 19 | | R | 2.37 | 1.33 | +----------+ +-------------------+---------+---------+ | 8 | | SQL | 1.76 | -0.19 | +----------+ +-------------------+---------+---------+ | 14 | | Go | 1.46 | 0.24 | +----------+ +-------------------+---------+---------+ | 16 | | Swift | 1.38 | 0.28 | +----------+ +-------------------+---------+---------+ | 20 | | Perl | 1.30 | 0.26 | +----------+ +-------------------+---------+---------+ | 12 | | Assembly language | 1.30 | -0.08 | +----------+--------+-------------------+---------+---------+ | 15 | | Ruby | 1.24 | 0.03 | +----------+--------+-------------------+---------+---------+
9. Barevný výstup
Poslední vlastností knihovny tablewriter, o níž se v dnešním článku zmíníme, je podpora pro barevný výstup, resp. přesněji řečeno pro obarvení vybraných částí tabulky. V prvním příkladu s barevným výstupem obarvíme jednotlivé nadpisy sloupců – u každého sloupce může být definována barva popředí, barva pozadí a styl vykreslení (typicky tučné písmo). Konkrétní způsob zobrazení je ovšem do značné míry závislý na nastavení terminálu:
package main import ( "log" "os" "github.com/olekukonko/tablewriter" ) func main() { table, err := tablewriter.NewCSV(os.Stdout, "tiobe.csv", true) if err != nil { log.Fatal(err) } table.SetBorder(false) table.SetHeaderColor( tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor}, tablewriter.Colors{tablewriter.FgHiRedColor, tablewriter.Bold, tablewriter.BgBlackColor}, tablewriter.Colors{tablewriter.BgRedColor, tablewriter.FgWhiteColor}, tablewriter.Colors{tablewriter.BgCyanColor, tablewriter.FgWhiteColor}, tablewriter.Colors{tablewriter.Bold, tablewriter.BgWhiteColor}) table.Render() }
Výsledek:
Obrázek 1: Tabulka s obarvenými nadpisy sloupců.
Ve druhém příkladu obarvíme i vybrané sloupce:
package main import ( "log" "os" "github.com/olekukonko/tablewriter" ) func main() { table, err := tablewriter.NewCSV(os.Stdout, "tiobe.csv", true) if err != nil { log.Fatal(err) } table.SetBorder(false) table.SetHeaderColor( tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor}, tablewriter.Colors{tablewriter.FgHiRedColor, tablewriter.Bold, tablewriter.BgBlackColor}, tablewriter.Colors{tablewriter.BgRedColor, tablewriter.FgBlackColor}, tablewriter.Colors{tablewriter.BgCyanColor, tablewriter.FgYellowColor}, tablewriter.Colors{tablewriter.Bold, tablewriter.BgWhiteColor}) table.SetColumnColor( tablewriter.Colors{tablewriter.FgHiBlackColor}, tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiRedColor}, tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiGreenColor}, tablewriter.Colors{tablewriter.FgBlackColor}, tablewriter.Colors{tablewriter.Bold, tablewriter.BgWhiteColor}) table.Render() }
Výsledek:
Obrázek 2: Tabulka s obarvenými nadpisy sloupců i jednotlivými sloupci.
10. Nepracuje se pouze s tabulkami: pokročilá knihovna go-pretty
Vývojářům, kteří pracují s jazykem Go, je k dispozici ještě jedna velmi užitečná knihovna, kterou je možné použít pro vykreslení obsahu různých datových struktur, samozřejmě včetně tabulek. Tato knihovna se jmenuje go-pretty a dnes si ukážeme, jaké možnosti nám nabízí právě při vykreslování tabulek. Instalaci této knihovny můžeme provést s využitím modulů jazyka Go: postačuje vytvořit nový projekt a upravit jeho projektový soubor do podoby:
module go-pretty-test go 1.14 require ( github.com/jedib0t/go-pretty/v6 v6.1.0 )
Při prvním pokusu o překlad se stáhnou i další potřebné knihovny:
go: downloading github.com/jedib0t/go-pretty v4.3.0+incompatible go: downloading github.com/jedib0t/go-pretty/v6 v6.1.0 go: extracting github.com/jedib0t/go-pretty/v6 v6.1.0 go: extracting github.com/jedib0t/go-pretty v4.3.0+incompatible
A dojde ke zpětné úpravě projektového souboru:
module go-pretty-test go 1.14 require ( github.com/go-openapi/strfmt v0.20.0 // indirect github.com/jedib0t/go-pretty v4.3.0+incompatible github.com/jedib0t/go-pretty/v6 v6.1.0 )
Od této chvíle je možné knihovnu importovat i do dalších projektů.
11. Zobrazení jednoduché tabulky knihovnou go-pretty
Podobně, jako tomu bylo u předchozích třech popisovaných knihoven, si nejdříve ukážeme, jak jsou vlastně zobrazeny jednoduché tabulky. Používá se podobný postup, jaký byl využit i v předchozí knihovně:
- Je zkonstruován objekt představující tabulku, a to konstruktorem NewWriter
- Nastaví se objekt použitý pro vykreslení, v našem případě os.Stdout
- Jednotlivé řádky tabulky se připojí metodou AppendRow
- Celá tabulka je vykreslena metodou Render
Důležité je, že řádek tabulky je představován datovým typem table.Row, což ale není nic jiného než řez objektů vyhovujících rozhraní interface{}, tedy jinými slovy jakýchkoli objektů:
package main import ( "os" "github.com/jedib0t/go-pretty/table" ) // Role represents user role in some IS type Role struct { name string surname string popularity int } func main() { roles := []Role{ Role{"Eliška", "Najbrtová", 4}, Role{"Jenny", "Suk", 3}, Role{"Anička", "Šafářová", 1}, Role{"Sváťa", "Pulec", 3}, Role{"Blažej", "Motyčka", 8}, Role{"Eda", "Wasserfall", 3}, Role{"Přemysl", "Hájek", 10}, } t := table.NewWriter() t.SetOutputMirror(os.Stdout) t.AppendHeader(table.Row{"#", "First Name", "Last Name", "Popularity"}) for i, role := range roles { t.AppendRow(table.Row{i, role.name, role.surname, role.popularity}) } t.Render() }
Výsledkem spuštění předchozího příkladu by měla být tato tabulka:
+---+------------+------------+------------+ | # | FIRST NAME | LAST NAME | POPULARITY | +---+------------+------------+------------+ | 0 | Eliška | Najbrtová | 4 | | 1 | Jenny | Suk | 3 | | 2 | Anička | Šafářová | 1 | | 3 | Sváťa | Pulec | 3 | | 4 | Blažej | Motyčka | 8 | | 5 | Eda | Wasserfall | 3 | | 6 | Přemysl | Hájek | 10 | +---+------------+------------+------------+
12. Patička tabulky
Do tabulky je možné (což opět není nic unikátního) přidat patičku, a to konkrétně metodou nazvanou AppendFooter. Této metodě se předává hodnota stejného typu, jako metodám AppendHeader a AppendRow – typ table.Row, což je řez hodnotami splňujícími rozhraní interface{}:
package main import ( "os" "github.com/jedib0t/go-pretty/table" ) // Role represents user role in some IS type Role struct { name string surname string popularity int } func main() { roles := []Role{ Role{"Eliška", "Najbrtová", 4}, Role{"Jenny", "Suk", 3}, Role{"Anička", "Šafářová", 1}, Role{"Sváťa", "Pulec", 3}, Role{"Blažej", "Motyčka", 8}, Role{"Eda", "Wasserfall", 3}, Role{"Přemysl", "Hájek", 10}, } t := table.NewWriter() t.SetOutputMirror(os.Stdout) t.AppendHeader(table.Row{"#", "First Name", "Last Name", "Popularity"}) totalPopularity := 0 for i, role := range roles { t.AppendRow(table.Row{i, role.name, role.surname, role.popularity}) totalPopularity += role.popularity } t.AppendFooter(table.Row{"", "", "Total", totalPopularity}) t.Render() }
Výsledná tabulka bude obsahovat patičku se součtem popularit jednotlivých postav z jedné známé divadelní hry:
+---+------------+------------+------------+ | # | FIRST NAME | LAST NAME | POPULARITY | +---+------------+------------+------------+ | 0 | Eliška | Najbrtová | 4 | | 1 | Jenny | Suk | 3 | | 2 | Anička | Šafářová | 1 | | 3 | Sváťa | Pulec | 3 | | 4 | Blažej | Motyčka | 8 | | 5 | Eda | Wasserfall | 3 | | 6 | Přemysl | Hájek | 10 | +---+------------+------------+------------+ | | | TOTAL | 32 | +---+------------+------------+------------+
13. Styl vykreslení tabulek
Jednou z mnoha předností knihovny go-pretty je existence již předpřipravených stylů aplikovaných při vykreslení tabulek. Styly určují například způsob zobrazení okrajů tabulky, barvu sloupců či nadpisů sloupců atd. Nejprve si ukažme způsob aplikace stylu, který ovlivňuje pouze okraje tabulky a nikoli barvu vykreslení. Styl se vybírá metodou nazvanou SetStyle:
package main import ( "os" "github.com/jedib0t/go-pretty/table" ) // Role represents user role in some IS type Role struct { name string surname string popularity int } func main() { roles := []Role{ Role{"Eliška", "Najbrtová", 4}, Role{"Jenny", "Suk", 3}, Role{"Anička", "Šafářová", 1}, Role{"Sváťa", "Pulec", 3}, Role{"Blažej", "Motyčka", 8}, Role{"Eda", "Wasserfall", 3}, Role{"Přemysl", "Hájek", 10}, } t := table.NewWriter() t.SetOutputMirror(os.Stdout) t.SetStyle(table.StyleLight) t.AppendHeader(table.Row{"#", "First Name", "Last Name", "Popularity"}) totalPopularity := 0 for i, role := range roles { t.AppendRow(table.Row{i, role.name, role.surname, role.popularity}) totalPopularity += role.popularity } t.AppendFooter(table.Row{"", "", "Total", totalPopularity}) t.Render() }
Výsledkem běhu tohoto příkladu by měla být následující tabulka (založená na speciálních Unicode znacích, což vyžaduje použití vhodného fontu):
┌───┬────────────┬────────────┬────────────┐ │ # │ FIRST NAME │ LAST NAME │ POPULARITY │ ├───┼────────────┼────────────┼────────────┤ │ 0 │ Eliška │ Najbrtová │ 4 │ │ 1 │ Jenny │ Suk │ 3 │ │ 2 │ Anička │ Šafářová │ 1 │ │ 3 │ Sváťa │ Pulec │ 3 │ │ 4 │ Blažej │ Motyčka │ 8 │ │ 5 │ Eda │ Wasserfall │ 3 │ │ 6 │ Přemysl │ Hájek │ 10 │ ├───┼────────────┼────────────┼────────────┤ │ │ │ TOTAL │ 32 │ └───┴────────────┴────────────┴────────────┘
14. Ostatní styly okrajů tabulek
Kromě stylu zmíněného v předchozí kapitole existují další tři předpřipravené styly okrajů tabulky, resp. okrajů mezi jejími jednotlivými buňkami:
- table.StyleBold
- table.StyleDouble
- table.StyleRounded
Všechny tři zmíněné styly jsou použity v dalším demonstračním příkladu, jehož úplný zdrojový kód vypadá následovně:
package main import ( "os" "github.com/jedib0t/go-pretty/table" ) // Role represents user role in some IS type Role struct { name string surname string popularity int } func main() { roles := []Role{ Role{"Eliška", "Najbrtová", 4}, Role{"Jenny", "Suk", 3}, Role{"Anička", "Šafářová", 1}, Role{"Sváťa", "Pulec", 3}, Role{"Blažej", "Motyčka", 8}, Role{"Eda", "Wasserfall", 3}, Role{"Přemysl", "Hájek", 10}, } t := table.NewWriter() t.SetOutputMirror(os.Stdout) t.AppendHeader(table.Row{"#", "First Name", "Last Name", "Popularity"}) totalPopularity := 0 for i, role := range roles { t.AppendRow(table.Row{i, role.name, role.surname, role.popularity}) totalPopularity += role.popularity } t.AppendFooter(table.Row{"", "", "Total", totalPopularity}) t.SetStyle(table.StyleBold) t.Render() t.SetStyle(table.StyleDouble) t.Render() t.SetStyle(table.StyleRounded) t.Render() }
Opět je patrné, že tyto styly jsou založeny na použití specializovaných Unicode znaků a vyžadují tedy vhodný font:
┏━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┓ ┃ # ┃ FIRST NAME ┃ LAST NAME ┃ POPULARITY ┃ ┣━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━┫ ┃ 0 ┃ Eliška ┃ Najbrtová ┃ 4 ┃ ┃ 1 ┃ Jenny ┃ Suk ┃ 3 ┃ ┃ 2 ┃ Anička ┃ Šafářová ┃ 1 ┃ ┃ 3 ┃ Sváťa ┃ Pulec ┃ 3 ┃ ┃ 4 ┃ Blažej ┃ Motyčka ┃ 8 ┃ ┃ 5 ┃ Eda ┃ Wasserfall ┃ 3 ┃ ┃ 6 ┃ Přemysl ┃ Hájek ┃ 10 ┃ ┣━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━╋━━━━━━━━━━━━┫ ┃ ┃ ┃ TOTAL ┃ 32 ┃ ┗━━━┻━━━━━━━━━━━━┻━━━━━━━━━━━━┻━━━━━━━━━━━━┛ ╔═══╦════════════╦════════════╦════════════╗ ║ # ║ FIRST NAME ║ LAST NAME ║ POPULARITY ║ ╠═══╬════════════╬════════════╬════════════╣ ║ 0 ║ Eliška ║ Najbrtová ║ 4 ║ ║ 1 ║ Jenny ║ Suk ║ 3 ║ ║ 2 ║ Anička ║ Šafářová ║ 1 ║ ║ 3 ║ Sváťa ║ Pulec ║ 3 ║ ║ 4 ║ Blažej ║ Motyčka ║ 8 ║ ║ 5 ║ Eda ║ Wasserfall ║ 3 ║ ║ 6 ║ Přemysl ║ Hájek ║ 10 ║ ╠═══╬════════════╬════════════╬════════════╣ ║ ║ ║ TOTAL ║ 32 ║ ╚═══╩════════════╩════════════╩════════════╝ ╭───┬────────────┬────────────┬────────────╮ │ # │ FIRST NAME │ LAST NAME │ POPULARITY │ ├───┼────────────┼────────────┼────────────┤ │ 0 │ Eliška │ Najbrtová │ 4 │ │ 1 │ Jenny │ Suk │ 3 │ │ 2 │ Anička │ Šafářová │ 1 │ │ 3 │ Sváťa │ Pulec │ 3 │ │ 4 │ Blažej │ Motyčka │ 8 │ │ 5 │ Eda │ Wasserfall │ 3 │ │ 6 │ Přemysl │ Hájek │ 10 │ ├───┼────────────┼────────────┼────────────┤ │ │ │ TOTAL │ 32 │ ╰───┴────────────┴────────────┴────────────╯
15. Styly se změnou barvy tabulky či její části
Mnohem více předpřipravených stylů definuje mj. i barvy jednotlivých řádků tabulky, nadpisů sloupců atd. Jeden z těchto stylů se jmenuje table.StyleColoredBright. Ukažme si nyní způsob jeho použití:
package main import ( "os" "github.com/jedib0t/go-pretty/table" ) // Role represents user role in some IS type Role struct { name string surname string popularity int } func main() { roles := []Role{ Role{"Eliška", "Najbrtová", 4}, Role{"Jenny", "Suk", 3}, Role{"Anička", "Šafářová", 1}, Role{"Sváťa", "Pulec", 3}, Role{"Blažej", "Motyčka", 8}, Role{"Eda", "Wasserfall", 3}, Role{"Přemysl", "Hájek", 10}, } t := table.NewWriter() t.SetOutputMirror(os.Stdout) t.SetStyle(table.StyleColoredBright) t.AppendHeader(table.Row{"#", "First Name", "Last Name", "Popularity"}) totalPopularity := 0 for i, role := range roles { t.AppendRow(table.Row{i, role.name, role.surname, role.popularity}) totalPopularity += role.popularity } t.AppendFooter(table.Row{"", "", "Total", totalPopularity}) t.Render() }
Výsledkem by měla (resp. mohla být) tato tabulka:
Obrázek 3: Tabulka se stylem StyleColoredBright.
16. Ostatní připravené barevné styly
Standardních barvových stylů (či témat) existuje v knihovně go-pretty větší množství:
- table.StyleColoredBright
- table.StyleColoredDark
- table.StyleColoredBlackOnBlueWhite
- table.StyleColoredBlackOnCyanWhite
- table.StyleColoredBlackOnGreenWhite
- table.StyleColoredBlackOnMagentaWhite
- table.StyleColoredBlackOnYellowWhite
- table.StyleColoredBlackOnRedWhite
- table.StyleColoredBlueWhiteOnBlack
- table.StyleColoredCyanWhiteOnBlack
- table.StyleColoredGreenWhiteOnBlack
- table.StyleColoredMagentaWhiteOnBlack
- table.StyleColoredRedWhiteOnBlack
- table.StyleColoredYellowWhiteOnBlack
Následující příklad zobrazí tabulky ve všech možných standardních barevných kombinacích:
package main import ( "fmt" "os" "github.com/jedib0t/go-pretty/table" ) // Role represents user role in some IS type Role struct { name string surname string popularity int } func main() { roles := []Role{ Role{"Eliška", "Najbrtová", 4}, Role{"Jenny", "Suk", 3}, Role{"Anička", "Šafářová", 1}, Role{"Sváťa", "Pulec", 3}, Role{"Blažej", "Motyčka", 8}, Role{"Eda", "Wasserfall", 3}, Role{"Přemysl", "Hájek", 10}, } t := table.NewWriter() t.SetOutputMirror(os.Stdout) t.AppendHeader(table.Row{"#", "First Name", "Last Name", "Popularity"}) totalPopularity := 0 for i, role := range roles { t.AppendRow(table.Row{i, role.name, role.surname, role.popularity}) totalPopularity += role.popularity } t.AppendFooter(table.Row{"", "", "Total", totalPopularity}) styles := []table.Style{ table.StyleColoredBright, table.StyleColoredDark, table.StyleColoredBlackOnBlueWhite, table.StyleColoredBlackOnCyanWhite, table.StyleColoredBlackOnGreenWhite, table.StyleColoredBlackOnMagentaWhite, table.StyleColoredBlackOnYellowWhite, table.StyleColoredBlackOnRedWhite, table.StyleColoredBlueWhiteOnBlack, table.StyleColoredCyanWhiteOnBlack, table.StyleColoredGreenWhiteOnBlack, table.StyleColoredMagentaWhiteOnBlack, table.StyleColoredRedWhiteOnBlack, table.StyleColoredYellowWhiteOnBlack, } for _, style := range styles { fmt.Println(style.Name) t.SetStyle(style) t.Render() fmt.Println() fmt.Println() } }
Výsledky:
Obrázek 4: Barvová témata tabulek.
Obrázek 5: Barvová témata tabulek.
Obrázek 6: Barvová témata tabulek.
Obrázek 7: Barvová témata tabulek.
17. Obsah následující části seriálu
V navazující části seriálu o programovacím jazyku Go i o knihovnách a nástrojích, které pro tento jazyk existují, dokončíme popis možností nabízených knihovnou go-pretty. Ukážeme si především způsob vykreslení dalších datových struktur podporovaných touto knihovnou.
18. Příloha: často používané formáty tabulek vykreslených neproporcionálním písmem
Tabulky zapisované v čistých textových souborech (plain ASCII, plain text) se v praxi používají poměrně často, a to už minimálně několik desetiletí (ve skutečnosti ovšem mnohem déle, neboť se jednalo o standardní formát tiskových sestav jak na mainframech, tak i na minipočítačích). V této příloze jsou uvedeny tři formáty, které se ve své oblasti staly de-facto standardy a existují nástroje, které takové tabulky dokážou rozpoznat a korektně zpracovat.
První formát tabulek je používán ve slavném režimu Org v textovém editoru Emacs. Ve skutečnosti tento formát podporují i další nástroje:
| Language | Sep 2020 | Sep 2019 | Change | Ratings | Changep | |-------------------+------------+------------+----------+-----------+-----------| | C | 1 | 2 | change | 15.95 | 0.74 | | Java | 2 | 1 | change | 13.48 | -3.18 | | Python | 3 | 3 | nan | 10.47 | 0.59 | | C++ | 4 | 4 | nan | 7.11 | 1.48 | | C# | 5 | 5 | nan | 4.58 | 1.18 | | Visual Basic | 6 | 6 | nan | 4.12 | 0.83 | | JavaScript | 7 | 7 | nan | 2.54 | 0.41 | | PHP | 8 | 9 | change | 2.49 | 0.62 | | R | 9 | 19 | change | 2.37 | 1.33 | | SQL | 10 | 8 | change | 1.76 | -0.19 | | Go | 11 | 14 | change | 1.46 | 0.24 | | Swift | 12 | 16 | change | 1.38 | 0.28 | | Perl | 13 | 20 | change | 1.3 | 0.26 | | Assembly language | 14 | 12 | change | 1.3 | -0.08 | | Ruby | 15 | 15 | nan | 1.24 | 0.03 | | MATLAB | 16 | 18 | change | 1.1 | 0.04 | | Groovy | 17 | 11 | change | 0.99 | -0.52 | | Rust | 18 | 33 | change | 0.92 | 0.55 | | Objective-C | 19 | 10 | change | 0.85 | -0.99 | | Dart | 20 | 24 | change | 0.77 | 0.13 |
Další formát je akceptován Jirou a podobnými nástroji:
|| Language || Sep 2020 || Sep 2019 || Change || Ratings || Changep || | C | 1 | 2 | change | 15.95 | 0.74 | | Java | 2 | 1 | change | 13.48 | -3.18 | | Python | 3 | 3 | nan | 10.47 | 0.59 | | C++ | 4 | 4 | nan | 7.11 | 1.48 | | C# | 5 | 5 | nan | 4.58 | 1.18 | | Visual Basic | 6 | 6 | nan | 4.12 | 0.83 | | JavaScript | 7 | 7 | nan | 2.54 | 0.41 | | PHP | 8 | 9 | change | 2.49 | 0.62 | | R | 9 | 19 | change | 2.37 | 1.33 | | SQL | 10 | 8 | change | 1.76 | -0.19 | | Go | 11 | 14 | change | 1.46 | 0.24 | | Swift | 12 | 16 | change | 1.38 | 0.28 | | Perl | 13 | 20 | change | 1.3 | 0.26 | | Assembly language | 14 | 12 | change | 1.3 | -0.08 | | Ruby | 15 | 15 | nan | 1.24 | 0.03 | | MATLAB | 16 | 18 | change | 1.1 | 0.04 | | Groovy | 17 | 11 | change | 0.99 | -0.52 | | Rust | 18 | 33 | change | 0.92 | 0.55 | | Objective-C | 19 | 10 | change | 0.85 | -0.99 | | Dart | 20 | 24 | change | 0.77 | 0.13 |
A konečně formát třetí je použít v Restructured Textu (rst):
================= ========== ========== ======== ========= ========= Language Sep 2020 Sep 2019 Change Ratings Changep ================= ========== ========== ======== ========= ========= C 1 2 change 15.95 0.74 Java 2 1 change 13.48 -3.18 Python 3 3 nan 10.47 0.59 C++ 4 4 nan 7.11 1.48 C# 5 5 nan 4.58 1.18 Visual Basic 6 6 nan 4.12 0.83 JavaScript 7 7 nan 2.54 0.41 PHP 8 9 change 2.49 0.62 R 9 19 change 2.37 1.33 SQL 10 8 change 1.76 -0.19 Go 11 14 change 1.46 0.24 Swift 12 16 change 1.38 0.28 Perl 13 20 change 1.3 0.26 Assembly language 14 12 change 1.3 -0.08 Ruby 15 15 nan 1.24 0.03 MATLAB 16 18 change 1.1 0.04 Groovy 17 11 change 0.99 -0.52 Rust 18 33 change 0.92 0.55 Objective-C 19 10 change 0.85 -0.99 Dart 20 24 change 0.77 0.13 ================= ========== ========== ======== ========= =========
19. Repositář s demonstračními příklady
Zdrojové kódy všech dnes použitých demonstračních příkladů byly uloženy do nového Git repositáře, který je dostupný na adrese https://github.com/tisnik/go-root (stále na GitHubu :-). V případě, že nebudete chtít klonovat celý repositář (ten je ovšem – alespoň prozatím – velmi malý, dnes má přibližně stovku kilobajtů), můžete namísto toho použít odkazy na jednotlivé demonstrační příklady, které naleznete v následující tabulce:
20. Odkazy na Internetu
- Standardní balíček text/tabwriter
https://golang.org/pkg/text/tabwriter/ - Elastic tabstops: A better way to indent and align code
https://nickgravgaard.com/elastic-tabstops/ - ASCII Table Writer
https://github.com/olekukonko/tablewriter - TablePrinter
https://github.com/lensesio/tableprinter - go-pretty
https://github.com/jedib0t/go-pretty - What are the drawbacks of elastic tabstops?
https://softwareengineering.stackexchange.com/questions/137290/what-are-the-drawbacks-of-elastic-tabstops - Elastic tabstop editors and plugins
https://stackoverflow.com/questions/28652/elastic-tabstop-editors-and-plugins - Příkaz gofmt
https://golang.org/cmd/gofmt/ - 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/ - Standardní balíček fmt
https://golang.org/pkg/fmt/ - Standardní balíček text/template
https://golang.org/pkg/text/template/ - Pretty print struct variables in Go (Golang)
https://golangbyexample.com/print-struct-variables-golang/ - Golang String Padding Example
https://golang.cafe/blog/golang-string-padding-example.html - Ultimate Golang String Formatting Cheat Sheet
https://medium.com/swlh/ultimate-golang-string-formatting-cheat-sheet-234ec92c97da - Box Drawing (znaky Unicode)
https://en.wikipedia.org/wiki/List_of_Unicode_characters#Box_Drawing - Box Drawing (Unicode block)
https://en.wikipedia.org/wiki/Box_Drawing_(Unicode_block) - Tables in Restructured Text
https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#tables - JIRA Tables
https://www.idalko.com/jira-tables/ - Základy použití režimu org-mode v Emacsu
https://www.root.cz/clanky/zaklady-pouziti-rezimu-org-mode-v-emacsu/