If you have any questions or suggestions, please contact us in time. My official account is “Brain fried Fish”, GitHub address: github.com/eddycjy.

Hello, I’m fried fish.

In the past, many students who came to Go from other languages would ask, or step into a pit. It is assumed that the binaries packaged with the Go language will contain co-compilation and packaging of configuration files.

As a result, binaries are often shuffled around so that the application can’t run. The static file resource cannot be read.

When static resource compilation cannot be packaged into a binary file, there are usually two solutions:

  • The first is to identify such static resources and whether they need to follow the program.
  • The second is to consider packaging it into a binary file.

In the second case, Go was not previously supported and people resorted to fancy open source libraries such as Go-bindata/Go-bindata.

But since Go1.16, the Go language itself has officially supported this feature, which we’ll quickly learn about in this article today.

The basic use

Demo code:

import _ "embed"

//go:embed hello.txt
var s string

func main() {
	print(s)
}
Copy the code

We first created a hello. TXT file in the corresponding directory, and wrote the text content “eat fried fish”.

The core //go: Embed Hello.txt annotation is prepared in the code. The format of the annotations is simple: the Go: Embed instruction statement, plus the address of the content read, can support relative and absolute paths.

Output result:

Eat fishCopy the code

The contents of the static file are automatically assigned to the variable S and printed successfully in the main function.

For other base types, Go Embed is also supported:

//go:embed hello.txt
var s string

//go:embed hello.txt
var b []byte

//go:embed hello.txt
var f embed.FS

func main() {
	print(s)
	print(string(b))

	data, _ := f.ReadFile("hello.txt")
	print(string(data))
}
Copy the code

Output result:

Eat fried fish eat fried fish eat fried fishCopy the code

We made multiple embed annotation declarations simultaneously in a code file.

And for string, slice, byte, FS and other types of packaging, also do not need too much processing, very convenient.

Expand the usage

In addition to basic usage, the Embed itself also supports multiple morphs on instructions:

//go:embed hello1.txt hello2.txt
var f embed.FS

func main() {
	data1, _ := f.ReadFile("hello1.txt")
	fmt.Println(string(data1))

	data2, _ := f.ReadFile("hello2.txt")
	fmt.Println(string(data2))
}
Copy the code

The go: Embed annotation can be read from multiple files at a time, and can also be read from multiple lines of a variable:

//go:embed hello1.txt 
//go:embed hello2.txt
var f embed.FS
Copy the code

You can also specify the directory helloWorld in the annotation and read the file accordingly:

//go:embed helloworld
var f embed.FS

func main() {
	data1, _ := f.ReadFile("helloworld/hello1.txt")
	fmt.Println(string(data1))

	data2, _ := f.ReadFile("helloworld/hello2.txt")
	fmt.Println(string(data2))
}
Copy the code

At the same time, since it can support directory reading, it can also support greedy mode matching:

//go:embed helloworld/*
var f embed.FS
Copy the code

For those of you who may have noticed that embed.FS can also tune all kinds of file system interfaces. The essence of embed.

Read-only property

In the FS provided by Embed, we can find both open and read-only methods:

type FS
    func (f FS) Open(name string) (fs.File, error)
    func (f FS) ReadDir(name string) ([]fs.DirEntry, error)
    func (f FS) ReadFile(name string) ([]byte, error)
Copy the code

It is also clear from this that embed packages into the binary can only be read, not changed.

More abstractly, embed content is determined at compile time and cannot be modified at run time to ensure consistency.

conclusion

With the EMBED feature officially provided by Go1.16, it is possible to embed natively supported static resource files. As a whole:

  • In terms of functionality: the ability to embed static resources in binaries and open and read related packaged static files at run time.
  • On security: The embedding is compiled at compile time and does not support modification at run time.
  • In use:
    • Support single file reading:go:embed hello.txt.
    • Support multiple file reading:go:embed hello1.txt,go:embed hello2.txt.
    • Support directory reading:go:embed helloworld.
    • Support greedy matching:go:embed helloworld/*.

In general, the Go1.16 Embed feature nicely fills a native void in the Go language for packaging static file resources. It also shows that Go officials are constantly incorporating good ideas and experiences from the community.

My official account

Share Go language, micro service architecture and strange system design, welcome to pay attention to my public number and I exchange and communication.

The best relationship is mutual achievement. Your praise is the biggest motivation for the creation of fried fish. Thank you for your support.