什么时候使用嵌入?
When to use embed?
从 Go 1.16 开始,我们有 embed directive. It helps us embed an extra file (say, a .txt file) into the executable without having to supply that file additionally. (Reference, here).
我不太理解 'extra file' 的含义。所有不以 .go
结尾的文件都被解释为额外文件吗?有例外吗?
我想将二进制 protobuf 定义文件作为主二进制文件的一部分发送,以便我的代码可以读取它。这个文件会是一个额外的文件吗?或者它会是主二进制文件本身的一部分吗?
通常情况下 运行 Go 程序无法访问编译该程序的文件系统目录。
嵌入功能在构建时吸收包源代码树中的文件,并使这些文件在运行时可用。
包应该嵌入包源代码树中包需要在运行时访问的文件。
这是一个例子:包 foo 有源文件 foo.go。该包需要访问与 foo.go.
相同目录中的文件 abc.txt
如果 current working directory 是源代码代码目录,则包代码可以使用 os.Open 或任何调用 os.Open:
的方式访问该文件
f, err := os.Open("abc.txt")
if err != nil {
// handle error
}
defer f.Close()
// do something with f
此代码可能会失败。运行时的当前工作目录不一定与包源代码目录相同。它通常不是同一个目录。 运行 应用程序甚至可能无法使用包源目录。
在这种情况下,包应该嵌入文件以确保包可以访问文件的内容:
//go:embed abc.txt
var abc []byte
Embed 允许您将非 Go 文件视为源代码树的真实部分,而不是 运行 时间依赖项。您可以将嵌入式文件视为源代码的扩展,并且可以类似地对待它们(主要是文件的内容由您通常的源代码控制措施保证)。
对于普通文件,即使它们在理论上是应用程序的静态元素,它们通常仍然需要在每次程序 运行 时进行错误检查和验证,否则可能会出现无法解释的错误。使用嵌入式文件,一旦通过所有测试并部署应用程序,您就不必担心这一点。
嵌入式文件的主要问题是如果不重建程序就无法更改内容,并且(可能很大)文件大小会添加到二进制文件中。如果这没有造成问题,请继续。
任何时候你可以合理地嵌入一个文件而不是在 运行 时加载它,这样做可能是可取的,因为它使程序部署更简单。
为了补充其他答案,嵌入指令的一个缺点是您不能使用它来嵌入 OS 级资源,例如 Windows application manifests 或显示在旁边的图标Windows 资源管理器中的二进制文件;至少不会以 OS 会接受的方式。
在 Windows 上,您可以使用 goversioninfo 之类的东西来嵌入这些内容。
从 Go 1.16 开始,我们有 embed directive. It helps us embed an extra file (say, a .txt file) into the executable without having to supply that file additionally. (Reference, here).
我不太理解 'extra file' 的含义。所有不以 .go
结尾的文件都被解释为额外文件吗?有例外吗?
我想将二进制 protobuf 定义文件作为主二进制文件的一部分发送,以便我的代码可以读取它。这个文件会是一个额外的文件吗?或者它会是主二进制文件本身的一部分吗?
通常情况下 运行 Go 程序无法访问编译该程序的文件系统目录。
嵌入功能在构建时吸收包源代码树中的文件,并使这些文件在运行时可用。
包应该嵌入包源代码树中包需要在运行时访问的文件。
这是一个例子:包 foo 有源文件 foo.go。该包需要访问与 foo.go.
相同目录中的文件 abc.txt如果 current working directory 是源代码代码目录,则包代码可以使用 os.Open 或任何调用 os.Open:
的方式访问该文件 f, err := os.Open("abc.txt")
if err != nil {
// handle error
}
defer f.Close()
// do something with f
此代码可能会失败。运行时的当前工作目录不一定与包源代码目录相同。它通常不是同一个目录。 运行 应用程序甚至可能无法使用包源目录。
在这种情况下,包应该嵌入文件以确保包可以访问文件的内容:
//go:embed abc.txt
var abc []byte
Embed 允许您将非 Go 文件视为源代码树的真实部分,而不是 运行 时间依赖项。您可以将嵌入式文件视为源代码的扩展,并且可以类似地对待它们(主要是文件的内容由您通常的源代码控制措施保证)。
对于普通文件,即使它们在理论上是应用程序的静态元素,它们通常仍然需要在每次程序 运行 时进行错误检查和验证,否则可能会出现无法解释的错误。使用嵌入式文件,一旦通过所有测试并部署应用程序,您就不必担心这一点。
嵌入式文件的主要问题是如果不重建程序就无法更改内容,并且(可能很大)文件大小会添加到二进制文件中。如果这没有造成问题,请继续。
任何时候你可以合理地嵌入一个文件而不是在 运行 时加载它,这样做可能是可取的,因为它使程序部署更简单。
为了补充其他答案,嵌入指令的一个缺点是您不能使用它来嵌入 OS 级资源,例如 Windows application manifests 或显示在旁边的图标Windows 资源管理器中的二进制文件;至少不会以 OS 会接受的方式。
在 Windows 上,您可以使用 goversioninfo 之类的东西来嵌入这些内容。