Hlavní navigace

Užitečné nástroje pro Go: automatické doplňování kódu, plnohodnotná smyčka REPL a integrace s Vimem

Pavel Tišnovský

Dnes se seznámíme s nástroji gocode a gopls, které umožňují provádět automatické doplňování kódu. Lze je využít jak ve Vimu (vim-gocode), tak i v plnohodnotné interaktivní smyčce REPL, které byla (kupodivu) vyvinuta i pro Go.

Doba čtení: 42 minut

Sdílet

11. Konfigurace klávesové zkratky pro vyvolání omni completion

12. Interaktivní smyčka REPL pro kompilovaný programovací jazyk Go?

13. Interaktivní smyčka REPL v různých jazycích a nástrojích

14. Projekt Gore

15. Instalace projektu Gore a spuštění interaktivní smyčky REPL

16. Speciální pseudopříkazy používané v REPL projektu Gore

17. Odkazy na Internetu

1. Užitečné nástroje pro Go: automatické doplňování kódu, plnohodnotná smyčka REPL a integrace s Vimem

V dnešním pokračování seriálu o programovacím jazyce Go se seznámíme s některými užitečnými nástroji, které mohou dobře posloužit především vývojářům při tvorbě a úpravách zdrojových kódů psaných v Go. V úvodní části článku se budeme věnovat především nástroji pojmenovaném gocode, který umožňuje integraci funkce pro automatické doplňování kódu do textových editorů a samozřejmě i do integrovaných vývojových prostředí. Tato technologie, která se nazývá omni completion, IntelliSense apod. je samozřejmě vývojáři vyhledávaná a prakticky dennodenně používaná, protože mnohdy značným způsobem urychluje jejich práci, redukuje nutnost častého studia dokumentace méně často volaných funkcí a metod, zmenšuje množství triviálních chyb typu chybějící parametr volané funkce/metody, nekompatibilní typ předávaného parametru atd.

Poznámka: možnosti a především přesnost automatického doplňování kódu jsou do značné míry závislé na vlastnostech daného programovacího jazyka. Obecně lze říci, že čím více dynamických prvků (zjišťovaných až v době běhu aplikace, tedy nikoli už při překladu) jazyk obsahuje, tím bude implementace automatického doplňování složitější a mnohdy i méně přesná. Tento problém se v posledních několika letech snaží autoři IDE či LSP pluginů řešit s využitím technologií založených na strojovém učení. Příkladem může být intellicode.

Ve druhé části dnešního článku si ukážeme, jakým způsobem se výše zmíněný projekt gocode používá v textovém editoru Vim. Uvidíme, že integrace Vim+gocode je z pohledu uživatelů jednoduchá a přitom uspokojivě funkční. Třetí část dnešního článku je věnována možná poněkud neočekávanému tématu – popisem projektu Gore, který do programovacího jazyka Go implementuje plnohodnotnou interaktivní smyčku REPL (Read-Eval-Print-Loop), což je pro kompilovaný programovací jazyk možná poněkud neobvyklé, ale o to zajímavější řešení. Smyčka REPL totiž mj. umožňuje odlišný způsob vývoje, než jaký známe z klasických vývojových prostředí: namísto neustálých opakování cyklů editace→překlad→spuštění→kontrola chyb je totiž možné interaktivně, tj. doslova příkaz po příkazu, zadávat a sledovat chování programu. To je výhodné například při testování možností cizích knihoven, přípravě jednotkových testů, zkoumání různých parametrů použitých algoritmů atd.

2. Nastavení proměnných prostředí PATH a GOPATH

Jak jsme si již řekli v úvodní kapitole, budeme se v první části dnešního článku zabývat popisem nástroje gocode. Ještě předtím, než budeme moci tento nástroj nainstalovat a plnohodnotně použít, je však nutné správně nastavit proměnné prostředí (environment variables) nazvané PATH a GOPATH. I v případě, že tyto proměnné nejsou nastaveny korektně, je totiž možné jazyk Go (překladač atd.) relativně bez problémů používat, ovšem nástroj gocode by bez nastavení těchto proměnných ve velkém množství případů neposkytoval žádné rozumné výsledky.

Proměnná GOPATH by měla obsahovat cestu či cesty k adresářové struktuře, ve které se nachází zdrojové kódy, balíčky a spustitelné aplikace/nástroje jazyka Go, které ovšem leží mimo ten adresář, do kterého je nainstalován jazyk Go (tento adresář je obsažen v proměnné prostředí GOROOT). Proměnná GOPATH je použita několika nástroji, mj. i nástrojem gocode při hledání kódu pro automatické doplnění.

Proměnná PATH obsahuje cestu či (mnohem častěji) větší množství cest k adresářům se spustitelnými soubory. Do této proměnné je vhodné přidat mj. i podadresář bin obsahující nativní nástroje programovacího jazyka Go a taktéž podadresář, do kterého se ukládají lokálně zkompilované nástroje instalované příkazem go get.

Podívejme se nyní na typické nastavení proměnných GOPATH a PATH. Proměnná GOPATH bude ukazovat na adresář ~/go/, tj. na adresář vytvořený v domácím adresáři aktivně přihlášeného uživatele, v němž je vytvořena následující struktura:

├── bin
├── pkg
│   └── linux_amd64
└── src
    ├── github.com
        └── golang.org
    ...
    ...
    ...
Poznámka: ve skutečnosti postačuje, aby zde existovaly tři prázdné podadresáře bin, pkg a src.

Do proměnné PATH přidáme dva adresáře. Prvním z nich je adresář s cestou /opt/go/bin, protože právě do /opt/go byl nainstalován jazyk Go se všemi standardními knihovnami a nástroji. Druhým adresářem je ~/go/bin, jelikož právě do tohoto adresáře se instalují spustitelné soubory instalované příkazem go get (mezi tyto soubory patří i dále popsaný nástroj gocode).

Následuje ukázka nastavení obou proměnných prostředí provedených například v souboru .bashrc či .profile:

export GOPATH=~/go/
export PATH=$PATH:~/bin:~/.local/bin/:/opt/go/bin:~/go/bin

Po nastavení těchto proměnných prostředí se můžeme příkazem go env přesvědčit, jaká je aktuální konfigurace jazyka Go, přesněji řečeno, jak proměnné interpretují standardní nástroje Go (dochází zde k expanzi ~ atd. atd.):

$ go env
 
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/tester/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/tester/go/bin"
GOPROXY=""
GORACE=""
GOROOT="/opt/go"
GOTMPDIR=""
GOTOOLDIR="/opt/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build015606214=/tmp/go-build -gno-record-gcc-switches"
Poznámka: povšimněte si, že se proměnná GOPATH skutečně interpretovala správně, protože nastavení bylo provedeno pro uživatele tester, jehož domácí adresář ~/ je expandován na /home/tester.

3. Instalace nástroje gocode

Po nastavení konfigurace programovacího jazyka Go se již můžeme zabývat prvním nástrojem, o němž jsme se ve stručnosti zmínili v úvodní kapitole dnešního článku. Tento nástroj se jmenuje gocode a instaluje se naprosto stejným způsobem, jako většina ostatních knihoven, nástrojů a pomocných modulů programovacího jazyka Go – příkazem go get:

$ go get github.com/mdempsky/gocode

Po zadání tohoto příkazu se naklonuje repositář se zdrojovými kódy nástroje gocode, naklonují se i repositáře závislých projektů a následně se provede překlad všech potřebných knihoven i slinkování výsledného spustitelného nativního souboru. Výsledkem překladu a slinkování bude soubor gocode uložený v adresáři ~/$GOPATH/bin/:

$ ls -l $GOPATH/bin
 
total 19872
-rwxr-xr-x 1 tester tester 11995863 čen 26 21:47 gocode
-rwxr-xr-x 1 tester tester  8347658 čen 26 14:38 gore

O tom, že byl nástroj gocode přeložen korektně (pro danou architekturu) se prozatím můžeme přesvědčit alespoň pokusem o zobrazení jeho nápovědy:

$ gocode --help
 
Usage: gocode [-s] [-f=<format>] [-in=<path>] [-sock=<type>] [-addr=<addr>]
       <command> [<args>]
 
Flags:
  -addr string
        address for tcp socket (default "127.0.0.1:37373")
  ...
  ...
  ...
Poznámka: pokud pouze spustíte soubor gocode bez dalších parametrů, spustí se na pozadí v režimu serveru.

4. Otestování nástroje gocode z příkazové řádky

Nyní si již můžeme ukázat základní funkce nabízené nástrojem gocode. Nejdříve tento nástroj spustíme v režimu serveru a přesvědčíme se, že byl skutečně spuštěn na pozadí:

$ gocode
 
$ ps ax |grep gocode
 1897 pts/6    Sl     0:00 gocode -s -sock unix -addr 127.0.0.1:37373

Následně vytvoříme následující zdrojový soubor nazvaný 01_counter.go, který ovšem není, jak jste si mohli povšimnout, úplný, takže by ho nebylo možné přeložit. Šipka na šestnáctém řádku není součástí zdrojového kódu, ale pouze ukazuje pozici kurzoru v textovém editoru. Právě na tomto místě budeme požadovat, aby nám nástroj gocode nabídl všechny možné identifikátory, které je možné v daném kontextu doplnit:

package main
 
import (
        "fmt"
        "time"
)
 
func main() {
        var cnt int = 0
 
        for i := 0; i < 1000; i++ {
                go func() {
                        cnt++
                }()
        }
        time.Sleep(1000 * time.M
        fmt.Printf("%d\n", cnt)
}

Obrázek 1: S využitím klávesové zkratky G Ctrl+G lze získat přesné informace o pozici kurzoru (ten je zde naznačen modrým obdélníkem, i když skutečný kurzor přeskočil na příkazovou a stavovou řádku).

Pozice naznačená šipkou je od počátku souboru vzdálena o 159 bajtů (a v tomto případě i znaků, protože pro jednoduchost používáme čisté ASCII a nikoli plné Unicode), takže pro zobrazení všech možných identifikátorů, které lze na pozici 159 doplnit použijeme příkaz:

$ gocode -f=json --in 01_counter.go autocomplete 159

Povšimněte si, že je nutné specifikovat výstupní formát, jméno souboru, který se pošle nástroji gocode (přes socket), příkaz pro gocode (autocomplete) a taktéž i pozici kurzoru, na které očekáváme seznam pro doplnění.

Poznámka: žádné další příkazy kromě autocomplete a exit prozatím nejsou nástrojem gocode podporovány.

Nástroj gocode by měl vrátit JSON obsahující přesné informace o identifikátorech, které je možné na daném místě doplnit:

[1,[{"class":"const","package":"time","name":"March","type":"time.Month"},
{"class":"const","package":"time","name":"May","type":"time.Month"},
{"class":"const","package":"time","name":"Microsecond","type":"time.Duration"},
{"class":"const","package":"time","name":"Millisecond","type":"time.Duration"},
{"class":"const","package":"time","name":"Minute","type":"time.Duration"},
{"class":"const","package":"time","name":"Monday","type":"time.Weekday"},
{"class":"type","package":"time","name":"Month","type":"int"}]]

Můžeme vidět, že se skutečně nabídly pouze ty identifikátory z balíčku time, které začínají znakem „M“. Zajímavé ovšem je, že identifikátory konstant mají rozdílné typy.

V dalším příkladu vyzkoušíme, zda nástroj gocode dokáže doplnit všechny funkce, konstanty a proměnné balíčku fmt. Opět se podívejte, na kterém místě se nyní nachází šipka kurzoru:

package main
 
import (
        "fmt"
        "time"
)
 
func main() {
        var cnt int = 0
 
        for i := 0; i < 1000; i++ {
                go func() {
                        cnt++
                }()
        }
        time.Sleep(1000 * time.Microsecond)
        fmt.
}

Nyní se kurzor nachází na offsetu 176, takže si vyžádáme všechny možnosti automatického doplnění na této pozici:

$ gocode -f=json --in 02_counter.go autocomplete 176

Výsledek (ve formátu JSON) pro větší přehlednost upravíme do čitelnější podoby:

[
  0,
  [
    {
      "class": "func",
      "package": "fmt",
      "name": "Errorf",
      "type": "func(format string, a ...interface{}) error"
    },
    {
      "class": "func",
      "package": "fmt",
      "name": "Fprint",
      "type": "func(w io.Writer, a ...interface{}) (n int, err error)"
    },
    {
      "class": "func",
      "package": "fmt",
      "name": "Fprintf",
      "type": "func(w io.Writer, format string, a ...interface{}) (n int, err error)"
    },
    {
      "class": "func",
      "package": "fmt",
      "name": "Fprintln",
      "type": "func(w io.Writer, a ...interface{}) (n int, err error)"
    },
    ...
    ...
    ...

5. Ladicí informace vypisované serverem

Server gocode je možné nastavit i takovým způsobem, aby vypisoval ladicí informace o zdrojových kódech, které mu byly předloženy a o nabídkách automatického doplnění, které provedl. Původní instanci serveru je nejdříve nutné vypnout:

$ gocode exit

A následně znovu nastartovat, tentokrát ovšem s uvedením přepínačů -debug (výpis ladicích informací) a -s (vynucení režimu serveru, nikoli klienta):

$ gocode -debug -s

Nyní serveru znovu předložíme první testovací příklad a budeme požadovat nabídky pro automatické doplnění na offsetu 159:

$ gocode -f=json --in 01_counter.go autocomplete 159

Server vrátí požadovanou informaci, ovšem kromě toho na svůj terminál vypíše i ladicí informace v tomto tvaru:

2019/06/27 20:51:15 Got autocompletion request for '/home/tester/go-root/article_32/01_counter.go'
2019/06/27 20:51:15 Cursor at: 159
2019/06/27 20:51:15 -------------------------------------------------------
package main
 
import (
        "fmt"
        "time"
)
 
func main() {
        var cnt int = 0
 
        for i := 0; i < 1000; i++ {
                go func() {
                        cnt++
                }()
        }
        time.Sleep(1000 * time.
#       fmt.Printf("%d\n", cnt)
}
2019/06/27 20:51:15 -------------------------------------------------------
2019/06/27 20:51:15 Error parsing input file (outer block):
2019/06/27 20:51:15  /home/tester/go-root/article_32/01_counter.go:17:1: expected selector or type assertion, found ';'
2019/06/27 20:51:15  /home/tester/go-root/article_32/01_counter.go:17:3: missing ',' in argument list
2019/06/27 20:51:15  /home/tester/go-root/article_32/01_counter.go:17:6: expected operand, found '.'
2019/06/27 20:51:15  /home/tester/go-root/article_32/01_counter.go:18:3: expected ')', found 'EOF'
2019/06/27 20:51:15  /home/tester/go-root/article_32/01_counter.go:18:3: expected ';', found 'EOF'
2019/06/27 20:51:15  /home/tester/go-root/article_32/01_counter.go:18:3: expected ';', found 'EOF'
2019/06/27 20:51:15  /home/tester/go-root/article_32/01_counter.go:18:3: expected '}', found 'EOF'
2019/06/27 20:51:15  /home/tester/go-root/article_32/01_counter.go:18:3: missing ',' in argument list
2019/06/27 20:51:15 Error parsing "/home/tester/go-root/article_32/02_counter.go":
2019/06/27 20:51:15  /home/tester/go-root/article_32/02_counter.go:18:1: expected selector or type assertion, found '}'
2019/06/27 20:51:15 Elapsed duration: 8.815436ms
2019/06/27 20:51:15 Offset: 0
2019/06/27 20:51:15 Number of candidates found: 67
2019/06/27 20:51:15 Candidates are:
2019/06/27 20:51:15   const ANSIC untyped string
2019/06/27 20:51:15   const April time.Month
2019/06/27 20:51:15   const August time.Month
2019/06/27 20:51:15   const December time.Month
2019/06/27 20:51:15   const February time.Month
...
...
...
2019/06/27 20:51:15   const Wednesday time.Weekday
2019/06/27 20:51:15   func After(d time.Duration) <-chan time.Time
2019/06/27 20:51:15   func AfterFunc(d time.Duration, f func()) *time.Timer
2019/06/27 20:51:15   func Date(year int, month time.Month, day int, hour int, min int, sec int, nsec int, loc *time.Location) time.Time
...
...
...
2019/06/27 20:51:15   type Time struct
2019/06/27 20:51:15   type Timer struct
2019/06/27 20:51:15   type Weekday int
2019/06/27 20:51:15   var Local *time.Location
2019/06/27 20:51:15   var UTC *time.Location
2019/06/27 20:51:15 =======================================================

Podobně je tomu ve druhém příkladu:

$ gocode -f=json --in 02_counter.go autocomplete 176

S ladicími informacemi:

2019/06/27 20:49:01 Got autocompletion request for '/home/tester/go-root/article_32/02_counter.go'
2019/06/27 20:49:01 Cursor at: 176
2019/06/27 20:49:01 -------------------------------------------------------
package main
 
import (
        "fmt"
        "time"
)
 
func main() {
        var cnt int = 0
 
        for i := 0; i < 1000; i++ {
                go func() {
                        cnt++
                }()
        }
        time.Sleep(1000 * time.Microsecond)
        fmt.#
}
2019/06/27 20:49:01 -------------------------------------------------------
2019/06/27 20:49:01 Error parsing input file (outer block):
2019/06/27 20:49:01  /home/tester/go-root/article_32/02_counter.go:17:6: expected selector or type assertion, found ';'
2019/06/27 20:49:01 Error parsing "/home/tester/go-root/article_32/01_counter.go":
2019/06/27 20:49:01  /home/tester/go-root/article_32/01_counter.go:17:25: missing ',' before newline in argument list
2019/06/27 20:49:01  /home/tester/go-root/article_32/01_counter.go:18:1: expected operand, found '}'
2019/06/27 20:49:01 Elapsed duration: 8.312908ms
2019/06/27 20:49:01 Offset: 0
2019/06/27 20:49:01 Number of candidates found: 25
2019/06/27 20:49:01 Candidates are:
2019/06/27 20:49:01   func Errorf(format string, a ...interface{}) error
2019/06/27 20:49:01   func Fprint(w io.Writer, a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Fscan(r io.Reader, a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Fscanln(r io.Reader, a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Print(a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Printf(format string, a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Println(a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Scan(a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Scanf(format string, a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Scanln(a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Sprint(a ...interface{}) string
2019/06/27 20:49:01   func Sprintf(format string, a ...interface{}) string
2019/06/27 20:49:01   func Sprintln(a ...interface{}) string
2019/06/27 20:49:01   func Sscan(str string, a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Sscanf(str string, format string, a ...interface{}) (n int, err error)
2019/06/27 20:49:01   func Sscanln(str string, a ...interface{}) (n int, err error)
2019/06/27 20:49:01   type Formatter interface
2019/06/27 20:49:01   type GoStringer interface
2019/06/27 20:49:01   type ScanState interface
2019/06/27 20:49:01   type Scanner interface
2019/06/27 20:49:01   type State interface
2019/06/27 20:49:01   type Stringer interface
2019/06/27 20:49:01 =======================================================
Poznámka: informace o tom, že zdrojové kódy nelze parsovat, je správná, protože nejsou zcela dokončeny (chybí uzavírací závorky atd.).

6. Výstupní formáty nástroje gocode

Nástroj gocode poskytuje informace o kódu, který je možné v daném místě doplnit, v několika různých formátech. S formátem JSON jsme se již setkali v předchozích kapitolách, takže se zde zmiňme o dalších podporovaných formátech:

  1. CSV
  2. Formát pro Vim
  3. Formát pro Emacs
  4. Takzvaný „nice“ formát

Formát CSV poskytuje informace ve formě jednoduché tabulky zpracovatelné libovolnou knihovnou, která s CSV dokáže pracovat (taková knihovna dnes existuje pro prakticky každý programovací jazyk):

$ gocode -f=csv --in 01_counter.go autocomplete 159
 
const,,ANSIC,,untyped string,,time
const,,April,,time.Month,,time
const,,August,,time.Month,,time
const,,December,,time.Month,,time
const,,February,,time.Month,,time
const,,Friday,,time.Weekday,,time
const,,Hour,,time.Duration,,time
const,,January,,time.Month,,time
const,,July,,time.Month,,time
...
...
...

Formát pro Vim odpovídá datovým typům Vim Scriptu, takže je snadno zpracovatelný přímo ve Vimu:

$ gocode -f=vim --in 01_counter.go autocomplete 159
 
[0, [
    {'word': 'ANSIC', 'abbr': 'const ANSIC untyped string', 'info': 'const ANSIC untyped string'},
    {'word': 'April', 'abbr': 'const April time.Month', 'info': 'const April time.Month'},
    {'word': 'August', 'abbr': 'const August time.Month', 'info': 'const August time.Month'},
    {'word': 'December', 'abbr': 'const December time.Month', 'info': 'const Decembe
    ...
    ...
    ...

Formát určený pro Emacs má následující strukturu podobnou struktuře CSV:

$ gocode -f=emacs --in 01_counter.go autocomplete 159
 
ANSIC,,const untyped string
April,,const time.Month
August,,const time.Month
December,,const time.Month
...
...
...

A konečně „pěkný“ (nice) formát je určen spíše pro čtení uživateli než pro přímé zpracování:

$ gocode -f=nice --in 01_counter.go autocomplete 159
 
Found 67 candidates:
  const ANSIC untyped string
  const April time.Month
  const August time.Month
  const December time.Month
  const February time.Month
  const Friday time.Weekday
  const Hour time.Duration

7. Doplňování kódu v textovém editoru Vim

Ve druhé části článku si ukážeme zkombinování textového editoru Vim a nástroje gocode.

Velmi užitečnou vlastností textového editoru Vim, kterou se dnes budeme v souvislosti s pluginem vim-gocode alespoň ve stručnosti zabývat, je technologie nazvaná „omni completion“ (někdy se setkáme i s jednoslovným zápisem „omnicompletion“). Tato technologie, která se ve Vimu objevila až v jeho sedmé verzi, rozšiřuje možnosti automatického doplňování kódu (či obecně textu) o externí nástroje. Připomeňme si, že Vim nabízí ve vkládacím a přepisovacím režimu klávesovou zkratku Ctrl+P (previous) pro nalezení a doplnění slova nacházejícího se před kurzorem a taktéž zkratku Ctrl+N (next), která slouží ke stejnému účelu, ovšem hledá slovo pro doplnění v textu za kurzorem (pokud je k dispozici více možností, zobrazí se všechny nalezené možnosti v kontextovém menu). V praxi tedy postačuje napsat jen začátek slova a stlačit Ctrl+P nebo Ctrl+N. Rozsah vyhledávání se specifikuje volbou complete popsanou zde a samozřejmě i ve vestavěné nápovědě.

Obrázek 2: Doplňování kódu nebo libovolného textu s využitím příkazů CTRL+P a CTRL+N zavolaných v režimu zápisu (insert mode).

Ovšem možnosti automatického doplňování kódu jsou ve skutečnosti daleko větší a textový editor Vim pro ně dokonce nabízí samostatný režim vyvolávaný z vkládacího či přepisovacího režimu klávesovou zkratkou Ctrl+X (právě z tohoto důvodu se tento režim nazývá ^X-mode nebo též CTRL-X mode). Po stlačení této klávesové zkratky se v příkazové řádce editoru objeví jednoduché jednořádkové menu s příkazy platnými pro režim doplňování:

Všechny dostupné příkazy jsou vypsány v tabulce níže:

# Příkaz Význam
1 Ctrl+X Ctrl+L nalezení a doplnění celého (shodného) řádku, užitečné především v případě editace některých typů konfiguračních souborů
2 Ctrl+X Ctrl+N doplnění slova, které se nalézá v aktuálně editovaném souboru
3 Ctrl+X Ctrl+K podobné Ctrl+N, ovšem slova se hledají v souborech specifikovaných pomocí konfiguračního parametru dictionary (jedná se o běžný textový soubor se seznamem slov)
4 Ctrl+X Ctrl+T podobné Ctrl+T, ovšem slova se hledají v souborech specifikovaných pomocí konfiguračního parametru thesaurus
5 Ctrl+X Ctrl+I podobné Ctrl+N, ovšem prohledávají se i všechny vkládané (included) soubory
6 Ctrl+X Ctrl+] vyhledávání v seznamu značek
7 Ctrl+X Ctrl+F doplnění názvu souboru a/nebo cesty, postačuje například zadat text ~/ za nímž následuje klávesová zkratka Ctrl+X Ctrl+F a zobrazí se výpis souborů v domácím adresáři
8 Ctrl+X Ctrl+D vyhledání definice makra a doplnění jména tohoto makra
9 Ctrl+X Ctrl+U zavolání funkce zadané v konfiguračním parametru completefunc, které se předá právě editovaný text
10 Ctrl+X Ctrl+O vyvolání funkce omni completion popsané <a>v následující kapitole (dostupné od Vimu 7)

Obrázek 3: Doplnění názvu souboru v pracovním adresáři pomocí příkazu CTRL+X CTRL+F.

8. Technologie omnicompletion

V předchozí kapitole jsme si řekli, že s využitím klávesové zkratky Ctrl+X Ctrl+O lze ve vkládacím a přepisovacím režimu zavolat technologii „omni completion“. Tuto technologii lze využít pro (pseudo)inteligentní doplňování textů založeném na analýze zdrojových kódů. Podobnou funkci můžeme najít v nejrůznějších integrovaných vývojových prostředích (Eclipse, Netbeans, Visual Studio, Visual Studio Code, nověji například i v Atomu), v nichž lze doplňovat například jména funkcí a metod, názvy prvků ve strukturách či uniích, atributů objektů, metod objektů či tříd, jmen balíčků atd.

Implicitně tato funkce není specifikována vůbec, o čemž se můžete velmi snadno přesvědčit při spuštění „prázdného“ Vimu:

:set omnifunc?
   omnifunc=

Naopak při editaci tohoto článku (v HTML) je funkce nastavena, a to konkrétně standardním filetype pluginem html.vim:

:set omnifunc?
   omnifunc=htmlcomplete#CompleteTags

V případě, že chceme použít možnosti nabízené například pluginem vim-lsp, můžeme omnifunc nastavit globálně (pro celý Vim). To se provede jednoduše příkazem:

:set omnifunc=lsp#complete

Popř. lze stejnou funkci nastavit pouze lokálně pro právě aktivní buffer:

:setlocal omnifunc=lsp#complete

Samozřejmě nemusíme toto nastavení stále provádět ručně po otevření každého zdrojového souboru, ale můžeme do konfiguračního souboru .vimrc přidat příkaz, který se automaticky zavolá při otevření souboru s koncovkou *.py (Python):

augroup __python__
  au!
  au BufRead,BufNewFile *.py setlocal omnifunc=lsp#complete
augroup END

9. Instalace pluginu vim-gocode do Vimu

Pro zkombinování možností textového editoru Vim a výše popsaného nástroje gocode slouží plugin (přídavný modul) nazvaný jednoduše a přímočaře vim-gocode. Zdrojové kódy tohoto modulu nalezneme v repositáři dostupném na adrese https://github.com/volgar1×/vim-gocode.

Instalaci modulu vim-gocode je možné provést různými způsoby (například využít různé správce balíčků), ovšem lze zůstat i u konzervativní metody a rozbalit všechny soubory přímo do adresáře ~./vim. V mém případě používám správce balíčků nazvaný Pathogen (viz též Užitečné skripty a pluginy pro textový editor Vim), takže instalace bude ještě jednodušší – celý repositář se jednoduše naklonuje do adresáře ~/.vim/bundle.

V podadresáři ~/.vim by měla být vytvořena následující adresářová struktura (samozřejmě zde můžeme mít uloženy další pluginy, ostatně i já zde mám nainstalovány například slovníky):

.
├── autoload
├── bundle
│   ├── calendar-vim
│   │   ...
│   │   ...
│   │   ...
│   ├── rainbow_parentheses.vim
│   │   ...
│   │   ...
│   │   ...
│   ├── todo.txt-vim
│   │   ...
│   │   ...
│   │   ...
│   ├── vim-fugitive
│   │   ...
│   │   ...
│   │   ...
│   ├── vim-gocode
│   │   ├── autoload
│   │   │   └── go
│   │   ├── compiler
│   │   ├── doc
│   │   ├── ftdetect
│   │   ├── ftplugin
│   │   │   └── go
│   │   ├── indent
│   │   ├── plugin
│   │   └── syntax
│   ├── vim-slime
│   │   ...
│   │   ...
│   │   ...
│   └── vim-table-mode
│       ...
│       ...
│       ...
├── doc
├── ftdetect
├── plugin
├── spell
└── syntax

10. Otestování základních vlastností poskytovaných pluginem vim-gocode

Plugin vim-gocode nabízí uživatelům větší množství důležitých funkcí, které naleznete v integrované nápovědě po zadání příkazu:

:help vim-gocode

Mezi užitečné funkce patří především použití klávesy Tab s automatickým zarovnáváním bloků a s převodem mezer na znaky Tab (což je současnou verzí jazyka Go striktně vyžadováno). Důležitější je ovšem funkce omni completion, která je dostupná pod standardní klávesovou zkratkou Ctrl+X Ctrl+O. Podívejme se nyní na použití této klávesové zkratky na obou demonstračních příkladech, které jsme již viděli v předchozích kapitolách:

Obrázek 4: Nabídka s automaticky nalezenými funkcemi a konstantami. Povšimněte si, že v automaticky vytvořeném okně (nahoře) se zobrazují přesnější informace o doplňovaném symbolu.

Obrázek 5: Nabídka s automaticky nalezenými funkcemi v balíčku fmt.

11. Konfigurace klávesové zkratky pro vyvolání omni completion

Výše uvedená konfigurace sice teoreticky postačuje po prakticky plnohodnotné využití možností pluginu vim-gocode, ovšem skalní uživatelé Vimu pravděpodobně očekávají nějaká vylepšení, která by Vim přiblížila k moderním IDE. Týká se to mj. i klávesové zkratky použité pro vyvolání funkce omni completion, protože Ctrl+X Ctrl+O je spíše „emacsovina“ :-) Řešení samozřejmě existuje několik. Můžeme například použít klávesovou zkratku Ctrl+Tab, pokud se nepoužívá ve správci oken:

:imap <C-Tab> <C-X><C-O>

Alternativně je možné napsat funkci, která bude na začátku řádku klávesu Tab používat pro vkládání mezer a naopak po stisku Tab za písmenem pro zavolání omni completion. Podobné řešení bylo použito v pluginu IndentTab popř. pluginu Smart-Tabs. Další ideu naleznete například na stránce Smart mapping for tab completion

V případě, že používáte GVim nebo KVim, je možné namísto klávesy Tab použít například i klávesovou zkratku Ctrl+Space:

:imap <C-Space> <C-X><C-O>

Na terminálech sice většinou není klávesová zkratka Ctrl+Space korektně rozpoznána, ale můžete se pokusit zjistit, zda terminál namísto Ctrl+Space nerozpozná alespoň Ctrl+@, tj. přesněji řečeno, zda obě klávesové zkratky nejsou rozpoznány jako shodný kód. Pokud tomu tak je, můžete mapování změnit na:

:imap <C-@> <C-X><C-O>

a používat Ctrl+Space i v terminálu.

Poznámka: technicky se klávesovou zkratkou Ctrl+@ zadává ASCII kód NUL, tj. první znak v ASCII tabulce, protože znak @ má ASCII kód 64 a stiskem modifikátoru Ctrl snižujeme ASCII kód právě o hodnotu 64. To je také důvod, proč stisk Ctrl+I odpovídá znaku HT (Horizontal Tab), Ctrl+H znaku BS (Backspace), Ctrl+[ řídicímu znaku ESC, Ctrl+M konci řádku (CR) atd. Vše osvětlí pohled na ASCII tabulku.

12. Interaktivní smyčka REPL pro kompilovaný programovací jazyk Go?

Mnozí programátoři, popř. ti uživatelé, kteří programovací jazyk musí používat pro řešení problémů ve své profesi (ovšem vývoj aplikací naopak není jejich hlavní pracovní náplní), mnohdy namísto klasických integrovaných vývojových prostředí preferují dosti odlišný způsob práce, který je v mnohem větší míře založen na přímočaré a prakticky neustálé interakci mezi vývojářem a systémem nebo vznikající (mini)aplikací, jež je mnohdy vysoce jednoúčelová. V takových případech ustupuje správa projektů poněkud do pozadí a naopak se začíná využívat dosti odlišný druh vývojového prostředí založený buď na interaktivní smyčce REPL (Read-Eval-Print-Loop) nebo na konceptu takzvaných diářů (notebooks), které jsou už poměrně dlouho velmi populární především v systémech pro numerickou matematiku, analýzy, statistické výpočty, symbolickou matematiku (manipulace se symboly a výrazy, integrace, derivace, zjednodušování výrazů atd.) a dnes taktéž pro machine learning (ML).

Obrázek 6: Za zjednodušenou formu interaktivní smyčky REPL je možné považovat i takzvaný přímý mód (direct mode) použitý například v klasickém BASICu. Na tomto screenshotu je v přímém módu zapsán příkaz LIST.

Poměrně velkou předností těchto systémů oproti klasickým integrovaným vývojovým prostředím je zejména okamžitá zpětná vazba systému na zadávané definice, deklarace, makra a příkazy. To uživatelům umožňuje se snadněji a taktéž většinou i mnohem rychleji seznámit jak s vlastním programovacím jazykem (nalezení chyby na jediném programovém řádku je určitě snazší, než analýza mnohdy několikastránkového výpisu vytvořeného překladačem), tak i s použitými knihovnami. To je dnes vlastně ještě důležitější, protože mnohdy vývoj spočívá v „lepení“ již existujících komponent či knihoven (se všemi z toho plynoucími důsledky). Aplikace vytvářené v takto koncipovaných prostředích většinou vznikají systémem zdola-nahoru (to se někdy označuje termínem bottom-up programming), tj. postupně se skládají z funkcí a tříd, které mohou být ihned po své deklaraci interaktivně otestovány.

Obrázek 7: Koncept diáře je použit například v nástroji Gorilla REPL, který mohou využít programátoři pracující s jazykem Clojure.

REPL si sice většinou spojujeme s interpretovanými programovacími jazyky, ovšem ve skutečnosti je možné smyčku REPL do určité míry používat i u jazyků kompilovaných či překládaných do bajtkódu (příkladem je programovací jazyk Clojure). Je tomu tak i v případě jazyka Go, který je kompilovaný a REPL pro něj skutečně vznikl. U jazyka Go je to umožněno zejména díky tomu, že překladač Go je velmi rychlý, takže se v REPL může relativně bez problémů používat překlad každé definice či příkazu, a to i na pomalejších počítačích.

13. Interaktivní smyčka REPL v různých jazycích a nástrojích

S principem a použitím interaktivní smyčky REPL jsme se již na stránkách Rootu setkali, a to dokonce mnohokrát. Kromě článků, které se věnovaly klasickým Unixovým shellům typu BASH, tcsh či zsh (a rozhraní shellů není nic jiného, než interaktivní REPL), jsme smyčku REPL použili například při popisu programovacího jazyka Julia či jazyka Clojure. Historií vzniku REPL jsme se zabývali i zde.

Některé smyčky REPL jsou pojaty přísně minimalisticky, což je případ dnes již spíše minimálně používaného jazyka TCL. Tato interaktivní REPL dokonce ani neobsahuje historii příkazů či podporu pro pohyb kurzoru na příkazovém řádku:

%
Poznámka: povšimněte si, že se liší i znak výzvy (prompt), protože se namísto obvyklého > používá znak procenta; to je ovšem pouze marginální změna.

Další interaktivní REPL alespoň uživatele informují, v jakém prostředí se nachází. To je případ REPL (opět velmi jednoduše pojaté) programovacího jazyka Lua:

Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio
>

REPL projektu LuaJIT vypadá nepatrně odlišně:

LuaJIT 2.1.0-beta3 -- Copyright (C) 2005-2017 Mike Pall. http://luajit.org/
JIT: ON SSE2 SSE3 SSE4.1 BMI2 fold cse dce fwd dse narrow loop abc sink fuse
>

Nově se plnohodnotný REPL objevil i v jazyku Clojure; v předchozích verzích se používal dále zmíněný alternativní nREPL:

Clojure 1.9.0
user=>

Podobně vypadá REPL programovacího jazyka Pixie (to vlastně není nijak překvapivé, protože se opět jedná o jednu z v:

user =>

Interaktivní rozhraní projektu GNU Guile, což je jedna z variant programovacího jazyka Scheme:

GNU Guile 2.0.14
Copyright (C) 1995-2016 Free Software Foundation, Inc.
 
Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.
 
Enter `,help' for help.
scheme@(guile-user)>

Plnohodnotnou smyčku REPL se všemi vymoženostmi nabízí zejména programovací jazyk Julia, což ostatně není překvapivé, protože se tento jazyk používá právě pro postupnou inkrementální tvorbu aplikací v interaktivním prostředí:

               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.0.0 (2018-08-08)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |
 
julia>

Podobně je tomu v případě programovacího jazyka Clojure doplněného o nREPL (ten lze spustit například příkazem lein repl):

nREPL server started on port 42733 on host 127.0.0.1 - nrepl://127.0.0.1:42733
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.8.0
OpenJDK 64-Bit Server VM 1.8.0_171-b10
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e
 
user=>

Samozřejmě nesmíme zapomenout ani na REPL doménově specifického jazyka R:

R version 3.5.3 (2019-03-11) -- "Great Truth"
Copyright (C) 2019 The R Foundation for Statistical Computing
Platform: x86_64-redhat-linux-gnu (64-bit)
 
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.
 
  Natural language support but running in an English locale
 
R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.
 
Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.
 
During startup - Warning messages:
1: Setting LC_TIME failed, using "C"
2: Setting LC_MONETARY failed, using "C"
3: Setting LC_PAPER failed, using "C"
4: Setting LC_MEASUREMENT failed, using "C"
gt;

Obrázek 8: Jedna z alternativních REPL určených pro programovací jazyk Python.

14. Projekt Gore

Jak jsme se již zmínili v předchozích kapitolách, implementace interaktivní smyčky REPL vznikla i pro programovací jazyk Go. Jedná se o projekt nazvaný Gore, jehož zdrojové kódy nalezneme na adrese https://github.com/motemen/go­re/cmd/gore (existuje i několik forků tohoto projektu). O tomto projektu se v dnešním článku zmiňujeme mj. i proto, že díky kooperaci s projektem gocode nabízí uživatelům i možnost automatického doplňování příkazů, což je velmi užitečné (a mnozí uživatelé si plnohodnotný REPL bez funkce autocomplete ani nedokážou představit).

15. Instalace projektu Gore a spuštění interaktivní smyčky REPL

Instalace projektu Gore se nijak neliší od instalace jakéhokoli jiného balíčku programovacího jazyka Go:

$ go get -u github.com/motemen/gore/cmd/gore

Po (doufejme že úspěšné) instalaci by se měl na PATH objevit i příkaz gore (viz též druhou kapitolu s popisem nastavení cesty).

Samotnou interaktivní smyčku REPL spustíme právě příkazem gore:

$ gore

Následně by se měly objevit základní informace o REPL, verze projektu i takzvaná výzva (prompt):

gore version 0.4.1  :help for help
gore>

V tomto okamžiku REPL očekává příkazy, které budou ihned vykonány. Můžeme zadávat i pseudopříkazy, které začínají dvojtečkou. Asi nejlepším příkladem takového pseudopříkazu je nápověda vyvolaná pomocí :help:

gore> :help
 
    :import <package>     import a package
    :type <expr>          print the type of expression
    :print                print current source
    :write [<file>]       write out current source
    :clear                clear the codes
    :doc <expr or pkg>    show documentation
    :help                 show this help
    :quit                 quit the session

Do interaktivní smyčky REPL ovšem můžete zadávat i běžné programové konstrukce programovacího jazyka Go. Příkladem může být deklarace proměnné:

gore> i := 42
(int)42
 
gore> x := "Hello"
(string)Hello
Poznámka: zde využijeme možnost použití deklarace s automatickým odvozením typu proměnné.

Dále si můžeme vyzkoušet vytvořit si programovou smyčku. Povšimněte si, že REPL správně zjistí, kde se používají programové bloky a nevyžaduje stisk Tabu:

gore> for j := 1; j <= 10; j++ {
.....     println(j)
..... }
1
2
3
4
5
6
7
8
9
10

V REPL lze vytvářet i funkce:

gore> func Hello() {
.....     println("Hello world!")
..... }
 
gore> Hello()
Hello world!
 
gore> Hello
(func())0x4a9350
Nedílnou součástí moderních REPL je i historie příkazů. Ta je v případě projektu gore ukládána do souboru, takže je historie dostupná i mezi restarty REPLu.

Jedna důležitá vlastnost zde ovšem chybí – barevné odlišení příkazů, parametrů, konstant, proměnných a pseudopříkazů.

16. Speciální pseudopříkazy používané v REPL projektu Gore

S takzvanými pseudopříkazy jsme se již setkali v předchozí kapitole. Tyto pseudopříkazy začínají znakem dvojtečky a můžeme je použít například pro získání dokumentace. Následující pseudopříkaz vypíše dokumentaci k zabudované funkci println:

gore> :doc println
 
func println(args ...Type)
    The println built-in function formats its arguments in an
    implementation-specific way and writes the result to standard error. Spaces
    are always added between arguments and a newline is appended. Println is
    useful for bootstrapping and debugging; it is not guaranteed to stay in the
    language.

Dalším pseudopříkazem je příkaz :import, který je možné použít kdykoli, nikoli jen na začátku balíčku (pojem balíček je ovšem v rámci REPLu poněkud mlhavý):

gore> :import fmt

Ihned po importu balíčku je možné získat nápovědu k jeho funkcím, konstantám, typům a metodám:

gore> :doc fmt.Println
 
func Println(a ...interface{}) (n int, err error)
    Println formats using the default formats for its operands and writes to
    standard output. Spaces are always added between operands and a newline is
    appended. It returns the number of bytes written and any write error
    encountered.

Dtto pro balíček time a jeho funkci Sleep:

gore> :import time
gore> :doc time.Sleep
func Sleep(d Duration)
    Sleep pauses the current goroutine for at least the duration d. A negative
    or zero duration causes Sleep to return immediately.

Velmi užitečný je i pseudopříkaz :write jméno_souboru, který zapíše zapsané definice do specifikovaného souboru, který by měl být později přeložitelný překladačem jazyka Go.

17. Odkazy na Internetu

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