JavaScript Objects in Go and WebAssembly

Muthukumaraswamy
3 min readOct 17, 2020

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Implement your performance-critical stuff in wasm and import it like a standard JavaScript module.WebAssembly code defines an AST (Abstract Syntax Tree) represented in a binary format. Browsers will understand the binary format, which means we’ll be able to compile binary bundles that compress smaller than the text JavaScript we use today. Smaller payloads mean faster delivery. Depending on compile-time optimization opportunities, WebAssembly bundles may run faster than JavaScript, tooooooo!

Go is an imperative, statically typed, compiled programming language first developed at Google by Rob Pike, Robert Griesemer, and Ken Thompson in 2007 and open-sourced in 2009.

As you are aware that the WebAssembly runtime for Go will automatically convert the most common Go types to javascript equivalent. We have a good documentation for the ValueOf method which has a nice summary table of the types.

here in the above if you can notice may of the common types like numbers, booleans, and strings which are converted automatically. You can take a look at the last row which is interesting. here is the explanation about Plain Old JavaScrpit Object these are also called as also called dictionaries. Let’s take an example go code which defines a function called MyGoFunc that can be called from JavaScript code, which returns a dictionary with a string and a number

Learn more about how to compile Go code into WebAssembly Get started here.

// Copyright (C) 2020 Alessandro Segala (ItalyPaleAle)
// License: MIT
package main// Import the package to access the Wasm environment
import (
"syscall/js"
)
// Main function: it sets up our Wasm application
func main() {
// Define the function "MyGoFunc" in the JavaScript scope
js.Global().Set("MyGoFunc", MyGoFunc())
// Prevent the function from returning, which is required in a wasm module
select {}
}
// MyGoFunc returns a JavaScript function
func MyGoFunc() js.Func {
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
// Return a JS dictionary with two keys (of heterogeneous type)
return map[string]interface{}{
"hello": "world",
"answer": 42,
}
})
}

Once i comiple the code into WebAssembly and then imported it in the JavaScript you can call MyGoFunc() from JavaScript and see the result

console.log(MyGoFunc())// Prints: {hello: "world", answer: 42}

The documentation is not very explicit about using any JavaScript object inside the Go code, even built-ins and this is where things getting more interesting.Now let’s try to pass a date as a Date object. To do that, we first need to grab the Date constructor, loading its js.Value from the global scope of JS:

dateConstructor := js.Global().Get("Date")

Create a new object off this constructor with the date constructor.New method, which will pass any argument to it as you’d pass to the new Date() constructor in JavaScript. The result of the invocation is a js.Value that can be returned to JavaScript:

dateConstructor.New("2020-10-17")

we can modify our MyGoFunc to return the current date as computed in Go:

// Copyright (C) 2020 Alessandro Segala (ItalyPaleAle)
// License: MIT
// MyGoFunc returns a Go time.Time to JavaScript
func MyGoFunc() js.Func {
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
// Get the current time as a Go time.Time object
now := time.Now()
// Get the Date object constructor from JavaScript
dateConstructor := js.Global().Get("Date")
// Return a new JS "Date" object with the time from the Go "now" variable
// We're passing the UNIX timestamp to the "Date" constructor
// Because JS uses milliseconds for UNIX timestamp, we need to multiply the timestamp by 1000
return dateConstructor.New(now.Unix() * 1000)
})
}

Invoking MyGoFunc() in the JavaScript code will now return a Date object:

let d = MyGoFunc()
console.log(typeof d)
console.log(d instanceof Date)
console.log(d.toString())
/*
Prints:
object
true
*/
Sun Oct 17 2020 10:58:27 GMT-0700 (Pacific Daylight Time)

--

--