Synopsis
I wanted to run an application in Go that returned plain HTML,
I decided to use Cloudflare Workers, which can convert it to Wasm and deploy it.
I recommend syumai/workers's template for deploying Go applications to Cloudflare Workers.
syumai/workers: Go package to run an HTTP server on Cloudflare Workers.
Go text/template
First, let's build using text/template in a straightforward manner.
❯ ls -lh . /build total 15656 -rwxr-xr-x 1 ergofriend staff 7.6M 8 8 20:12 app.wasm -rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:12 shim.mjs -rw-r--r-- 1 ergofriend staff 16K 8 8 20:12 wasm_exec.js -rw-r--r-- 1 ergofriend staff 160B 8 8 20:12 worker.mjs
It was almost 8 MB.
https://developers.cloudflare.com/workers/platform/limits/#account-plan-limits
Cloudflare Workers has worker size limits depending on the plan.
The free slot is 1MB, and the paid slot ($5~) is 10MB.
Even with the final limit based on size after compression, it will be tough to fit into the free quota starting at 8MB.
TinyGo text/template
So I decided to switch to TinyGo, which is supposed to be for WebAssembly (Wasm).
After building, the size is about 0.75 MB, which seems to fit into the free frame.
❯ ls -lh . /build total 1160 -rwxr-xr-x 1 ergofriend staff 556K 8 8 20:23 app.wasm -rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:23 shim.mjs -rw-r--r-- 1 ergofriend staff 15K 8 8 20:23 wasm_exec.js -rw-r--r-- 1 ergofriend staff 160B 8 8 20:23 worker.mjs
Oops!
But here is where tragedy strikes.
When I try to access the built application, I get an error.
[wrangler:inf] GET / 200 OK (35ms) ✘ [ERROR] Uncaught (in response) RuntimeError: unreachable at main.runtime._panic (wasm://wasm/main-0022bc46:wasm-function[35]:0x2b4a) at main.(*text/template.state).evalField (wasm://wasm/main-0022bc46:wasm-function[540]:0x6c5f4) at main.(*text/template.state).evalFieldChain (wasm://wasm/main-0022bc46:wasm-function[531]:0x697fe) at main.(*text/template.state).evalFieldNode (wasm://wasm/main-0022bc46:wasm-function[530]:0x6959a) at main.(*text/template.state).evalPipeline (wasm://wasm/main-0022bc46:wasm-function[535]:0x6a1d2) at main.(*text/template.state).walk (wasm://wasm/main-0022bc46:wasm-function[569]:0x72cdd) at main.(*text/template.state).walk (wasm://wasm/main-0022bc46:wasm-function[569]:0x730b0) at main.main (wasm://wasm/main-0022bc46:wasm-function[261]:0x2ac52) at main.(net/http.HandlerFunc).ServeHTTP (wasm://wasm/main-0022bc46:wasm-function[463]:0x5973a) at main.interface:{ServeHTTP:func:{named:net/http.ResponseWriter,pointer:named:net/http.Request}{}}.ServeHTTP$invoke (wasm://wasm/main-0022bc46:wasm-function[459]:0x56f72) panic: unimplemented: (reflect.Value).MethodByName()
The method MethodByName, which is called when a template variable is passed in template.ExecuteTemplate(), is not yet It seems to be unimplemented.
Since TinyGo is a subset of the original, there are many unsupported features,
I found that text/template was calling unsupported methods.
https://github.com/tinygo-org/tinygo/blob/1154212c15e6e97048e122068730dab5a1a9427f/src/reflect/type.go#L1086-L1088
Now, I would like to be cool and say p-r for TinyGo, but this time I'm going to look for a quick alternative.
TEMPL
So I was looking for another template engine to replace text/template and came across templ.
a-h
/
templ
A language for writing HTML user interfaces in Go.
An HTML templating language for Go that has great developer tooling.
Documentation
See user documentation at https://templ.guide
Tasks
build
Build a local version.
❯ ls -lh . /build
total 15656
-rwxr-xr-x 1 ergofriend staff 7.6M 8 8 20:12 app.wasm
-rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:12 shim.mjs
-rw-r--r-- 1 ergofriend staff 16K 8 8 20:12 wasm_exec.js
-rw-r--r-- 1 ergofriend staff 160B 8 8 20:12 worker.mjs
nix-update-gomod2nix
❯ ls -lh . /build
total 15656
-rwxr-xr-x 1 ergofriend staff 7.6M 8 8 20:12 app.wasm
-rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:12 shim.mjs
-rw-r--r-- 1 ergofriend staff 16K 8 8 20:12 wasm_exec.js
-rw-r--r-- 1 ergofriend staff 160B 8 8 20:12 worker.mjs
install-snapshot
Build and install current version.
❯ ls -lh . /build
total 1160
-rwxr-xr-x 1 ergofriend staff 556K 8 8 20:23 app.wasm
-rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:23 shim.mjs
-rw-r--r-- 1 ergofriend staff 15K 8 8 20:23 wasm_exec.js
-rw-r--r-- 1 ergofriend staff 160B 8 8 20:23 worker.mjs
build-snapshot
Use goreleaser to build the command line binary using goreleaser.
❯ ls -lh . /build
total 15656
-rwxr-xr-x 1 ergofriend staff 7.6M 8 8 20:12 app.wasm
-rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:12 shim.mjs
-rw-r--r-- 1 ergofriend staff 16K 8 8 20:12 wasm_exec.js
-rw-r--r-- 1 ergofriend staff 160B 8 8 20:12 worker.mjs
generate
Run templ generate using local version.
❯ ls -lh . /build
total 1160
-rwxr-xr-x 1 ergofriend staff 556K 8 8 20:23 app.wasm
-rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:23 shim.mjs
-rw-r--r-- 1 ergofriend staff 15K 8 8 20:23 wasm_exec.js
-rw-r--r-- 1 ergofriend staff 160B 8 8 20:23 worker.mjs
test
Run Go tests.
❯ ls -lh . /build
total 15656
-rwxr-xr-x 1 ergofriend staff 7.6M 8 8 20:12 app.wasm
-rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:12 shim.mjs
-rw-r--r-- 1 ergofriend staff 16K 8 8 20:12 wasm_exec.js
-rw-r--r-- 1 ergofriend staff 160B 8 8 20:12 worker.mjs
test-short
Run Go tests.
❯ ls -lh . /build
total 1160
-rwxr-xr-x 1 ergofriend staff 556K 8 8 20:23 app.wasm
-rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:23 shim.mjs
-rw-r--r-- 1 ergofriend staff 15K 8 8 20:23 wasm_exec.js
-rw-r--r-- 1 ergofriend staff 160B 8 8 20:23 worker.mjs
test-cover
Run…
Features
Here is a summary of TEMPL.
Own DSL
It is not difficult to write a unique program, but it can be written like templ ≈ Go JSX.
❯ ls -lh . /build total 15656 -rwxr-xr-x 1 ergofriend staff 7.6M 8 8 20:12 app.wasm -rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:12 shim.mjs -rw-r--r-- 1 ergofriend staff 16K 8 8 20:12 wasm_exec.js -rw-r--r-- 1 ergofriend staff 160B 8 8 20:12 worker.mjs
It looks like a very familiar writing style.
❯ ls -lh . /build total 1160 -rwxr-xr-x 1 ergofriend staff 556K 8 8 20:23 app.wasm -rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:23 shim.mjs -rw-r--r-- 1 ergofriend staff 15K 8 8 20:23 wasm_exec.js -rw-r--r-- 1 ergofriend staff 160B 8 8 20:23 worker.mjs
When you use it, you call Go functions generated from the DSL by templ generate on a component-by-component basis.
[wrangler:inf] GET / 200 OK (35ms) ✘ [ERROR] Uncaught (in response) RuntimeError: unreachable at main.runtime._panic (wasm://wasm/main-0022bc46:wasm-function[35]:0x2b4a) at main.(*text/template.state).evalField (wasm://wasm/main-0022bc46:wasm-function[540]:0x6c5f4) at main.(*text/template.state).evalFieldChain (wasm://wasm/main-0022bc46:wasm-function[531]:0x697fe) at main.(*text/template.state).evalFieldNode (wasm://wasm/main-0022bc46:wasm-function[530]:0x6959a) at main.(*text/template.state).evalPipeline (wasm://wasm/main-0022bc46:wasm-function[535]:0x6a1d2) at main.(*text/template.state).walk (wasm://wasm/main-0022bc46:wasm-function[569]:0x72cdd) at main.(*text/template.state).walk (wasm://wasm/main-0022bc46:wasm-function[569]:0x730b0) at main.main (wasm://wasm/main-0022bc46:wasm-function[261]:0x2ac52) at main.(net/http.HandlerFunc).ServeHTTP (wasm://wasm/main-0022bc46:wasm-function[463]:0x5973a) at main.interface:{ServeHTTP:func:{named:net/http.ResponseWriter,pointer:named:net/http.Request}{}}.ServeHTTP$invoke (wasm://wasm/main-0022bc46:wasm-function[459]:0x56f72) panic: unimplemented: (reflect.Value).MethodByName()
go run ./get-version > .version cd cmd/templ go build
The function of the generated component inherits the argument types defined in the template, so it can be safely called.
Unlike some ExecuteTemplate, this is safe.
VSCode Extensions
https://marketplace.visualstudio.com/items?itemName=a-h.templ
Syntax Highlight and LSP completion will be very useful.
TinyGo templ
Just to be sure, I checked and found that it only depends on reflect's TypeOf, which is already implemented in TinyGo.
https://github.com/tinygo-org/tinygo/blob/1154212c15e6e97048e122068730dab5a1a9427f/src/reflect/type.go#L494-L500
Now let's try using templ.
The build seemed to have enough room.
gomod2nix
Here is the actual application.
goworkers-demo.ergofriend.workers.dev
When accessed, the HTML can be returned without error.
<span class="pl-c"># Remove templ from the non-standard ~/bin/templ path</span> <span class="pl-c"># that this command previously used.</span> rm -f ~/bin/templ <span class="pl-c"># Clear LSP logs.</span> rm -f cmd/templ/lspcmd/*.txt <span class="pl-c"># Update version.</span> go run ./get-version > .version <span class="pl-c"># Install to $GOPATH/bin or $HOME/go/bin</span> cd cmd/templ && go install
The final deployed size is also 187.91 KiB, so there is plenty of room to expand the application.
This verification is left in this repository.
ergofriend/goworkers-demo
This article is a translation from Japanese.
https://ergofriend.hatenablog.com/entry/2024/08/08/230603
The above is the detailed content of Gos template engine 'templ” is convenient (it also works with TinyGo). For more information, please follow other related articles on the PHP Chinese website!

Go uses the "encoding/binary" package for binary encoding and decoding. 1) This package provides binary.Write and binary.Read functions for writing and reading data. 2) Pay attention to choosing the correct endian (such as BigEndian or LittleEndian). 3) Data alignment and error handling are also key to ensure the correctness and performance of the data.

The"bytes"packageinGooffersefficientfunctionsformanipulatingbyteslices.1)Usebytes.Joinforconcatenatingslices,2)bytes.Bufferforincrementalwriting,3)bytes.Indexorbytes.IndexByteforsearching,4)bytes.Readerforreadinginchunks,and5)bytes.SplitNor

Theencoding/binarypackageinGoiseffectiveforoptimizingbinaryoperationsduetoitssupportforendiannessandefficientdatahandling.Toenhanceperformance:1)Usebinary.NativeEndianfornativeendiannesstoavoidbyteswapping.2)BatchReadandWriteoperationstoreduceI/Oover

Go's bytes package is mainly used to efficiently process byte slices. 1) Using bytes.Buffer can efficiently perform string splicing to avoid unnecessary memory allocation. 2) The bytes.Equal function is used to quickly compare byte slices. 3) The bytes.Index, bytes.Split and bytes.ReplaceAll functions can be used to search and manipulate byte slices, but performance issues need to be paid attention to.

The byte package provides a variety of functions to efficiently process byte slices. 1) Use bytes.Contains to check the byte sequence. 2) Use bytes.Split to split byte slices. 3) Replace the byte sequence bytes.Replace. 4) Use bytes.Join to connect multiple byte slices. 5) Use bytes.Buffer to build data. 6) Combined bytes.Map for error processing and data verification.

Go's encoding/binary package is a tool for processing binary data. 1) It supports small-endian and large-endian endian byte order and can be used in network protocols and file formats. 2) The encoding and decoding of complex structures can be handled through Read and Write functions. 3) Pay attention to the consistency of byte order and data type when using it, especially when data is transmitted between different systems. This package is suitable for efficient processing of binary data, but requires careful management of byte slices and lengths.

The"bytes"packageinGoisessentialbecauseitoffersefficientoperationsonbyteslices,crucialforbinarydatahandling,textprocessing,andnetworkcommunications.Byteslicesaremutable,allowingforperformance-enhancingin-placemodifications,makingthispackage

Go'sstringspackageincludesessentialfunctionslikeContains,TrimSpace,Split,andReplaceAll.1)Containsefficientlychecksforsubstrings.2)TrimSpaceremoveswhitespacetoensuredataintegrity.3)SplitparsesstructuredtextlikeCSV.4)ReplaceAlltransformstextaccordingto


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function

WebStorm Mac version
Useful JavaScript development tools
