programming

Introduction and Implementation of Golang Embed

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.

comments powered by Disqus