Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Go playground powered by WASM that runs in the browser (go-playground-wasm.vercel.app)
140 points by zackoverflow on Sept 23, 2021 | hide | past | favorite | 41 comments



This is a little experiment demonstrating the capabilities of the goscript project (https://github.com/oxfeeefeee/goscript) by compiling it to wasm.

Here's the source code (https://github.com/zackradisic/go-playground-wasm) if you would like to look at it and do something similar with your own projects.

I'm really excited for the future of goscript, Go is a great candidate for a scripting language thanks to its minimalistic design choices.


Got to admit, I think "Rewrite it in Rust" has gone too far this time.


> Goscript > A script language like Python or Lua written in Rust, with exactly the same syntax as Go's.

Strange things are afoot at the Circle K.


Thanks. I've never seen Bill & Ted's Excellent Adventure and this comment lead me down a great little Internet rabbit hole


Stop at the first movie, both the sequels are totally heinous.


I enjoyed the newest one, but probably because it was dumb and nostalgic and I hadn't seen the original in twenty years.


What GC is used in goscript? The upstream one, a Rust GC<> one, maybe the mini one from TinyGo, or something else custom?


I poked around earlier and found this file: https://github.com/oxfeeefeee/goscript/blob/master/vm/src/gc...

Perhaps someone can shed more light on how exactly it works


From looking at it for like 20 seconds (I ain't no serious rustacean, so forgive if I'm wrong) I think they're using just a growable pool (as vectors) of each fundamental type in the Go language, then having each instance of each fundamental type be boxed in a Rc (reference counted) type so that they can count all references to each instance of each fundamental type.I believe that this can be used to get simple reference counting "for free" via the borrow checker of Rust. Probably many downsides, and apparently they don't yet implement GC of channels, but it seems like a nice straightforward way to get a script-ing/purely interpreted implementation of a language off the ground.

The Rc module with the impl - https://doc.rust-lang.org/alloc/rc/

Further docs on Rc- https://doc.rust-lang.org/book/ch15-04-rc.html


How come this is so fast? I feel like the processing faster than I would get on an native compiled and run program. Are there any benchmarks?


Speculation here, but I think WASM lends itself very well to JIT compilation, and V8 has one of the best compiler teams in the world.


    [Error] TypeError: i64 not allowed as return type or argument to an imported function
        [f] ut (framework-a4fd281a1981cd6d009d.js:1:16748)
        [f] mt (framework-a4fd281a1981cd6d009d.js:1:17899)
        [f] L (framework-a4fd281a1981cd6d009d.js:1:115080)
        [f] W (framework-a4fd281a1981cd6d009d.js:1:2282)
        [f] Jt (framework-a4fd281a1981cd6d009d.js:1:23856)
        [f] Zt (framework-a4fd281a1981cd6d009d.js:1:23074)
        [N] Zt
        [f] (anonymous function) (framework-a4fd281a1981cd6d009d.js:1:128011)
        [f] F (framework-a4fd281a1981cd6d009d.js:1:114857)
        [f] Xt (framework-a4fd281a1981cd6d009d.js:1:22889)
        [N] Xt
I get that error when I click “Run” with the sample code in Safari.


Thanks, this is a problem with some browsers not supporting BigInt <-> Wasm i64 conversion, I just made some changes that should fix it


Perfect! The updated version works.

Nice project. Thanks for sharing.


Which browsers?


Couldn't find a list but I tested it on brave, chrome, firefox, safari and it was safari that was having troubles


Oh ok, Apple will fix that in five years.


This was supposedly fixed by at least Safari 14.1 (or earlier).


Off-topic: I know one of you smart folks here at HN have figured out how to do something similar to go playground in the terminal that makes it easy to write a script, and on safe it go fmt's + imports, and then runs it. Something with vim + tmux or whatever. If this is you, I'd love it if you could share it!


I use a script for this. Something like:

    #!/usr/bin/env bash
    {
      find . -name "*.go" -print
      echo package.json
    } | entr bash -c '
    set -euxo pipefail
    clear
    go fmt
    clear
    go build
    :
    '
You can make it fancier like adding cd into "${BASH_SOURCE[0]%/*}", etc


I made this extension for VS Code that also saves the outputs to markdown, so you can save it straight to blog posts: https://marketplace.visualstudio.com/items?itemName=gobookde...

Each cell runs in a 0.3 secs on Linux, but 3 seconds + on Windows.

If you want just straight terminal check out Gomacro, that's a interpreter that runs really fast, didn't find any differences to compiled Go.


There's an REPL called yaegi, but it's pretty primitive (no autocompletion etc.. when I tried).

There seems to be another interpreter that seems to be able to provide some autocomplete using some other third party tool, but it seemed to run from beginning every time (same effect as `go run`) and I havent tried it.


The issue with these REPLs is for whatever reason it doesn't come close to the experience of say the python REPL. I have been hoping for the Go devs to build a REPL into the tooling but so far nothing has happened yet.


Yeah they are very primitive :(


I would love if wasm got some more TLC from the go team. Output sizes are massive compared to rust or C. I think it’s just a matter of adding some tree shaking … but probably easier said than done.

I’ve been falling more and more in love with wasm … so many possibilities :)


I would like that too but probably wont happen.

There are 3 big reasons for large Go binaries.

1. Unicode data is ~1 MB. It's needed to implement all the unicode-aware string functions like strings.EqualFold()

2. reflection. For reflection to work, every struct used in a Go program needs to have a description information that tells names and types of all fields. This adds up

3. Precise garbage collector also requires struct descriptions like reflection but even more information like: layout of stack frame for every function.

Those are problems that could, in theory, be worked-around.

A build could exclude Unicode info and functions that require it.

A different garbage collector could be used that doesn't require knowing layout of structs and stack frames.

Reflection could be changed to require explicit opt-in (99% of structs are not reflected upon).

Realistically none of that will happen in the official Go implementation. For better or worse most of the work is sponsored by Google and Google runs Go on servers. With 512 MB of memory, it makes little difference if your binary is 10 MB vs 9 MB, especially if you compete with even more bloat (in runtime memory use, not necessarily binary size) of Java / Python / Ruby / Node.

There are a couple of not-very-mature Go-like implementation that are trying to address this (tinygo, emgo) but they have long way to go.


I agree with everything you said. Reflection, I think, is the one that is quite difficult to address.

The others - GC and unicode data - can be addressed through changes to WebAssembly in theory.

For Zig, I developed a custom compression algorithm[0] for the Unicode data files needed to implement the same string functions - reducing the data size down to just 58 KiB. The same could certainly be applied to Go.

[0] https://devlog.hexops.com/2021/unicode-data-file-compression


great points. I’ve used tinygo, it is pretty awesome unfortunately the features I was using weren’t supported; I was utilizing some public key cryptography.

I will have to check out emgo; first time I’m hearing about it.


much reflection can also be done through the host environment especially since it has full access to the data and custom name sections


I wonder how tinygo works for wasm. I’m not sure how much of the bloat is runtime (which I assume is smallish) vs how much of the standard library is just included by default.


Tinygo produces very small binaries (kb rather than mb), through using the LLVM tool chain (which does tree shaking), and only (presently) supporting a subset of the standard library.

Plus their own (simplified) subset of the standard library, which is getting more comprehensive over time, but is nowhere near complete yet.


You can have a go at it over here, https://ebiten.org/examples/


I was sure wasm was going to replace javascript by now, still waiting though. Is it ever going to happen?


You might already know this, but WASM isn't even at a stage where it can replace JS. Bindings to the browser APIs are currently done through a JS bridge, which can be pretty slow.

I've lost track of the process (there were several proposals) so I'm not sure where we're at now.

I guess not much changed, so the current state of WASM is mostly for porting and running non-JS code (such as Go's here) in the browser.

It's also faster than JS (if passed through an optimizing compiler) so it might be useful for non-IO-bound code.

Outside the browser it's being used as a sort of universal bytecode (a la JVM). https://wasmer.io/


I'm just trying to avoid all the JS spaghetti.


Nice, maybe add some line numbers to the source view. Makes dealing with compile errors a bit easier.


Having a bigger / resizeable output box would help too - running the Fibonacci example, all I can see is "0" unless I manage to find the tiny box with its invisible boundary to scroll in.


awesome! I made one just like it about a year ago: https://app.qvault.io/playground/go

it actually powers some of the courses in go that I've written as well


nice, i’d love to see a mobile web browser that supports wasm


offtopic: I love your username, zackoverflow

neat project too!


thanks! when I came up with it I couldn't believe I hadn't thought of it earlier lmao




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: