I wanted to write today about my experience with a very cool project named tinygo

Let me first off by saying web assembly in Go has a BIG problem. It’s way too reliant on it’s very bespoke API’s for getting things done. syscalls/js in my opinion is the very definition of the wrong way to go for web assembly:

Go devs should NOT learn javascript

As time goes to infinity, web assembly will get its own API to the DOM probably based on WebIDL (https://github.com/WebAssembly/design/issues/1148)

It makes way too many assumptions about the host running the web assembly and what functions are required for import to even get your module running

calling external functions as they natively are in the web assembly stack machine (not some abstraction) will always be the fastest method.

I was very happy then when I came across tinygo , compile down a web assembly module and come to found it it makes WAY less assumptions and has a very simple based comment based system for importing functions — something to my knowledge currently impossible in the mainline Go compiler.

tinygo takes advantage of LLVM and is able to reduce web assembly modules to a pretty extreme amount pretty well. What this enables me to do is write very minimal modules like this hello world:

package main //go:export console_log

func console_log(msg string) //go:export main

func start(){

console_log("hello world")

} func main() {}

Compiled down, this module only had 2 import requirements:

console_log

io_std_out (because currently tinygo assumes some runtime )

Exports:

main

Out of all the options I’ve seen thus far for go web assembly tech, this is about as good as I could have hoped for.

I’ve been writing some libraries that expose some very efficient bindings to DOM manipulation APIs using a generation approached based on browser Web IDL ( standardized descriptions of what functionality browser environments have ).

Instead of making syscalls/JS you have a huge amount of imperative functions you can call to get handles to resources in the DOM and manipulate them. The advantage of this approach is that it is incredibly simple and C like, and requires no special code generation on your part and is entirely tech agnostic. Simply import in the functions you need.

Here’s an example of a canvas app:

package main //go:export global_getWindow

func GetWindow() int32

//go:export Window_get_document

func GetDocument(window int32) int32

//go:export Document_querySelector

func QuerySelector(document int32 ,query string) int32

//go:export HTMLCanvasElement_getContext

func GetContext(element int32,context string) int32

//go:export CanvasRenderingContext2D_fillRect

func FillRect(ctx ,x ,y ,w ,h int32)

//go:export CanvasRenderingContext2D_set_fillStyle

func FillStyle(ctx int32, fillStyle string) func cstr(s string) string{

return s+"\000"

} //go:export main

func start(){

win := GetWindow()

doc := GetDocument(win)

canvas := QuerySelector(doc,cstr("#screen"))

ctx := GetContext(canvas,cstr("2d"))

FillRect(ctx,0,0,50,50)

FillStyle(ctx,cstr("red"))

FillRect(ctx,10,10,50,50)

FillStyle(ctx,cstr("grey"))

FillRect(ctx,20,20,50,50)

} func main() {}

You can see this working live here