
GopherJS – A compiler from Go to JavaScript - primroot
https://github.com/gopherjs/gopherjs
======
jimmcslim
Showing my age, but until I read the full headline I thought this was a
JavaScript client for the Gopher protocol...

[http://en.wikipedia.org/wiki/Gopher_(protocol)](http://en.wikipedia.org/wiki/Gopher_\(protocol\))

Time to pour one out for protocols loved and lost...

------
shurcooL
I've been using it for some time and it's really hard to believe how it just
works for so many things.

[https://gopherjs.github.com/playground/](https://gopherjs.github.com/playground/)
\- GopherJS Playground.

(It compiles Go code to JavaScript in your browser using the GopherJS compiler
itself compiled to JavaScript. There is no backend being used.)

[https://godoc.org/honnef.co/go/js/dom](https://godoc.org/honnef.co/go/js/dom)
\- DOM bindings.

[https://godoc.org/honnef.co/go/js/xhr](https://godoc.org/honnef.co/go/js/xhr)
\- XHR bindings.

~~~
danesparza
I'm genuinely curious to know what you've been using it for.

~~~
shurcooL
Multiple things.

\- Making my Markdown Format package for Atom have zero external dependencies
by compiling the Go code into JavaScript. That way there's no need to install
and point to the markdownfmt binary, making install easier.
[https://github.com/shurcooL/atom-markdown-
format/commit/6b5f...](https://github.com/shurcooL/atom-markdown-
format/commit/6b5f21c4457309f8eba3a78b82e0c9a458ff13b4)

\- Replacing JavaScript with Go code in Go Package Store, still a WIP PR
because I need to figure out a `go get` difficulty, but aside from that it
works perfectly well. [https://github.com/shurcooL/Go-Package-
Store/pull/18](https://github.com/shurcooL/Go-Package-Store/pull/18)

\- Various experimental things that run in the browser and perform operations
that use existing Go code. For example:
[https://dl.dropboxusercontent.com/u/8554242/dmitri/projects/...](https://dl.dropboxusercontent.com/u/8554242/dmitri/projects/live-
markdown/live-markdown.html)
[https://dl.dropboxusercontent.com/u/8554242/dmitri/projects/...](https://dl.dropboxusercontent.com/u/8554242/dmitri/projects/live-
go-printer/live-go-printer.html)

\- At work, I've created a small standalone project with a frontend UI that
reused some common structs and html template code between the frontend and
backend (ala node.js, except all in Go).

\- Working on porting my small OpenGL game written in Go to run in the
browser. The goal is to have the same Go code use OpenGL when on desktop, but
use GopherJS and WebGL when compiling for the browser.

Basically, it lets me do all the things that one would normally be forced to
use JavaScript for (i.e., frontend code) but without having to use JavaScript
(I'm not good at it and I don't like it), while benefitting from Go compiler
to catch errors, autocomplete, godocs, goimports, etc. It also allows me to
import and use existing Go packages that perform non-trivial tasks.

~~~
syntern
Do you have any shareable code for the OpenGL cross-compilation?

~~~
shurcooL
I don't have a complete solution yet, but I can share some links:

[https://github.com/azul3d/issues/issues/29](https://github.com/azul3d/issues/issues/29)
\- Very relevant discussion with good resources/links/info.

[https://github.com/ajhager/engi](https://github.com/ajhager/engi) \- 2D game
library for Go with desktop/browser/android targets.

[https://github.com/shurcooL/play/tree/master/57](https://github.com/shurcooL/play/tree/master/57)
\- Simple WebGL/GopherJS render triangle demo.

[https://github.com/shurcooL/play/tree/master/58](https://github.com/shurcooL/play/tree/master/58)
\- Unfinished attempt to make the above compiled to two desktop/browser
targets.

------
andrewchambers
I'd like to point out that goroutine support has been added which allows
concurrency in the browser. You can literally avoid using callback soup using
this.

its like clojure core.async only more powerful.

~~~
sarnowski
> its like clojure core.async only more powerful.

Can you explain why its more powerful than core.async?

~~~
jlongster
You can use it without going through Go, and have proper support for normal
JavaScript. The concepts are explained here: [http://jlongster.com/Taming-the-
Asynchronous-Beast-with-CSP-...](http://jlongster.com/Taming-the-Asynchronous-
Beast-with-CSP-in-JavaScript) (EDIT: I see now you are asking why go's
channels are more powerful than core.async's)

The library: [https://github.com/ubolonton/js-
csp](https://github.com/ubolonton/js-csp)

------
Cyranix
Can anyone speak to the trade-off in file size, for non-trivial codebases?
There is a stated design goal of "small size of generated code", but the
default snippet in the playground introduces quite a large amount of
boilerplate. Is the penalty on file size fairly front-loaded or does the
generated code scale horribly?

~~~
nknighthb
Annoyingly but predictably, I don't really have any nontrivial code of my own
around that doesn't violate any of the (entirely reasonable, except for x509)
constraints.

GopherJS happily compiles itself, however. The raw source code looks to be
about 250KB. The native binary ends up 7.7MB, and the unminified js is 3MB. A
pass through UglifyJS with default options reduces that to 1.7MB (I have not
tested the result):

    
    
        ~/gocode/bin$ ls -lh *gopher*
        -rwxr-xr-x  1 nknight  staff   7.7M Oct 14 14:02 gopherjs
        -rw-r--r--  1 nknight  staff   3.0M Oct 14 14:32 gopherjs.js
        -rw-r--r--  1 nknight  staff   233K Oct 14 14:32 gopherjs.js.map
        -rw-r--r--  1 nknight  staff   1.7M Oct 14 14:41 min-gopherjs.js
        ~/gocode/bin$
    

Edit: Oh, and the playground example minifies to 300KB:

    
    
        ~/gjstest/playground$ ls -lh
        total 1784
        -rw-r--r--  1 nknight  staff   194B Oct 14 14:05 main.go
        -rw-r--r--  1 nknight  staff   536K Oct 14 14:53 main.js
        -rw-r--r--  1 nknight  staff    42K Oct 14 14:53 main.js.map
        -rw-r--r--  1 nknight  staff   300K Oct 14 14:54 min-main.js
        ~/gjstest/playground$

~~~
nulltype
What about after gzip?

~~~
nknighthb
About what you'd expect, the playground sample drops to 75KB, and the compiler
to 424KB. (Also the native binary gzips to 2MB.)

~~~
shurcooL
Very nice finding!

------
Rapzid
Is there any hope for a workflow similar to clojurescripts? It's very nice to
have your page hooked to the repl and be able to re-evaluate pieces of code
then have the page functionality change without constant refreshes and
recompiles.

Edit: I want to expand on this a bit. I'm curious about how the workflow is
now and what's envisioned. Things like the above mentioned and also
LightTables insta-repl make for great workflow value propositions. I very much
like Clojure, but I like Go as well and have written much, much more of it. So
this is very interesting, but.. Do I need to write the Go code blind, then
compile to js, then refresh and test my page to see what's going on?

~~~
shurcooL
I've written convenience http handlers that compile Go to js on demand (and
report errors in the browser console & server stderr). I do something like
this in the backend:

    
    
        http.Handle("/assets/script.go.js", gopherjs_http.GoFiles("./assets/script.go"))
    

Then my html files (or templates that generate html via html/template package)
include it with:

    
    
        <script src="./assets/script.go.js" type="text/javascript"></script>.
    

That way, I can edit the ./assets/script.go file in my code editor (with
goimports on save, autocomplete, etc.) with the server running. Whenever I
refresh the page in the browser, new compiled JavaScript is loaded.

It's really nice to be able edit the Go script, css, html template and not
need to restart the web server for effects to take place. Just refresh the
page, and see new code running.

That's my workflow so far.

I have plans to improve that code so that it accesses the assets via a virtual
file system interface, so that it's possible to have a debug version that hot-
reloads all files from disk, and a release version that embeds the assets into
the Go binary so it can run anywhere.

~~~
Rapzid
Very interesting, so It's sort of a repl server. Using node.js you could even
execute and return the results.. I'm starting to see how someone(who knows
what they are doing) could create a POC LightTable plugin...

------
kevingadd
Does this support pointers/memory buffers and other systems programming stuff?
It's unclear to me from the compatibility table/etc.

~~~
shurcooL
Yes, pointers are completely supported. You can create a var buf bytes.Buffer
and Write() to it and all that stuff without problems.

------
beefsack
Boy would I love to see someone take this and create a reactive web library
akin to what Meteor and DerbyJS are trying to achieve.

------
fizzbatter
Anyone know how hard it would be to get a ReactJS binding setup for this? I
was literally just looking into GopherJS (for a normal frontend stuff) - but
i'm unsure how gnarly it would be to setup bindings.

Part of me fears the output though. It can be rather verbose, large, and is
quite abstract from the original code. Debugging and code-size worry me
greatly.

~~~
shurcooL
I'm curious about this too. I've heard good things about ReactJS. There are
bindings for AngularJS for GopherJS, so you might want to look at that. I'm
guessing it should be doable.

------
jincheker
I would say that's a great work. But, in order to write efficient code, you
still need to understand both languages. It just saves you time to remember
JavaScript syntax. Since we have google and stackoverflow, people can pretty
much write more idiomatic code than machine. So the conclusion is not worth
it.

------
ankurpatel
Can this create appropriate ASM.js code?

~~~
shurcooL
Not yet, but it's definitely possible in the future. Open issue
[https://github.com/gopherjs/gopherjs/issues/72](https://github.com/gopherjs/gopherjs/issues/72).

FWIW, I've done some crazy things and so far I've seen that things work
surprisingly fast. Performance has not been a bottleneck yet.

------
agumonkey
For alternatives see (7 month old) :
[http://www.reddit.com/r/golang/comments/1z2bc4/a_transpiler_...](http://www.reddit.com/r/golang/comments/1z2bc4/a_transpiler_from_go_to_javascript_for_running_go/cfpxphl)

------
Leszek
Does it self-host? That is, could we have a fully client-side Go-in-the-
browser?

~~~
shurcooL
Yes, that's how the GopherJS Playground
([https://gopherjs.github.com/playground/](https://gopherjs.github.com/playground/))
works. See my other comment.

------
aclissold
Why use a server-side language developed by Google (Go) as an alternative to
JavaScript, when you could use a client-side language developed by Google and
intended as an alternative to JavaScript (Dart)?

------
walu
It remained me of GWT that is disappeared for a long time. hah

~~~
cromwellian
As of this month, GWT has 150,000 monthly active developers, and is deployed
to 20,000 unique domains that we can count (we can't count intranets) User
base has tripled since 2009 and held relatively constant.

