Is it possible to include an external file as a string constant in go?

huangapple go评论88阅读模式
英文:

Is it possible to include an external file as a string constant in go?

问题

我一直希望在C++中能够像这样做:

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

显然这是行不通的,在C++中没有办法这样做。但是在Go语言中是可能的,例如:

const fragmentShader string = `
<在编译时插入shader.frag的内容>
`

动机应该是显而易见的!

英文:

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

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

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 = `
&lt;insert contents of shader.frag at compile-time&gt;
`

The motivation should be obvious!

答案1

得分: 3

不是真的,但是这里有几个选项:

  1. 只需将文件的内容放入你的源代码中:

     const fragmentShaderFile = `shader.frag的内容`
    
  2. 你可以使用这个工具嵌入资源:https://github.com/jteeuwen/go-bindata,但是每次文件更改后都需要重新嵌入它。(可以将其自动化为git的pre-commit hook

英文:

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)

答案2

得分: 3

这是不可能在纯Go中实现的。但是你可以编写一个程序,从文件中读取内容并创建一个Go文件,例如:

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

现在已经支持这个功能了。你可以使用embed机制,如我在另一个回答中所解释的。

英文:

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

package main
import &quot;flag&quot;
import &quot;os&quot;
import &quot;fmt&quot;
import &quot;bufio&quot;
import &quot;io&quot;
var (
packageName = flag.String(&quot;p&quot;, &quot;main&quot;, &quot;package name&quot;)
outFile     = flag.String(&quot;o&quot;, &quot;-&quot;, &quot;output file. Defaults to stdout&quot;)
varName     = flag.String(&quot;v&quot;, &quot;file&quot;, &quot;variable name&quot;)
)
const (
header  = &quot;package %s\n\nvar %s = [...]byte{\n&quot;
trailer = &quot;}\n&quot;
)
func main() {
flag.Parse()
if len(flag.Args()) != 1 {
fmt.Fprintln(os.Stderr, &quot;Please provide exactly one file name&quot;)
os.Exit(1)
}
var inF, outF *os.File
if *outFile == &quot;-&quot; {
outF = os.Stdout
} else {
var err error
outF, err = os.Create(*outFile)
if err != nil {
fmt.Fprintf(os.Stderr, &quot;Cannot create %s: %v\n&quot;, *outFile, err)
os.Exit(1)
}
}
inF, err := os.Open(flag.Args()[0])
if err != nil {
fmt.Fprintf(os.Stderr, &quot;Cannot open %s: %v\n&quot;, 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 &gt; 0; n, err = io.ReadFull(in, buf) {
out.WriteRune(&#39;\t&#39;)
for i := 0; i &lt; n-1; i++ {
fmt.Fprintf(out, &quot;%#02x, &quot;, buf[i])
}
fmt.Fprintf(out, &quot;%#02x,\n&quot;, buf[n-1])
}
out.WriteString(trailer)
out.Flush()
if err != io.EOF {
fmt.Fprintf(os.Stderr, &quot;An error occured while reading from %s: %v\n&quot;, flag.Args()[0], err)
os.Exit(1)
}
}

¹&emsp;This is now supported. You can use the embed mechanism as explained in my other answer.

答案3

得分: 0

这些天,你应该使用embed机制。对于你的用例,可以这样做:

import _ "embed"

//go:embed shader.frag
var fragmentShader string
英文:

These days, you should probably use the embed mechanism. For your use case, that would be like

import _ &quot;embed&quot;
//go:embed shader.frag
var fragmentShader string

huangapple
  • 本文由 发表于 2013年12月28日 22:00:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/20815414.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定