Obsah
1. Vkládání dat přímo do spustitelných souborů vytvářených překladačem jazyka Go
2. Vložení krátkého řetězce do výsledného spustitelného souboru
3. Korektní způsob použití balíčku embed
4. Vložení delšího víceřádkového řetězce do výsledného spustitelného souboru
5. Binární data (sekvence bajtů) vložená do výsledného spustitelného souboru
6. Pokus o vložení dat jiného typu
7. Vložené soubory a virtuální souborový systém
8. Přístup ke vloženému souboru přes virtuální souborový systém
9. Vložení rastrových dat ve formátu JPEG, export obrázku v runtime
10. Jak lze do virtuálního souborového systému přidat větší množství souborů?
11. Získání seznamu všech souborů vložených do vybraného virtuálního adresáře
12. Větší množství adresářů ve virtuálním souborovém systému
14. Repositář s demonstračními příklady
1. Vkládání dat přímo do spustitelných souborů vytvářených překladačem jazyka Go
Programovací jazyk Go je mezi vývojáři v některých oblastech (například v oblasti mikroslužeb) oblíben mj. i proto, že pro nasazení aplikace vyvinuté v Go je mnohdy nutné pouze použít jediný spustitelný soubor a příliš se nestarat o to, na jakých dalších dynamicky linkovaných knihovnách nasazovaná aplikace závisí (protože tyto závislosti v mnoha případech vůbec neexistují). To je výhodné například tehdy, pokud se aplikace nasazuje do „kontejnerizovaného“ prostředí atd. Většinou se taková aplikace konfiguruje nikoli s využitím konfiguračního souboru, ale přes proměnné prostředí, takže odpadá nutnost nasazení a správy konfiguračních souborů.
Ovšem situace je poněkud odlišná tehdy, pokud aplikace ke své činnosti vyžaduje nějaké soubory s daty. Může se jednat například o statické HTML stránky, obrázky, šablony (templates) atd. Zde již výhody nasazení celé aplikace pouhým zkopírováním jediného souboru zdánlivě mizí. Ovšem jazyk Go od verze 1.16 podporuje zajímavou a užitečnou technologii – datové soubory je totiž umožněno přidat přímo do onoho spustitelného souboru vytvářeného překladačem a linkerem jazyka Go. A navíc je možné k obsahu těchto souborů přistupovat buď přímo jakoby se jednalo o inicializované proměnné (typu řetězec či sekvence bajtů) nebo přes „virtuální“ souborový systém. A právě tuto relativně málo známou vlastnost programovacího jazyka Go si popíšeme v dnešním článku.
2. Vložení krátkého řetězce do výsledného spustitelného souboru
Do výsledného spustitelného souboru můžeme vložit řetězec, jenž je v době překladu načtený z nějakého textového souboru. Pro tento účel se před definicí proměnné použije tento speciální komentář:
//go:embed hello.txt
Například:
package main import ( "fmt" ) //go:embed hello.txt var helloMessage string func main() { // pouziti retezce fmt.Println(helloMessage) }
Při pokusu o překlad tohoto zdrojového kódu však dojde k chybě, protože pro zpracování výše uvedeného speciálního komentáře je nutné načíst balíček embed:
./embed_string0.go:7:3: go:embed only allowed in Go files that import "embed"
Pokusme se tedy o úpravu tohoto příkladu:
package main import ( "embed" "fmt" ) //go:embed hello.txt var helloMessage string func main() { // pouziti retezce fmt.Println(helloMessage) }
Ani tento způsob ovšem ve skutečnosti není zcela korektní, protože sice importujeme balíček embed, ovšem nikde ho nepoužijeme, což v Go není dovoleno (je použit jen v onom komentáři):
./embed_string1.go:4:2: "embed" imported and not used
3. Korektní způsob použití balíčku embed
Jak tedy můžeme naimportovat balíček embed, i když není přímo v kódu použit? Programovací jazyk Go vyžaduje, aby každý importovaný balíček byl skutečně využit (což jsme ostatně viděli výše), ovšem existuje zde jeden trik, jak pouze provést import bez explicitního použití (používá se například při načítání databázových driverů). Tento trik spočívá v tom, že se před jméno importovaného balíčku zadá jeho jmenný alias, který je nastavený na podtržítko:
import _ "embed"
V praxi to může vypadat následovně:
package main import ( _ "embed" "fmt" ) //go:embed hello.txt var helloMessage string func main() { // pouziti retezce fmt.Println(helloMessage) }
Tento zdrojový kód je již bez problémů jak přeložitelný, tak i spustitelný:
$ go build embed_string2.go $ ./embed_string2 Hello world!
O tom, že řetězec „Hello world!“ je skutečně ve spustitelném kódu použit, se lze snadno přesvědčit (i když dost primitivním způsobem):
$ strings embed_string2 | grep Hello entersyscallgcBitsArenasgcpacertraceharddecommithost is downillegal seekinvalid slotlfstack.pushmadvdontneedmheapSpecialmspanSpecialnot pollablens} value: {releasep: m=runtime: gp=runtime: sp=spanSetSpinesweepWaiterstimer_deletetraceStringswirep: p->m=worker mode }, want {r1= != sweepgen MB globals, MB) workers= called from failed with flushedWork idlethreads= is nil, not nStackRoots= pluginpath= s.spanclass= span.base()= syscalltick= work.nproc= work.nwait= , gp->status=, not pointer-byte block (3814697265625: unknown pc GC sweep waitGunjala_GondiHello world!
4. Vložení delšího víceřádkového řetězce do výsledného spustitelného souboru
V dalším demonstračním příkladu se do výsledného spustitelného kódu pokusíme vložit delší řetězec, který je navíc víceřádkový. Použijeme přitom klasický příklad odstavce „Lorem ipsum“:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Samotný zdrojový kód příkladu se prakticky nebude lišit od příkladu předchozího, pouze použijeme jiné jméno souboru „ipsum.txt“ a jiné jméno proměnné, do které se obsah tohoto souboru automaticky přiřadí (loremIpsum):
package main import ( _ "embed" "fmt" ) //go:embed lorem_ipsum.txt var loremIpsum string func main() { // pouziti retezce fmt.Println(loremIpsum) }
Proveďme kontrolní překlad a spuštění:
$ go build embed_string3.go $ ./embed_string3 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
5. Binární data (sekvence bajtů) vložená do výsledného spustitelného souboru
Kromě řetězců lze do výsledného spustitelného souboru vložit data v ještě jednom dostupném a podporovaném formátu. Jedná se o sekvenci bajtů, což je datový typ, jenž je v jazyce Go reprezentován buď jako pole bajtů (nepříliš často používáno) nebo jako řez bajtů, tj.:
[]byte
Programově je možné tuto sekvenci bajtů použít různými způsoby, například ji předat do funkce json.Unmarshal, xml.Unmarshal atd. V obou zmíněných případech má funkce pro dekódování dat ze sekvence bajtů zcela shodnou hlavičku (což samozřejmě není náhoda):
func Unmarshal(data []byte, v any) error
Vložení binárních dat (a nikoli řetězců) do výsledného spustitelného souboru je snadné, jak to ostatně ukazuje následující demonstrační příklad:
package main import ( _ "embed" "fmt" ) //go:embed lorem_ipsum.txt var loremIpsum []byte func main() { // pouziti retezce fmt.Println(loremIpsum) }
Po překladu a spuštění tohoto příkladu se zobrazí obsah jednotlivých bajtů v řezu:
$ go run embed_binary1.go [76 111 114 101 109 32 105 112 115 117 109 32 100 111 108 111 114 32 115 105 116 32 97 109 101 116 44 32 99 111 110 115 101 99 116 101 116 117 114 32 97 100 105 112 105 115 99 105 110 103 32 101 108 105 116 44 32 115 101 100 32 100 111 32 101 105 117 115 109 111 100 32 116 101 109 112 111 114 10 105 110 99 105 100 105 100 117 110 116 32 117 116 32 108 97 98 111 114 101 32 101 116 32 100 111 108 111 114 101 32 109 97 103 110 97 32 97 108 105 113 117 97 46 32 85 116 32 101 110 105 109 32 97 100 32 109 105 110 105 109 32 118 101 110 105 97 109 44 32 113 117 105 115 10 110 111 115 116 114 117 100 32 101 120 101 114 99 105 116 97 116 105 111 110 32 117 108 108 97 109 99 111 32 108 97 98 111 114 105 115 32 110 105 115 105 32 117 116 32 97 108 105 113 117 105 112 32 101 120 32 101 97 32 99 111 109 109 111 100 111 32 99 111 110 115 101 113 117 97 116 46 10 68 117 105 115 32 97 117 116 101 32 105 114 117 114 101 32 100 111 108 111 114 32 105 110 32 114 101 112 114 101 104 101 110 100 101 114 105 116 32 105 110 32 118 111 108 117 112 116 97 116 101 32 118 101 108 105 116 32 101 115 115 101 32 99 105 108 108 117 109 32 100 111 108 111 114 101 32 101 117 10 102 117 103 105 97 116 32 110 117 108 108 97 32 112 97 114 105 97 116 117 114 46 32 69 120 99 101 112 116 101 117 114 32 115 105 110 116 32 111 99 99 97 101 99 97 116 32 99 117 112 105 100 97 116 97 116 32 110 111 110 32 112 114 111 105 100 101 110 116 44 32 115 117 110 116 32 105 110 10 99 117 108 112 97 32 113 117 105 32 111 102 102 105 99 105 97 32 100 101 115 101 114 117 110 116 32 109 111 108 108 105 116 32 97 110 105 109 32 105 100 32 101 115 116 32 108 97 98 111 114 117 109 46 10]
Zdrojový kód tohoto příkladu naleznete na adrese https://github.com/tisnik/go-root/blob/master/article_AB/embed_binary1.go.
Ale převod zpět na řetězec je snadný:
package main import ( _ "embed" "fmt" ) //go:embed lorem_ipsum.txt var loremIpsum []byte func main() { // pouziti retezce fmt.Println(string(loremIpsum)) }
S očekávaným výsledkem:
$ go run embed_binary2.go Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Zdrojový kód tohoto příkladu naleznete na adrese https://github.com/tisnik/go-root/blob/master/article_AB/embed_binary2.go.
6. Pokus o vložení dat jiného typu
Zajímavé bude zjistit, co se stane ve chvíli, kdy se do výsledného spustitelného souboru pokusíme vložit data jiného typu než řetězec nebo sekvence bajtů. Vyzkoušíme si to například na tomto demonstračním příkladu:
package main import ( _ "embed" "fmt" ) type Foo struct { x string y bool } //go:embed lorem_ipsum.txt var loremIpsum Foo func main() { // pouziti struktury fmt.Println(loremIpsum) }
I když by to mohlo být užitečné, není tato funkcionalita překladačem Go podporována, o čemž nás překladač bude nekompromisně informovat:
$ go build embed_other_data.go # command-line-arguments ./embed_other_data.go:14:5: go:embed cannot apply to var of type Foo
Zdrojový kód tohoto příkladu naleznete na adrese https://github.com/tisnik/go-root/blob/master/article_AB/embed_other_data.go.
7. Vložené soubory a virtuální souborový systém
Přímé vkládání obsahu souborů do výsledného spustitelného binárního souboru je sice potenciálně velmi užitečná funkce, ovšem standardní balíček embed programátorům nabízí ještě jednu velmi zajímavou funkcionalitu – možnost přístupu ke vloženým souborům takovým způsobem, jakoby se jednalo o virtuální souborový systém. Konkrétně je tento souborový systém dostupný přes datový typ embed.FS, který (ovšem pouze při správné inicializaci) programátorům nabízí tyto metody:
Metoda | Stručný popis metody |
---|---|
func (f FS) Open(name string) (fs.File, error) | otevření pojmenovaného souboru na virtuálním souborovém systému |
func (f FS) ReadDir(name string) ([]fs.DirEntry, error) | získání obsahu adresáře na virtuálním souborovém systému |
func (f FS) ReadFile(name string) ([]byte, error) | přečtení obsahu souboru na virtuálním souborovém systému |
Samotný virtuální souborový systém (resp. typ, který ho představuje) se deklaruje a naplní takto:
//go:embed lorem_ipsum.txt var f embed.FS
popř.:
//go:embed hello.txt //go:embed lorem_ipsum.txt var f embed.FS
nebo následovně:
//go:embed *.jpg //go:embed lorem_ipsum.txt var f embed.FS
8. Přístup ke vloženému souboru přes virtuální souborový systém
Vyzkoušejme si nyní, jak se k vloženým souborům přistupuje přes virtuální souborový systém. Strukturovaným komentářem //go:embed jméno souboru si necháme do výsledného spustitelného binárního souboru vložit obsah textového souboru pojmenovaného „ipsum.txt“. Následně k tomuto obsahu přistoupíme přes virtuální souborový systém s využitím metody FS.ReadFile. Tato metoda vrací řez bajtů, takže před tiskem provedeme převod na řetězec s využitím konverzního mechanismu string([]byte).
Celý zdrojový kód bude vypadat následovně:
package main import ( "embed" "fmt" "log" ) //go:embed lorem_ipsum.txt var f embed.FS func main() { data, err := f.ReadFile("lorem_ipsum.txt") if err != nil { log.Fatal(err) } // pouziti retezce fmt.Println(string(data)) }
Nyní provedeme překlad projektu:
$ go build access_string.go
A následně výsledný spustitelný soubor skutečně spustíme:
$ ./access_string
Na terminálu by se mělo zobrazit následujících šest řádků:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Zdrojový kód tohoto příkladu naleznete na adrese https://github.com/tisnik/go-root/blob/master/article_AB/access_string.go.
9. Vložení rastrových dat ve formátu JPEG, export obrázku v runtime
Jak jsme se již dozvěděli v předchozím textu, je možné do výsledného binárního souboru vkládat i poměrně rozsáhlá data. Může se například jednat o rastrové obrázky. Ukažme si tedy program, který ve svém spustitelném souboru obsahuje rastrový obrázek uložený ve formátu JPEG. Po spuštění tohoto programu je obrázek exportován na disk (ovšem stejně tak by mohl být poslán jako odpověď na HTTP dotaz atd.):
package main import ( "embed" "log" "os" ) //go:embed npe.jpg var f embed.FS func main() { data, err := f.ReadFile("npe.jpg") if err != nil { log.Fatal(err) } // open output file fout, err := os.Create("npe2.jpg") if err != nil { log.Fatal(err) } // close fo on exit and check for its returned error defer func() { err := fout.Close() if err != nil { log.Fatal(err) } }() fout.Write(data) }
Po spuštění tohoto programu by se měl v pracovním adresáři objevit nový soubor nazvaný „npe2.jpg“, který vypadá následovně:
Obrázek 1: Obsah souboru vytvořeného předchozím příkladem.
Zdrojový kód tohoto příkladu naleznete na adrese https://github.com/tisnik/go-root/blob/master/article_AB/access_binary.go.
10. Jak lze do virtuálního souborového systému přidat větší množství souborů?
Samozřejmě nám nic nebrání ve vložení většího množství souborů, které budou po překladu aplikace dostupné přes virtuální souborový systém. Jedna z nabízených možností spočívá v explicitním uvedení všech vkládaných souborů, přičemž každý soubor bude specifikován jedním strukturovaným komentářem //go:embed. V praxi to může vypadat následovně:
package main import ( "embed" "fmt" "log" ) //go:embed hello.txt //go:embed lorem_ipsum.txt var f embed.FS func main() { data, err := f.ReadFile("lorem_ipsum.txt") if err != nil { log.Fatal(err) } // pouziti retezce fmt.Println(string(data)) }
Zdrojový kód tohoto příkladu naleznete na adrese https://github.com/tisnik/go-root/blob/master/article_AB/more_strings1.go.
Překladač programovacího jazyka Go ovšem rozpoznává i žolíkové znaky (globs), takže nám nic nebrání v tom, abychom do virtuálního souborového systému vložili například všechny soubory s koncovkou „.txt“:
package main import ( "embed" "fmt" "log" ) //go:embed *.txt var f embed.FS func main() { data, err := f.ReadFile("lorem_ipsum.txt") if err != nil { log.Fatal(err) } // pouziti retezce fmt.Println(string(data)) }
Zdrojový kód tohoto příkladu naleznete na adrese https://github.com/tisnik/go-root/blob/master/article_AB/more_strings2.go.
11. Získání seznamu všech souborů vložených do vybraného virtuálního adresáře
Rozhraní, přes které se přistupuje k virtuálnímu souborovému systému, obsahuje i metodu nazvanou ReadDir, která slouží k přečtení obsahu vybraného virtuálního adresáře. V našem konkrétním příkladu vložíme do virtuálního souborového systému několik textových souborů (s využitím globu „*.txt“) a v runtime přečteme jejich seznam právě metodou ReadDir, které předáme aktuální adresář reprezentovaný tečkou:
package main import ( "embed" "fmt" "log" ) //go:embed *.txt var f embed.FS func main() { entries, err := f.ReadDir(".") if err != nil { log.Fatal(err) } for _, entry := range entries { fmt.Printf("%-25s %s\n", entry.Name(), entry.Type()) } }
Po překladu a spuštění tohoto příkladu by se na terminál měly vypsat následující řádky:
$ go run dir.go hello.txt ---------- lorem_ipsum.txt ----------
Zdrojový kód tohoto příkladu naleznete na adrese https://github.com/tisnik/go-root/blob/master/article_AB/dir.go.
12. Větší množství adresářů ve virtuálním souborovém systému
Ve virtuálním souborovém systému můžeme mít uloženou i adresářovou strukturu, což se provádí například následovně (opět zde tedy používáme globy):
//go:embed adresář1/* //go:embed adresář2/* var f embed.FS
Podívejme se nyní na konkrétní případ ve chvíli, kdy existuje dvojice adresářů a a b s vkládanými soubory:
a ├── A1.txt └── A2.txt b ├── B1.txt ├── B2.txt └── B3.txt
Všechny textové soubory z obou adresářů vložíme do výsledného spustitelného binárního souboru (v době překladu – compile time) a v čase běhu (runtime) si vypíšeme obsah kořenového virtuálního adresáře:
package main import ( "embed" "fmt" "log" ) //go:embed a/* //go:embed b/* var f embed.FS func main() { entries, err := f.ReadDir(".") if err != nil { log.Fatal(err) } for _, entry := range entries { fmt.Printf("%-25s %s\n", entry.Name(), entry.Type()) } }
Výsledek by měl v tomto případě vypadat následovně:
a d--------- b d---------
Zdrojový kód tohoto příkladu naleznete na adrese https://github.com/tisnik/go-root/blob/master/article_AB/dir2.go.
Samozřejmě nám nic nebrání v tom, abychom si vypsali obsah konkrétních virtuálních podadresářů:
package main import ( "embed" "fmt" "log" ) //go:embed a/* //go:embed b/* var f embed.FS func main() { entries, err := f.ReadDir("a") if err != nil { log.Fatal(err) } for _, entry := range entries { fmt.Printf("%-25s %s\n", entry.Name(), entry.Type()) } fmt.Println("*************************************") entries, err = f.ReadDir("b") if err != nil { log.Fatal(err) } for _, entry := range entries { fmt.Printf("%-25s %s\n", entry.Name(), entry.Type()) } }
Tentokrát budou výsledky pochopitelně odlišné:
A1.txt ---------- A2.txt ---------- ************************************* B1.txt ---------- B2.txt ---------- B3.txt ----------
Zdrojový kód tohoto příkladu naleznete na adrese https://github.com/tisnik/go-root/blob/master/article_AB/dir3.go.
13. Závěr
Balíček embed, který byl do ekosystému programovacího jazyka Go přidán ve verzi 1.16, může být pro některé typy aplikací velmi užitečný, protože zjednodušuje instalaci (která tak mnohdy vyžaduje pouze zkopírování jediného souboru) a navíc zmenšuje pravděpodobnost chyb, které s instalacemi či reinstalacemi souvisí – tedy chybějící soubory, soubory s jinými než očekávanými přístupovými právy, soubory ze starší verze aplikace, které nebyly při reinstalaci/upgradu přepsány atd. Nasazení takové aplikace je jednodušší i v „kontejnerizovaném IT světě“ atd. Přitom díky balíčku embed je vkládání dat do výsledných souborů nezávislé na použité architektuře ani na operačním systému.
14. Repositář s demonstračními příklady
Zdrojové kódy všech dnes použitých demonstračních příkladů naprogramovaných v jazyku Go byly uloženy do Git repositáře, který je dostupný na adrese https://github.com/tisnik/go-root. V případě, že nebudete chtít klonovat celý repositář, můžete namísto toho použít odkazy na jednotlivé demonstrační příklady, které naleznete v následující tabulce:
# | Příklad/soubor | Stručný popis | Cesta |
---|---|---|---|
1 | embed_string0.go | vložení jednořádkového řetězce do výsledného spustitelného souboru (nekorektní varianta) | https://github.com/tisnik/go-root/blob/master/article_AB/embed_string0.go |
2 | embed_string1.go | vložení jednořádkového řetězce do výsledného spustitelného souboru (nekorektní varianta) | https://github.com/tisnik/go-root/blob/master/article_AB/embed_string1.go |
3 | embed_string2.go | vložení jednořádkového řetězce do výsledného spustitelného souboru (korektní varianta) | https://github.com/tisnik/go-root/blob/master/article_AB/embed_string2.go |
4 | embed_string3.go | vložení víceřádkového řetězce do výsledného spustitelného souboru | https://github.com/tisnik/go-root/blob/master/article_AB/embed_string3.go |
5 | embed_binary1.go | vložení binárních dat do výsledného spustitelného souboru | https://github.com/tisnik/go-root/blob/master/article_AB/embed_binary1.go |
6 | embed_binary2.go | vložení binárních dat do výsledného spustitelného souboru | https://github.com/tisnik/go-root/blob/master/article_AB/embed_binary2.go |
7 | embed_other_data.go | pokus o vložení dat odlišného typu | https://github.com/tisnik/go-root/blob/master/article_AB/embed_other_data.go |
8 | access_string.go | přístup k původnímu řetězci přes virtuální souborový systém | https://github.com/tisnik/go-root/blob/master/article_AB/access_string.go |
9 | access_binary.go | přístup k binárním datům přes virtuální souborový systém | https://github.com/tisnik/go-root/blob/master/article_AB/access_binary.go |
10 | more_strings1.go | větší množství řetězců, přístup k nim přes virtuální souborový systém | https://github.com/tisnik/go-root/blob/master/article_AB/more_strings1.go |
11 | more_strings2.go | větší množství řetězců, přístup k nim přes virtuální souborový systém | https://github.com/tisnik/go-root/blob/master/article_AB/more_strings2.go |
12 | dir.go | výpis všech dat, která jsou vložena do spustitelného souboru a dostupná přes virtuální souborový systém | https://github.com/tisnik/go-root/blob/master/article_AB/dir.go |
13 | dir2.go | výpis všech dat v adresáři, která jsou vložena do spustitelného souboru a dostupná přes virtuální souborový systém | https://github.com/tisnik/go-root/blob/master/article_AB/dir2.go |
14 | dir3.go | výpis všech dat v adresářích, která jsou vložena do spustitelného souboru a dostupná přes virtuální souborový systém | https://github.com/tisnik/go-root/blob/master/article_AB/dir3.go |
15. Odkazy na Internetu
- Popis balíčku embed
https://pkg.go.dev/embed - How to Use go:embed in Go
https://blog.jetbrains.com/go/2021/06/09/how-to-use-go-embed-in-go-1–16/ - How to embed files into Go binaries
https://stackoverflow.com/questions/17796043/how-to-embed-files-into-go-binaries - Include binary file with GNU ld linker script
https://stackoverflow.com/questions/327609/include-binary-file-with-gnu-ld-linker-script - Executable and Linkable Format
https://en.wikipedia.org/wiki/Executable_and_Linkable_Format - Executable and Linkable Format 101 – Part 1 Sections and Segments
https://intezer.com/blog/research/executable-linkable-format-101-part1-sections-segments/ - appending data to an exe
https://stackoverflow.com/questions/5795446/appending-data-to-an-exe - Embedding resources in executable using GCC
https://stackoverflow.com/questions/4158900/embedding-resources-in-executable-using-gcc - Go 1.18 Release Notes
https://golang.org/doc/go1.18 - Go 1.17 Release Notes
https://golang.org/doc/go1.17 - Go 1.16 Release Notes
https://golang.org/doc/go1.16 - Go 1.15 Release Notes
https://golang.org/doc/go1.15 - Go 1.14 Release Notes
https://golang.org/doc/go1.14 - Go 1.13 Release Notes
https://golang.org/doc/go1.13 - Go 1.12 Release Notes
https://golang.org/doc/go1.12 - Go 1.11 Release Notes
https://golang.org/doc/go1.11 - Go 1.10 Release Notes
https://golang.org/doc/go1.10 - Go 1.9 Release Notes
https://golang.org/doc/go1.9 - Go 1.8 Release Notes
https://golang.org/doc/go1.8