Open5
GolangでCloudflare Workersのツールを作成する

setup
npm install -g wrangler
go install golang.org/x/tools/cmd/gonew@latest
init
cd
cd src/github.com/kazuph
gonew github.com/syumai/workers/_templates/cloudflare/worker-go github.com/kazuph/go-graph-worker
cd go-graph-worker
go mod tidy
make dev # start running dev server
curl http://localhost:8787/hello # outputs "Hello!"

を使って、配列を投げるとグラフ描画してくれるWorkerを作成する。
main.go
package main
import (
"encoding/json"
"net/http"
"github.com/syumai/workers"
"gonum.org/v1/plot"
"gonum.org/v1/plot/plotter"
"gonum.org/v1/plot/vg"
)
func main() {
// /plotエンドポイント: JSON配列を受け取り、グラフをPNGで返す
http.HandleFunc("/plot", func(w http.ResponseWriter, req *http.Request) {
// JSONデコード
var data []float64
if err := json.NewDecoder(req.Body).Decode(&data); err != nil {
http.Error(w, "invalid json", http.StatusBadRequest)
return
}
// グラフ生成
p := plot.New()
p.Title.Text = "Example Plot"
p.X.Label.Text = "X"
p.Y.Label.Text = "Y"
// dataをプロット用の点列に変換
pts := make(plotter.XYs, len(data))
for i, v := range data {
pts[i].X = float64(i)
pts[i].Y = v
}
line, err := plotter.NewLine(pts)
if err != nil {
http.Error(w, "failed to create line plotter", http.StatusInternalServerError)
return
}
p.Add(line)
// レスポンスをPNGで返す
w.Header().Set("Content-Type", "image/png")
// p.Saveではファイルに書き出すため、代わりに直接ResponseWriterに出力するには
// p.WriterToを使う
writerTo, err := p.WriterTo(4*vg.Inch, 4*vg.Inch, "png")
if err != nil {
http.Error(w, "failed to create writer", http.StatusInternalServerError)
return
}
_, err = writerTo.WriteTo(w)
if err != nil {
http.Error(w, "failed to write image", http.StatusInternalServerError)
return
}
})
workers.Serve(nil) // use http.DefaultServeMux
}
dev
make dev
test
curl -X POST \
-H "Content-Type: application/json" \
-d '[1,2,3,4,3,2,1]' \
http://localhost:8787/plot \
-o output.png

deploy
❯ make deploy
wrangler deploy
⛅️ wrangler 3.96.0
-------------------
Running custom build: make build
make[1]: Entering directory '/home/kazuph/src/github.com/kazuph/go-graph-worker'
go run github.com/syumai/workers/cmd/workers-assets-gen@v0.23.1 -mode=go
GOOS=js GOARCH=wasm go build -o ./build/app.wasm .
du -sh ./build
13M ./build
make[1]: Leaving directory '/home/kazuph/src/github.com/kazuph/go-graph-worker'
Total Upload: 12878.22 KiB / gzip: 4769.75 KiB
Uploaded go-worker (5.13 sec)
Deployed go-worker triggers (0.72 sec)
...
圧縮後4MB強だったので無料プランだとだめでしたが、有料プランなのでデプロイして動作確認までできました。

tinygo
install
wget https://github.com/tinygo-org/tinygo/releases/download/v0.34.0/tinygo_0.34.0_amd64.deb
sudo dpkg -i tinygo_0.34.0_amd64.deb
Makefileに追加
.PHONY: tinybuild
tinybuild:
go run github.com/syumai/workers/cmd/workers-assets-gen@v0.23.1
tinygo build -o ./build/app.wasm -target wasm -no-debug ./...
サイズ比較
# go
❯ du -sh ./build
13M ./build
# tinygo
❯ du -sh ./build
6.7M ./build
error
tinygo build -o ./build/app.wasm -target wasm -no-debug ./...
⎔ Starting local server...
panic: reflect: unimplemented: AssignableTo with interface
✘ [ERROR] A hanging Promise was canceled. This happens when the worker runtime is waiting for a Promise from JavaScript to resolve, but has detected that the Promise cannot possibly ever resolve because all code and events related to the Promise's I/O context have already finished.
[wrangler:inf] POST /plot 500 Internal Server Error (57ms)
✘ [ERROR] Uncaught (in response) Error: The script will never generate a response.
一旦時間切れ。

tinygoリベンジ
cd
cd src/github.com/kazuph
gonew github.com/syumai/workers/_templates/cloudflare/worker-tinygo github.com/kazuph/tinygo-graph-worker
cd tinygo-graph-worker
go mod tidy
....
一応テンプレートの違いの可能性も感じてやったのですが、変わらず。