Osadzanie pliku tekstowego w skompilowanym pliku wykonywalnym

Mam jakiś plik tekstowy, który przeczytałem z mojego programu Go. Chciałbym wysłać pojedynczy plik wykonywalny, nie dostarczając dodatkowo tego pliku tekstowego. Jak osadzić go w kompilacji?

Pytanie dotyczy zarówno Windowsa jak i Linuksa.

Author: Flimzy, 2013-07-22

4 answers

Użyj go-bindata . Z README:

To narzędzie konwertuje dowolny plik do zarządzalnego kodu źródłowego Go. Przydatne dla osadzanie danych binarnych w programie go. Dane Pliku są opcjonalne gzip skompresowany przed konwersją do surowego kawałka bajtów.

 26
Author: joshlf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-22 21:21:05

Od wersji Go 1.4, możesz użyć go generate, jeśli potrzebujesz większej elastyczności.

Jeśli masz więcej niż jeden plik tekstowy lub plik tekstowy może się zmienić, możesz nie chcieć kodować na twardo pliku tekstowego, ale dołączyć go podczas kompilacji.

Jeśli masz następujące pliki:

main.go
scripts/includetxt.go
a.txt
b.txt

I chcesz mieć dostęp do zawartości wszystkich .pliki txt w main.go, możesz dołączyć specjalny komentarz zawierający polecenie go generate.

Main.go

package main

import "fmt"

//go:generate go run scripts/includetxt.go

func main() {
    fmt.Println(a)
    fmt.Println(b)
}

The go generate polecenie uruchomi skrypt po go:generate. W tym przypadku uruchamia skrypt go, który odczytuje wszystkie pliki tekstowe i wysyła je jako literały łańcuchowe do nowego pliku. Pominąłem obsługę błędów dla krótszego kodu.

Script / includetxt.go

package main

import (
    "io"
    "io/ioutil"
    "os"
    "strings"
)

// Reads all .txt files in the current folder
// and encodes them as strings literals in textfiles.go
func main() {
    fs, _ := ioutil.ReadDir(".")
    out, _ := os.Create("textfiles.go")
    out.Write([]byte("package main \n\nconst (\n"))
    for _, f := range fs {
        if strings.HasSuffix(f.Name(), ".txt") {
            out.Write([]byte(strings.TrimSuffix(f.Name(), ".txt") + " = `"))
            f, _ := os.Open(f.Name())
            io.Copy(out, f)
            out.Write([]byte("`\n"))
        }
    }
    out.Write([]byte(")\n"))
}

Aby skompilować wszystkie .pliki txt do pliku wykonywalnego:

$ go generate
$ go build -o main

Teraz twoja struktura katalogów będzie wyglądać następująco:

main.go
main
scripts/includetxt.go
textfiles.go
a.txt
b.txt

Gdzie textfiles.go został wygenerowany przez go generate i script/includetxt.go

Textfiles.go

package main 

const (
a = `hello`
b = `world`
)

I uruchamianie main daje

$ ./main
hello
world

To będzie działać tak długo, jak kodujesz pliki zakodowane w UTF8. Jeśli chcesz kodować inne pliki, masz pełną moc języka go (lub innego narzędzia), aby to zrobić. Użyłem tej techniki do hex kodowania png: s do jednego pliku wykonywalnego. Wymaga to drobnej zmiany w includetxt.idź.

 36
Author: Johan Wikström,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-07 19:52:00

Możesz użyć string literal Aby zdefiniować tekst jako stałą lub zmienną. Literały łańcuchów są definiowane przez zamknięcie łańcucha cudzysłowami. np. "string".

Na przykład:

package main

import "fmt"

func main() {
    const text = `
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit  
amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante 
hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet 
vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut 
libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, 
consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a 
semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. 
Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut 
convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis 
quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis 
parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae 
nisi at sem facilisis semper ac in est.
`

    fmt.Println(text)
}
 5
Author: Intermernet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-23 05:21:20

Użyłem prostej funkcji do odczytu zewnętrznego szablonu w uruchomieniu go generate i wygenerowania z niego kodu Go. Zostanie wygenerowana funkcja zwracająca szablon jako ciąg znaków. Następnie można przetworzyć zwracany ciąg szablonu za pomocą tpl, err := template.New("myname").Parse(mynameTemplate())

Umieściłem ten kod na GitHubie. Możesz spróbować https://github.com/wlbr/templify

Bardzo proste, ale działa dla mnie całkiem dobrze.

 2
Author: wlbr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-28 01:13:23