diff options
| author | Shulhan <ms@kilabit.info> | 2024-12-15 13:31:07 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2024-12-15 13:31:07 +0700 |
| commit | 2c0c677e558e54854dd4189858895e9eaf063455 (patch) | |
| tree | 92b3602fb1437faed9eb85ed71e9d529a6454677 | |
| parent | db651010fd746282748c9fde610e0f0d9c53380e (diff) | |
| download | kilabit.info-2c0c677e558e54854dd4189858895e9eaf063455.tar.xz | |
journal/2024: write down "Memfs vs go:embed"
This article compare the feature of go:embed with the memfs
package from my pakakeh.go module.
| -rw-r--r-- | _content/journal/2024/index.adoc | 4 | ||||
| -rw-r--r-- | _content/journal/2024/memfs_vs_goembed/index.adoc | 122 |
2 files changed, 126 insertions, 0 deletions
diff --git a/_content/journal/2024/index.adoc b/_content/journal/2024/index.adoc index be0b314..e38dc65 100644 --- a/_content/journal/2024/index.adoc +++ b/_content/journal/2024/index.adoc @@ -1,6 +1,10 @@ === 2024 +link:/journal/2024/memfs_vs_goembed/[Memfs vs go:embed^]. +This article compare the feature of go:embed with the memfs package +from my pakakeh.go module. + link:/journal/2024/two_types_of_leader/[Two types of leader^]. link:/journal/2024/bad_coding_practices/[Bad coding practices^]. diff --git a/_content/journal/2024/memfs_vs_goembed/index.adoc b/_content/journal/2024/memfs_vs_goembed/index.adoc new file mode 100644 index 0000000..5118da3 --- /dev/null +++ b/_content/journal/2024/memfs_vs_goembed/index.adoc @@ -0,0 +1,122 @@ += Memfs vs go:embed +:sectanchors: +:sectlinks: +:toc: + +This article compare the feature of +https://pkg.go.dev/embed["go:embed"^] +with the +https://pkg.go.dev/git.sr.ht/~shulhan/pakakeh.go/lib/memfs[memfs +package^] from my +https://pkg.go.dev/git.sr.ht/~shulhan/pakakeh.go[pakakeh.go^] +module. + +The memfs package created on +https://git.sr.ht/~shulhan/pakakeh.go/commit/05b02c7b[November 2018^], +based on my experiences maintains the fork of +https://github.com/shuLhan/go-bindata[go-bindata^] +project. +The "go:embed" directive introduced into Go tools since +https://go.dev/doc/go1.16[Go version 1.16^], +released February 2021, three years after the first release of memfs +package. + +Given the following directory structure, + +---- +module-root/ ++-- cmd/prog/main.go ++-- _content/ + +-- index.adoc + +-- index.html + +-- static/ + +-- index.png + +-- index.png +---- + +We want to embed the directory "_content" but only html files and all +files inside the "static/" directory. + + +**Cons #1: The "go:embed" only works if files or directory to be +embedded is in the same parent directory.** + +The "go:embed" directive define in "cmd/prog/main.go" will not able to +embed files in their parent. +The following code will not compile, + +---- +//go:embed ../../_content/*.html +//go:embed ../../_content/static +var contentFS embed.FS + +// go build output, +// pattern ../../_content/*.html: invalid pattern syntax +---- + +If we remove the ".." and execute "go build" from module-root, it will +still not compile, + +---- +//go:embed _content/*.html +//go:embed _content/static +var contentFS embed.FS + +// go build or run output, +// pattern _content/*.html: no matching files found +---- + +The only solution is to create and export the variable "ContentFS" in +the same parent directory as "_content". + +The memfs package does not have this limitation. +As long as the Go commands are executed from the module-root +directory, you can define the variable in any packages. + + +**Cons #2: Accessing the embedded file require the original path.** + +Let say we have embeded the "_content" directory using the following +syntax, + +---- +//go:embed _content/*.html +//go:embed _content/static +var ContentFS embed.FS +---- + +To access the file "index.html" you need to pass their full path, in +this case "_content/index.html". +The path "_content" leaked to the parent FS and not portable. + +In the memfs package, the content of [Options.Root] directory can be +accessed with "/", so it would become "/index.html". +This design allow flexibility and consistency between modules and +packages. +If an external, third-party package accept the MemFS instance and the +first thing they do is to read all contents of "/" directory, the +caller can embed any path without have specific prefix or name. + +Case example, when we embed SQL files for migration under directory +"db/migration" using the "go:embed" directive, + +---- +//go:embed db/migration/*.sql +var DBMigrationFS embed.FS +---- + +and then call the Migrate function, it cannot found any ".sql" files +inside the "/" directory because the files is stored under +"db/migration/" prefix. + + +**Cons #3: No development mode.** + +Let say we run our server that served the content from FS instance. +If we changes the html files, and refresh the browser, the new content +will not reflected because it serve the content on the first embed. + +The memfs package have [Options.TryDirect] that bypass file in memory +and read directly to the file system. +This allow quick development when changes only template or non-code +files. |
