是否可以在go中包含一个外部文件作为字符串常量?

I always wished it was possible to do something like this in C++:

const std::string fragmentShader = "
#include "shader.frag"
";

Obviously that doesn't work, and there is no way to do it in C++. But it is possible in go? i.e.

const fragmentShader string = `
<insert contents of shader.frag at compile-time>
`

The motivation should be obvious!

This is not possible in pure Go. You could however write a program that reads a file and creates a Go file from it, such as this:

package main

import "flag"
import "os"
import "fmt"
import "bufio"
import "io"

var (
    packageName = flag.String("p", "main", "package name")
    outFile     = flag.String("o", "-", "output file. Defaults to stdout")
    varName     = flag.String("v", "file", "variable name")
)

const (
    header  = "package %s

var %s = [...]byte{
"
    trailer = "}
"
)

func main() {

    flag.Parse()

    if len(flag.Args()) != 1 {
        fmt.Fprintln(os.Stderr, "Please provide exactly one file name")
        os.Exit(1)
    }

    var inF, outF *os.File

    if *outFile == "-" {
        outF = os.Stdout
    } else {
        var err error
        outF, err = os.Create(*outFile)
        if err != nil {
            fmt.Fprintf(os.Stderr, "Cannot create %s: %v
", *outFile, err)
            os.Exit(1)
        }
    }

    inF, err := os.Open(flag.Args()[0])
    if err != nil {
        fmt.Fprintf(os.Stderr, "Cannot open %s: %v
", flag.Args()[0], err)
        os.Exit(1)
    }

    in, out := bufio.NewReader(inF), bufio.NewWriter(outF)

    fmt.Fprintf(out, header, *packageName, *varName)

    buf := make([]byte, 16)

    var n int

    for n, err = io.ReadFull(in, buf); n > 0; n, err = io.ReadFull(in, buf) {
        out.WriteRune('\t')

        for i := 0; i < n-1; i++ {
            fmt.Fprintf(out, "%#02x, ", buf[i])
        }

        fmt.Fprintf(out, "%#02x,
", buf[n-1])
    }

    out.WriteString(trailer)

    out.Flush()

    if err != io.EOF {
        fmt.Fprintf(os.Stderr, "An error occured while reading from %s: %v
", flag.Args()[0], err)
        os.Exit(1)
    }
}

Not really, but here are a couple options:

  1. Just take the contents of the file and put them in your source code:

    const fragmentShaderFile = `contents of shader.frag`
    
  2. You can embed assets with this tool: https://github.com/jteeuwen/go-bindata, but you'll have to re-embed the file anytime it's changed. (One could automate this as a git pre-commit hook though)