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\n\nvar %s = [...]byte{\n"
trailer = "}\n"
)
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\n", *outFile, err)
os.Exit(1)
}
}
inF, err := os.Open(flag.Args()[0])
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot open %s: %v\n", 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,\n", buf[n-1])
}
out.WriteString(trailer)
out.Flush()
if err != io.EOF {
fmt.Fprintf(os.Stderr, "An error occured while reading from %s: %v\n", flag.Args()[0], err)
os.Exit(1)
}
}
¹ This is now supported. You can use the embed mechanism as explained in my other answer.