How to embed files into Golang binaries?

后端 未结 7 1332
遇见更好的自我
遇见更好的自我 2020-12-12 16:58

I have some text file that I read from my Go program. I\'d like to ship a single executable, without supplying that text file additionally. How do I embed it into compilatio

相关标签:
7条回答
  • 2020-12-12 17:57

    Since Go 1.4, you can use go generate if you need more flexibility.

    If you have more than one text file or the text file may change you might not want to hardcode the text file but include it at compile time.

    If you have the following files:

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

    And want to have access to the contents of all .txt files in main.go, you can include a special comment containing a go generate command.

    main.go

    package main
    
    import "fmt"
    
    //go:generate go run scripts/includetxt.go
    
    func main() {
        fmt.Println(a)
        fmt.Println(b)
    }
    

    The go generate command will run the script after go:generate. In this case it runs a go script which reads all text files and outputs them as string literals into a new file. I skipped the error handling for shorter code.

    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"))
    }
    

    To compile all .txt files into your exectutable:

    $ go generate
    $ go build -o main
    

    Now your directory structure will look like:

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

    Where textfiles.go was generated by go generate and script/includetxt.go

    textfiles.go

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

    And running main gives

    $ ./main
    hello
    world
    

    This will work fine as long as you're encoding UTF8 encoded files. If you want to encode other files you have the full power of the go language (or any other tool) to do so. I used this technique to hex encode png:s into a single executable. That requires a minor change to includetxt.go.

    0 讨论(0)
提交回复
热议问题