Hacker News new | past | comments | ask | show | jobs | submit login
Extensible WASM Applications with Go (go.dev)
229 points by ingve 3 months ago | hide | past | favorite | 123 comments



A problem is that a Go produced WASM binary is really large. TinyGo overcomes this, but compiles too slow and you need to be really careful which libs to import (reflect). To overcome both, you need a lot of patience.

If you want to tryout Go WASM on Cloudflare workers you need to buy a subscription due to the size of the binary. Last time I tried you could run hello-world, but anything more substantial exceeded the size threshold.

Such a pity…


I guess my question is, why is Go compelling as a source language for WASM?

If I want to do high performance programming I don't want to worry about garbage collection.

If I can withstand GC then I know enough about JavaScript to keep V8's optimiser happy. Which will always be the best DX for writing code in the browser. (edit: though this post is specifically about WASI)

Go has never focused on binary size and probably never will unless it actually becomes an issue for Google. That's the disadvantage of having a corporate BDFL I guess.


"why is Go compelling as a source language for WASM?"

As near as I can tell, the answer is that it is supported, and has been working now for many versions.

See the short list of "production" languages here: https://github.com/appcypher/awesome-wasm-langs And read the sections carefully; you might think your $FAVORITE_LANG must be in the "stable for production usage" section given how big it is but it's full of a lot of languages with small communities. The really big names are mostly in the "unstable" category.

I can verify that I've toyed with some WASM support in a few languages now, and it is often not even functional, or takes vast effort to set up far above and beyond the official tutorials. You'll see a steady stream of stories on HN over the years about how this language or that language supports it, but in many cases those should be understood not so much as a commitment of support, but as a snapshot, that in that moment, it worked, but it may not work next week.

It's still true that Go produces big binaries. Official WASM garbage collection support may shrink that at some point though it'll still be larger than other languages for the goroutine runtime support. Not only is a bare minimum "Hello World" a couple of megabytes off the top, the Go WASM executables grow quickly as you add libraries. It rapidly becomes usable only for situations where you are guaranteed very high bandwidth for all users. Such situations exist, but is certainly a major limitation. (Though at least it does cache well, if you are even slightly careful with caching.)

So, to summarize, I'd say that it's not that Go is awesome and amazing, but that vast swathes of the competition are still quite bad.


Not true. I've built multiple production apps with Blazor WASM. Works great. Only drawback is the continually delayed multi threading support, but given native JS multi threading is far from ideal it's not a huge drawback.


I thought the runtime was essentially a fixed cost, and that a compiled Go binary would be similar in size to the native binary for the same source tree. Are you saying it grows faster?


Well, "normal" Go binaries grow somewhat quickly as you add libraries. I don't think WASM is growing faster, it just stings more when you're looking at transferring them in realtime over a network. A 20MB binary is not really anything to a modern system, not even a Raspberry Pi. But a 4MB WASM executable can still hurt.

(Though, sadly, only if you care. I just double-checked CNN's website, and given that it autostreams video it's hard to give a concrete "it took this much to load the site", but if I look at how much data was transferred before the home page stopped jumping around and rerendering and unblocking grey boxes and spinners, it was around 20MB.)


laughs in kubectl


The most basic understanding of programming language runtimes is sufficient to guess the entire Production-tier list. There isn't any need to talk down to us about $FAVORITE_LANG


I strongly disagree. I'd expect it to me much larger by now, at least, based on my expectations and not my experience.

And once you clear the small-community languages out of the "stable" list I think it's underpopulated there as well; it's basically just .Net, .Net through C#, and .Net through F# (which I'm sure is more the .Net than the F#, no offense intended to the F# team). Way, way more of the languages I can name off the top of my head in "unstable" than I'd expect.

And while I don't intend this to be offensive to anyone either, WASM is just generally moving way slower than I expect. Given how many years that has been true at this point I must conclude it is being quite underinvested in, or, to put it another way, I'm blaming Google and peers for underinvesting, not the people working on it. More power to the people working on it, their skill is evident.



How do you think?


> I guess my question is, why is Go compelling as a source language for WASM?

For me it is for three reasons: 1) I mostly write things in Go, 2) My main use-cases for WASM are backend applications, 3) being able to run sandboxed code (in backends) would be really, really useful.

Sadly, right now it is rather fiddly to make use of WASM in Go.

> If I want to do high performance programming I don't want to > worry about garbage collection

Then don't worry.

For most applications performance isn't going to be lost due to GC, but due to poor design choices and lack of effort. My observation is that most programmers tend to overestimate their own ability to routinely produce high performance code and under-estimate the cost of producing high performance code. The latter is more important. Writing high performance code (regardless of language/runtime) is time-consuming and tends to require a lot of skill to achieve consistently.

That being said, "high performance programming" is ill defined. For the term to have any real meaning one has to be more specific about what one tries to achieve.

> Go has never focused on binary size and probably never will unless > it actually becomes an issue for Google.

Probably correct. The problems of those who put in the work developing Go is probably going to receive priority. Binary size isn't a huge problem for the things people tend to use Go for.

As an aside; I've been writing software for an embedded Linux platform lately where binary size can become a challenge. I observed that the binaries produced by roughly equivalent C++ programs are about the same size as the Go binaries. Bigger if you take into account that the C++ programs were dynamically linked and the Go programs were statically linked. So your mileage may vary.

It may be that it is possible to introduce tooling and libraries that would allow you to generate WASM output that has a significantly smaller footprint.

> That's the disadvantage of having a corporate BDFL I guess.

No, I don't think it is tied to Google's ownership of Go. As with almost all large open source projects it is about developers and priorities. And a lot of open source gets developed on company time. If you want to help the Go project produce smaller WASM binaries then I don't see why Google would discourage you from contributing. If companies and people do not want to contribute it isn't going to get done.


What primarily brings you to using backend WASM rather than deploying Go natively?

    Then don't worry [...] high performance programming" is ill defined. For the term to have any real meaning one has to be more specific about what one tries to achieve.
My main "high performance" experience is of writing WebVR applications. VR can't tolerate framerate drops because it makes users physically sick.

I don't know what the GC story is like for Go in WASM but it would make me very wary.


To be clear: I'm not using WASM in any backends right now, but I would like to.

The two main use-cases for me would be data transformation and message routing or decision logic that is maintained by the user. That is, the user develops the code to parse custom data formats and emit them in various other data formats, tests and compiles it locally and then uploads it into the backend to be instantiated and run. Ditto for routing/decision logic. (So typical "reactor" usage).

Having third parties produce Go binaries to do this would be resource intensive and awkward.

One of our projects is an IoT platform where we get lots and lots of messages from devices. Some of these devices are very constrained and use, or want to use, space efficient custom data formats. However, they'd like to make the data available in more practical formats for consumers. Hence the need to be able to transform them to one or more other formats in real-time. I'd like to let the customers to be able to write these codecs.

There are a few other uses as well that we are looking at, but common for all of them is that none of them need a generic system interface. Typically you want to project some API(s) into the runtime that the code can call.

(I'm also on the lookout for ways to embed compilers in the backend so customers can edit code in a web interface and compile it in the backend, but embedding compilers has proven to be ... not incredibly fun)


That's interesting.

How do you enforce a contract on these WASI artefacts? How do you stop the user doing bad things (like infinite loops or crashing the surrounding program)?


The short answer is: I don't know and those are valid concerns.

The first issue you bring up is really one about resource limiting. You would want a mechanism to set resource limits (CPU, memory, execution time etc) and then be able to pause/unpause, throttle, terminate, restart or perform some other action when you hit a resource limit. It is safe to assume people will make mistakes. :-)

It has been a while since I looked at runtimes, but I don't think resource limits would necessarily be that hard to implement.

It seems to me that preventing crashing the surrounding program isn't something you can necessarily address in a runtime. Any library or component you use in your Go code can potentially crash the program. And if you project APIs into the sandbox that can be called in ways that crash the surrounding program, that's mostly on you, the programmer, and not really something I think the runtime could reasonably prevent.


You can do this with wasmtime using either a deadline trap or a concept called "fuel" which is basically a measure of "consumed CPU time" roughly speaking. I have used wasm for a very similar thing (user writing code for robots in a multiplayer video game) and it works very well. I am confident they can't mess with the server and I can prevent them from running long running processes.


For wazero (mentioned in the article) WASI capabilities can be granted piecemeal: (e.g.) the host can grant/deny access to the clock or implement a virtual one. Obviously, you can do the same with the file system, etc.

Guest crashes become panics the host can recover from.

Finally, you can use a Context to abort execution of the guest, although this option introduces a performance penalty: every backjump must read a counter to periodically poll this context.

That said there are issues when running adversarial code.

The default WASI filesystem implementation is not really meant for sandboxing. When you mount a host folder in the guest, it's possible for the guest to escape the root. You can improve the situation by using virtual files, but that's more work if you want anything sophisticated. WASI is simultaneously too sophisticated to make it hard/slow to emulate+sandbox (symlinks and Unix path resolution), and lacking important features.

There are little to no protections against speculative execution (i.e spectre) attacks. With memory bounds checks implemented in software, you're bound to leak information that way.

So please: don't mix multiple customers custom code in one Go host process. It's not really meant for that.

Allowing your single customer (per host/VM) to customize your product with some plugins, giving some tought about filesystem access (to prevent privilege escalation), is more realistic.


Well, now you have defined what you mean (realtime'ish execution low/no latency variance). The next step would be to formulate a test and see if it is actually a problem and then make technology choices. Just assuming isn't really professional.

You can always find use-cases where GC'ed languages might be challenging to use. With emphasis on "might", because you kind of have to try it out before you can determine if it is a problem.

There are a lot of high performance applications where they're just fine. For instance if you care more about throughput than latency variance. This is why "high performance" isn't a useful term. You have to be specific about how you measure "performance".

Most of the code for most developers isn't terribly performance critical. Correctness is usually far more important. Most performance tends to be lost due to lack of design talent rather than the language.


This is a great take, I agree 100%.

I'm curious, would you mind elaborating on your use-cases for sandboxed backend application code? This is clearly the direction in which it's all headed, yet is still mentioned relatively rarely in WASM-related discussions on here.


> I'm curious, would you mind elaborating on your use-cases for sandboxed backend application code?

When working with backend systems you generally have 2 choices, a less secure containerized environment that does a very good job of distributing resources or a bulky VM which has a fixed memory cost that you might not need.

WASM sits right in the middle of the two. It has a durable sandbox that prevents bugs in the application logic from exposing the whole machine to exploit (and it itself can be further isolated using the same containerization security practices) but also has the benefits of single app like resource requirements.

Another prime benefit of WASM (not related to the sandboxing) is that WASM is a write once run anywhere standard. That means you don't need a different x86 and ARM wasm deployable. Similar to Java's JAR.


Look at my other reply for a use-case.

In general I think being able to run user-supplied code in a sandbox is the most interesting use-case for WASM and backends/Go.

Compiling entire applications to WASM and running them in a WASM runtime is of no interest to me. So for instance WASI isn't actually useful to me since I'd only want to project a very narrow set of APIs into the runtime for the (WASM) code to call. I certainly do not want to give it access to my system and then have to clamp down what access I give it.

I think what the original post points to is an interesting step in the right direction. If someone were to figure out an ergonomic and safe way to support structs, []byte slices as both parameters and return values that would probably open up a lot of new possibilities by lowering the barriers for adoption. If it is Go specific, I can live with that. If it can be done in a manner that supports lots of other languages, that would be fantastic, but to me, right now, it isn't critical.

If it were up to me I'd say forget about WASI for now and solve that problem instead. Yes WASI may be slightly useful some day (I can't see that I'll ever use it), but actually being able to have sandboxed runtimes where I can project in my APIs is vastly more useful.

(I'm not saying WASI is not useful. I'm saying that it is not useful to me. And I think that if projecting Go APIs into a sandbox is easy, then WASI probably isn't going to be important to most people doing backends as they can project more application specific, narrower and more strictly guarded APIs into the sandbox)


Thanks, appreciate the response. I read your other answer too.

Given what you've just described, do you have an opinion on the component model & WIT[0]?

[0]: https://component-model.bytecodealliance.org/design/wit.html...


I wasn't aware of WIT. I'll have a look. Thanks for the link!


Check out Extism


I came here to say this. Here are their SDK docs: https://github.com/extism/extism#run-webassembly-in-your-app


why not just a slim podman?


I wouldn't want to run code from a third party in a container.


why is that? how is it different from WASM? podman can be rootless, and it runs inside its own sandbox on the server side as much as WASM runtime does. Plus there are many sandbox options on linux for podman.


In a sandbox you start out with access to nothing except the apis that you explicitly expose into the sandbox. In Podman you start out with a huge attack surface which you then have to clamp down. One of those surfaces is the kernel. Another is the network.

Using containers to run untrusted third party code is horribly risky. Containers provide nowhere nearly enough isolation and separation.


these days containers run well-known open source code or your own code, and are used widely in the field. Linux does have namespaces and other security approaches to safeguard them further. yes they are less secure than WASM but security is always a compromise between convenience and cost.

Anyway, points taken, thanks.


Database stored procedures / user-defined functions written in arbitrary languages is a live use case on several platforms today.


> Which will always be the best DX for writing code in the browser.

The article we're all commenting on is not about running WASM in the browser.

WASI in particular may never be supported by browsers.


I'm aware of the article's context but am asking the broader question.


> I'm aware of the article's context but that just raises further questions. Why invest much effort, as a developer, or as a vendor, in a version of WASM that doesn't even let you run client side? It's carving an ever smaller niche.

Because of the value it can deliver server-side, and that's where most of the value tends to be.

Server-side compute is the core of most companies' revenue streams, yet it really is bloating out of control. Think about how much money is wasted on build pipelines, artifact storage, giant image distribution, multi-tenant workload isolation, supply chain risk mitigation; how expensive cloud infrastructure is, and what a substantial share of it is spent on all of those. With the way WASM was designed, it has the potential to completely upend all of it: tiny binaries, sandboxed runtimes, tightly knit mt, instant scaling, clearly defined contracts, language agnostic microservices. It's a completely different world.

The potential for WASM in enterprise compute is immense - especially with the recent developments in the component model and WASI. We're talking about orders of magnitude improvements here.


Just wait until they figure out WASM Application Servers, using serialised WebAssembly for server to server messages, now that would be an idea.


They could call it wRPC or something


Funnily enough, that's what [wRPC](https://github.com/bytecodealliance/wrpc) is designed to do, using the small and efficient [Component Model Value Encoding](https://github.com/WebAssembly/component-model/blob/main/des...), largely based on [Core Wasm spec](https://webassembly.github.io/spec/core/).

For example, here's an example of a Web App using [`wasi:keyvalue` interface](https://github.com/WebAssembly/wasi-keyvalue/) via WebTransport using wRPC: https://github.com/bytecodealliance/wrpc/tree/8e9de3b446ac05...


And on that regard, there are more mature options out there, than reinventing the wheel with WebAssembly.


Do those "more mature" options support architecture-independent executables written in Rust or Go, so that a company doesn't need to rewrite their existing code in Java?


Well, depends if they target LLVM IR, or .NET MSIL.

https://www.graalvm.org/latest/reference-manual/llvm/

https://github.com/FractalFir/rustc_codegen_clr

Also ever heard about containers?

They have this magic feature, you don't need to rewrite anything to run on servers.


Containers are a much heavier way to implement a plug-in system, since you will also need to define an RPC of some kind, and they're not architecture-independent unless you require the users to build every container for every architecture. Containers generally aren't a security boundary, but you can wrap them in something like firecracker to help with that. (I believe plugins were an essential part of the context, based on the post we're commenting on, so it is important to evaluate these options against that.)

LLVM IR as it is actually generated is also not architecture independent, and not a security boundary, making it a poor way to do a plugin system. Definitely not more mature for this type of stuff.

.NET MSIL is probably a better fit than the other two options you provided, but not a good one... I don't think Go or Rust compile to MSIL, and MSIL probably isn't a very good security boundary anyways.

I know from past discussions that you don't like WASM. I think you're overly dismissive of it. WASM has been around long enough now that it is a fairly mature system. I haven't personally needed it, but that's simply a comment on my own work experience, not the usefulness of the technology for specific use cases... and I can easily see why people are passionate about WASM. It's not NIH syndrome.


If you want a plugin-in system, maybe don't pick a language with static linking, and an half-backed plugin implementation in first place.

WebAssembly outside of the browser is a solution looking for a problem that has been sorted out multiple times since the idea of bytecode based execution exist, 1958 to be more precise.

Even on the browser its use, besides bringing back the old plugins is debatable, using GPU compute is much better for number crunching, with much better tooling.


How do I prevent my statically linked plugins from having any filesystem access, or a bug messing with memory it doesn’t control once it’s loaded?


OS IPC and security configuration, no need to add a WebAssembly runtime and compiler toolchain.


So: slow, hard, complex and highly OS specific vs simple and secure.

Right.


Because WASM tooling is so much better, thank goodness for emscripten.


Don’t argue in bad faith, especially if you’ve got nothing substantial to add to the discussion or any real points to make.


Yes… I’m aware of the history. I’m also aware that WASM solves problems that those previous ones didn’t. Otherwise you would have provided an option that actually met the requirements, if there are so many to choose from.

> If you want a plugin-in system, maybe don't pick a language with static linking

Or… a plugin system could “just work”, without placing unnecessary restrictions on what I do.


It starts by choosing the right language for the job.


The right language for a plugin system is the one that attracts the most plugin writers. Supporting many languages is a huge boon for wasm in this department. It's one of the things that makes the JVM and .NET so appealing in the first place, but WASM is better than both combined when it comes to language selection.


That surely isn't any WebAssembly then, if we are counting adoption growth throughout computing history.


I'm not aware of any tech other than wasm that I could be using to implement decent-auth: https://github.com/lastlogin-net/decent-auth

Things like JVM and .NET are great, but not designed to be embedded other languages.


.NET does support embedding:

- As full runtime i.e. hostfxr https://learn.microsoft.com/en-us/dotnet/core/tutorials/netc... (supplementary: https://github.com/StudioCherno/Coral)

- As a dynamic library via DNNE with full runtime: https://github.com/AaronRobinsonMSFT/DNNE

- As either dynamic (easy) or static (hard) native library: https://github.com/dotnet/samples/tree/main/core/nativeaot/N...

There are a few community projects which build on top of these to provide a more seamless integration with other languages.


That's actually really cool, thanks for sharing. Does seem pretty low level and niche though.


It is very popular in gamedev space whenever using C# as a high-performance scripting language.

You are right to say this is low-level though, but low-level scenarios are not as niche for .NET platform as they are for other languages in this category.


You can embed JVM with JNI_CreateJavaVM(): https://docs.oracle.com/javase/7/docs/technotes/guides/jni/s...

It is used used by projects like Postgres PL/Java, LibreOffice and various native Java launchers/wrappers


Dynamic libraries come to mind.


You have to recompile for every architecture and OS, and no security features.


> Go has never focused on binary size and probably never will unless it actually becomes an issue for Google.

The Go project moved to being community directed quite a few years ago. The community hasn't shown it desperately needs smaller binaries either, though. It'd take them, I'm sure, but there are more important concerns.

> That's the disadvantage of having a corporate BDFL I guess.

Even if we, for the sake of discussion, assumed that Google still only specs the language for Google needs, there shouldn't be anything in the specification that necessitates large binaries. tinygo has shown that they can be small. And now that Microsoft has its own Go compiler, Google isn't the only deep pockets involved either. But so long as it is not seen as a pressing concern there isn't apt to be anyone to step up and put in the work to close the gaps.


The Microsoft Go distribution is a special build for FIPS 140-2 compliance (replacing some TLS / crypto libraries and such). I do not believe that there are plans to make any other changes here.


> why is Go compelling as a source language for WASM?

"Compelling" has nothing to do with it. People write Go code (or have already written it) and want to run in Wasm, just like they want to run it in any other environment. It's as simple as that.

Your question is equivalent to "why do people want to write Go?".


> I guess my question is, why is Go compelling as a source language for WASM?

I'm using WASM as a proper plugin architecture for some of my go applications. I provide an interface that allows external developers to create plugins (in whatever language supports WASM as a bonus). Then my application can then use these plugins to execute some extra functionality. It slows the application startup a little but runs pretty fast when in use, but I don't have plugins in any hot paths (yet).


Sounds interesting. What context? How can I imagine this?



I can think of a few (nothing super compelling though):

* “batteries-included” std - some of this is platform APIs, so only really the pure stuff. You can use all of this in the wasm extension, whereas you’d need to pull in deps for JS.

* Non-browser use cases (dynamic extensions, cross-platform “binaries”, cloud functions etc)

* probably the same reasons that JS/NodeJS became popular on the backend, but with roles reversed.


I used this in a previous role. The answer is, we had a server side solution that we wanted to make available on clients that had no internet connection. The logic was complex, and this allowed us to ship much faster.


> I guess my question is, why is Go compelling as a source language for WASM?

It's not currently: https://github.com/golang/go/issues/71134


Go binary size is not an issue, especially where the discussions is not related to browsers.


The use case is: "people who will waste days trying to not learn anything new".

The entire idea o nodejs is that.


Go is also a lot slower in wasm than non-gc languages due to its runtime requirements. I believe the wasm gc spec does not really help Go either so there won't be significant performance gains. It's a shame but it is what it is.

I have been playing with different languages in wasm and I settled on zig which does wasm pretty fine.


In practice, I've very rarely seen a downside: I compare it to something like Vite, where it uses esbuild in development and rollup in production, because the two libraries are for different things (esbuild doesn't bundle, rollup does, etc).

In development, I compile it with Go. In production, I compile it with TinyGo. Yes, you need to be careful about imports, and it does add complexity, but the benefits of not managing two different completely different languages (JS and whatever you're compiling to WASM) far outweigh that cost.

As for Cloudflare, I don't think their service's benefits outweigh the complexity, but I've had luck in the past with the dual setup on Workers.


ESBuild is a bundler. The subtitle on the website is literally “An extremely fast bundler for the web”. To bundle, pass —-bundle flag.

https://esbuild.github.io/


Yep! You're right, it does have the ability to bundle -- that's my bad. Rollup is just much better at bundling for production, just like TinyGo. Similarly, esbuild is better for development, just like Go.

A good rundown (rolldown) is available here: https://rolldown.rs/about


Agreed this is a big downside. It rules out go for websites (except maybe the biggest web “apps”) where load time isn’t important.

But being able to deploy a Go app to Cloudflare or other wasi runtimes is still really nice to have.


You can run the Go compiled wasm binary through wasm-opt (https://github.com/WebAssembly/binaryen) and it will decrease the size and give back some of the performance lost by using the standard go compiler over TinyGo. Fair warning it's pretty slow, and fun fact tinygo passes it's wasm files through wasm-opt which is why the tinygo compilation feels especially slow, I believe this can possibly be disabled via flag.


This is awesome. Something to keep in mind[0]:

> Remember that all the webassembly work in Go has been designed and implemented by volunteers, not the Go team, so timelines are dependent on availability of volunteers.

[0]: https://github.com/golang/go/issues/65333#issuecomment-22336...


Seems to me like it would have been more "Go" to simply export all functions starting with a capital letter in the main package, as exporting works normally in the language, only resorting to the compiler directive when you need to specifically name something starting with lowercase.

Apparently this is just copying the existing way cgo exports work. Fair enough I guess, prior art. The ergonomics are just a little outside the language as usual.


No mention of working with the WASM component model.


This addition unlocks the ability to use Go with the component model. The component model layers on top of Wasm Modules - a module which imports and exports functions with the component model ABI can be turned into a component using e.g. `wasm-tools component new`, and that transformation can include adapting wasip1 interfaces to wasip2. Without support for declaring export functions besides `main`, Go could only target the wasip2 CLI command world, but this enables it to target any component model world.


Correct, this looks like wasip1 support only for now. Discussion thread here[0].

Might be for the best, with wasip3 just around the corner.

[0]: https://github.com/golang/go/issues/66984#issuecomment-20762...


Feel free to elaborate, because I have never heard about it either.


From the wasi.dev[0] front page:

> WASI can be implemented by both core Wasm modules and applications built according to the Component Model, a specification for Wasm applications that are interoperable and composable. You can learn more about components in the Bytecode Alliance's WebAssembly Component Model documentation[1].

[0]: https://wasi.dev/ [1]: https://component-model.bytecodealliance.org/


I thought that WASI and the component model were separate specs. Am I wrong?


WASIp2 implies component model. WASIp2 is implemented using component model.


I see, thank you. I'm trying to get up to speed with the whole ecosystem as I have a use case for it. I would like to interact with WASM components from a go binary, but it seems like wazero doesn't and won't support the component model anytime soon. The rust tooling seems more mature ATM :(


At some point Wazero will have to support component model, regardless of their opinion about it. Otherwise they will lose any relevance.

But I agree with you, the tooling is very immature.


It's not just a matter of opinion, but resource allocation.

WASI preview 1 was already a significant effort. It is the least polished bit of the wazero implementation, but even compared to: a spec compliant interpreter, two compilers and runtime, it weighs. It has some issues around filesystem sandboxing. And portability to “everywhere Go runs” is a pain.

Preview 2 is a significant departure, with little promise that preview 3 isn't another, ad nauseam. For a small team, that's hard to track.

Wasm 1.0 is a useful spec; Wasm 2.0 is still a draft. wazero supports everything final from 2.0 so far.

WASIp1 was useful too, but wazero is useful without WASI.

Until the dust settles, I'd rather wazero was reworked to make WASI even more pluggable from the outside (there are two impls already), than invest more resources in the WASI implementation itself.

Still, if anyone wants to fund fulltime work on this, I guess that can be arranged.


no it will not. Wazero will likely never do that.


Great, there are other Wasm runtimes to choose from.


of course not - Go has taste and appreciates quality and simplicity.


The WASM IDL for components (WIT) seems sleek enough.


its fine, I prefer ours more oriented around a familiar format like OpenAPI

https://github.com/dylibso/xtp-bindgen


I may be misremembering but wasn't it already possible to export go functions to js before go 1.24? I distinctly remember being able to call exported go functions in js without issues in prior. It would be really helpful if someone could explain to me how the new wasi niceties improve on what we had before (beyond supporting more types accross the ffi)?

Second question: it was possible for me to extract strings and other complex types from the wasm module's instance memory by casting pointers to integers, returning those integers to js, then using those values as an offset. If the binary representation of my types is guaranteed to be stable in go, is this method of passing pointers to js still viable for wasm modules produced when passing goos=wasip1?


MoonBit looks like a promising language for WASM. They have WASM-GC and produce quite tiny code size. https://www.moonbitlang.com/


How does garbage collection work with Go and WASM?


not sure what's the current status of Go so there are two alternatives:

if they are targeting Wasm pre Wasm-GC then they have to ship their GC in the Wasm module and it can't interoperate with "the outside world"

if they use Wasm-GC then they use the host's GC and values can be shared with the host and other guests.


No, Go can never use WasmGC because Go has interior pointers. Not even fat pointers help because Go has unboxed types.

Go will continue to use its own GC for the foreseeable future.


Interesting. Can it collect garbage _concurrently_ in WASM?


Last I checked WASM applications are single threaded, not sure if that's changed. GC is concurrent, but not parallelized.


Just the same as it works on amd64 or arm64 or any other architecture.


You mean inside another thread, collecting garbage concurrently? I'd be very surprised if it worked that way.


I am kind of worried that the eagerness for more WASM features may irremediably harm the young ecosystem. Most of what Go added to WASM could be done natively if the component model proposal [1] was merged already.

The standard evolves slowly and as adoption rises we risk having to support more and more non-standard features forever, like WASI and now this.

[1] https://github.com/WebAssembly/component-model


The component model is... part of WASI, so that criticism doesn't make any sense.

When Go adds support for WASI Preview 2 (or 3), it will have no choice but to support component model. The way WASI Preview 2 works is by making use of the component model.


if Go supports it. I do not believe it is likely. There will still be no native Go runtime to execute components. No one is using WASI p2.


Predicting things is hard, especially about the future, that being said, the people doing the Wasm work for Go want to move to the component model.


ok. it’s on the brink of collapse. Bytecode Alliance is basically comprised of near-dead startups and one or two large corporates who do not care about it.


Considering the near complete overlap of people comprising the Bytecode Alliance with the people who created WebAssembly and people who maintain WebAssembly (especially the formal specification), I very much doubt that the Bytecode Alliance is in any sort of immediate danger. That said, you are right that corporations don't care about it, with some corporations even working against it.


the active overlap is basically 1 person.


do you need a disclaimer to your comments that you work on a product (XTP Bindgen) that is basically competing with the WASI component model? I don't care for either but thought the transparency was necessary.


How do you debug WASM modules that are running in a host program?


In v8 environments like browser or node, source maps work, so if you inject console.trace you can get printf debugging w/ legible stack traces on each log line, at least that’s my experience with c code compiled with Emscripten.

According to this 2020 blog post from Google, the Chrome debugger appears to have pretty full featured support for interactive debugging, although I’ve never needed to use it. https://developer.chrome.com/blog/wasm-debugging-2020


Unfortunately Go doesn’t support exporting DWARF for WASM atm, so printf is the only option.

https://github.com/golang/go/issues/33503


the one true debugging method: printf debug


Poorly. The tooling is very bad. But to be fair, this is not specific to Go.


If there only was a low level language that came with strong typing and excellent wasm support...


And an excellent standard library with first class coroutine support and garbage collection?


let's agree to have different tastes, my dear gentleman


Zig is great too. But different audiences imo.


every language has a little bit different audiences. Haven't tried zig myself but I respect it (more than go... :D) and wanna check out some time - any recommendation to get an introduction (sth. like rust language book)?


Companies like Figma have been doing that for years.


doing what?


[flagged]


Uppercase for exported is actually one of my favorite go features.

https://cs.opensource.google/go/go/+/refs/tags/go1.24.0:src/...

https://www.compart.com/en/unicode/category/Lu

there are plenty of non-latin scripts that have upper case letters.




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

Search: