Introduction to Embed Packages
Since Golang released version 1.16 there is a new feature called Embed. This embed package is a feature that makes it easier to open the contents of a file at compile time, automatically inserting the contents of the file into the variables that we have defined. For more details, you can see here.
How to Embed Files
When we want to embed a file into a variable, we can import the embed
package first, then we can add the comment //go:embed
followed by the file above the variable we are aiming for. The target variable will automatically contain the contents of the file we want when the Golang code is compiled. The target variable cannot be stored in a function.
Embed File to String
Entering the contents of a file into a variable (Embed) will automatically read the contents of the file as text and insert it into the variable.
Before we carry out the implementation, we try to create a folder first with the name learn-golang-embed
then also initialize go mod
with the command below
go mod init github.com/santekno/learn-golang-embed
After that we create a txt
file called version.txt
which we will later read by the embed program which we will try this time with the version contents, for example like this
v1.0.0
After that, we try to create a main.go
file and fill the main file with the program code below.
package main
import (
_ "embed"
"fmt"
)
//go:embed version.txt
var version string
func main() {
fmt.Println(version)
}
So, when we run it it will produce this.
➜ learn-golang-embed git:(main) ✗ go run main.go
v1.0.0
Embed Files into Bytes
Now we try to embed it into another type, namely []byte. Apart from the string data type, this embed can also be used in several types. This is very suitable if we want to embed files in binary form, for example images and others.
package main
import (
_ "embed"
"io/fs"
"os"
)
//go:embed logo.png
var logo []byte
func main() {
err := os.WriteFile("logo_new.png", logo, fs.ModePerm)
if err != nil {
panic(err)
}
}
When run it will create a new file with the name logo_new.png
with the same image as logo.png
Embed Multiple Files
Usually we also want to embed several files at once for our needs. We can do this by using the embed package by adding //go:embed
comments on more than one line and we can use the variable data type embed.FS
.
We create a file
folder with 3 files with the names a.txt
, b.txt
and c.txt
with the contents of each file AAA
, BBB
, CCC
or just adjust it to your friend’s wishes -Friend.
package main
import (
"embed"
_ "embed"
"fmt"
)
//go:embed files/a.txt
//go:embed files/b.txt
//go:embed files/c.txt
var files embed.FS
func main() {
a, _ := files.ReadFile("files/a.txt")
fmt.Println(string(a))
b, _ := files.ReadFile("files/b.txt")
fmt.Println(string(b))
c, _ := files.ReadFile("files/c.txt")
fmt.Println(string(c))
}
Path Matcher
Apart from manually reading one file at a time, we can also use a patch matcher to read multiple files that we want. We can implement this when we have a need to open files by having a pattern of the types of files we read. How to? We need to use path matcher
in the path.Match
function package
package main
import (
"embed"
_ "embed"
"fmt"
)
//go:embed files/*.txt
var path embed.FS
func main() {
dir, _ := path.ReadDir("files")
for _, entry := range dir {
if !entry.IsDir() {
fmt.Println(entry.Name())
content, _ := path.ReadFile("files/" + entry.Name())
fmt.Println("Content: ", string(content))
}
}
}
Ketika kita jalankan akan menghasilkan seperti ini.
➜ learn-golang-embed git:(main) ✗ go run main.go
a.txt
Content: AAA
b.txt
Content: BBB
c.txt
Content: CCC
Compile Embed Results
We need to know that the results of the embed carried out by the embed package are permanent and the file data that is read will be saved into the Golang binary file that we have created. So this embed
package does not read external files in real time so that if we have compiled it and have a Golang binary file, then we no longer need the external file and if we change the external file then the contents of the variables will not change again, so we need to re-compile.