Verbally Flimzy

Ramblings, Observations and Misconceptions

How I got go-spew to work with GopherJS

Posted on October 19, 2016

go-spew is a very handy library used for dumping arbitrarily complex data structures in a (roughly) human-readable format.

This is immensely helpful when debugging or writing automated tests in programs. Coupled with a package like go-difflib, it can make comparing the expected and actual results of a test not only easy, but into something approaching fun.

6654647Much of my time lately is spent hacking on projects to be compiled by GopherJS, the Go-to-JavaScript compiler.

Sadly, go-spew and GopherJS don’t play together well. Or they didn’t, until recently.

You see, go-spew does some pretty nitty-gritty introspection on data structures, to report on the sizes of variables, and memory addresses and whatnot. These features are not supported by GopherJS, as code compiled by GopherJS is run within a JavaScript interpreter, where direct memory access isn’t available, and pointers are emulated.

When executing a common go-spew function in GopherJS, I would get something like this:

`$ nodejs jstest.js
/home/jonhall/go/src/github.com/flimzy/jstest/jstest.js:1475
        throw err;
        ^` 

`TypeError: upf.$get is not a function
    at init (/home/jonhall/go/src/github.com/flimzy/jstest/jstest.js:24518:14)
    at Object.$init (/home/jonhall/go/src/github.com/flimzy/jstest/jstest.js:26410:8)
    ...` 

I decided I wasn't happy with this state of things, so I set out to investigate. And I stumbled upon [a year-old commit](https://github.com/davecgh/go-spew/commit/2df174808ee097f90d259e432cc04442cf60be21) to the _go-spew_ package, with the description:

> Add support for limited mode without unsafe pkg.
> 
> This commit adds support for compiling spew without the unsafe package.
> When compiled without the unsafe package, some of the more advanced
> features such as invoking stringers on pointers from non-pointer
> variables and unexported struct fields are not available.

This looked promising, so I set out to see if _go-spew_ would work with GopherJS with this new build tag:

$ gopherjs test –tags=disableunsafe github.com/davecgh/go-spew/spew TypeError: upf.$get is not a function at init (/github.com/davecgh/go-spew/spew/bypass.go:88:3) at Object.$init (/home/jonhall/go/src/github.com/davecgh/go-spew/test.166243863:32502:8) …


Ugh. I've hacked on GopherJS a few times before, so I wasn't afraid to start debugging it.  Pretty quickly I found that GopherJS was simply ignoring build tags during testing. I [filed a bug](https://github.com/gopherjs/gopherjs/issues/507), then found and submitted [a patch](https://github.com/gopherjs/gopherjs/pull/508) which was quickly merged.

My next step was to submit a [pull request](https://github.com/davecgh/go-spew/pull/51) to the _go-spew_ project to treat the `js` tag the same way it treated the `disableunsafe` tag. This patch was quickly merged as well.

Now _go-spew_ works safely, and out of the box with GopherJS, and I'm a happy camper!  Isn't open-source software great?

Filed under: Go gopherjs Programming