Learn to code by coding - try our free CS courses

Unexpected Printf Behavior in Go WASM – Nothing Prints

While working on Qvault’s Go Playground, I came across a very strange error. The standard library’s fmt.Printf() function prints nothing to the console when called. Nothing.

Take Action and Learn Go

Our ‘Go Mastery’ courses include 160+ interactive coding lessons to give you all the skills you need to become a successful Go developer.

For those of you who are familiar with the function, when compiled to a “normal” executable fmt.Printf prints a formatted string to standard output. As per the official documentation, this program:

package main import ( "fmt" ) func main() { const name, age = "Kim", 22 fmt.Printf("%s is %d years old.", name, age) }
Code language: Go (go)

Will print:

Kim is 22 years old.

The interesting thing is that when the same exact program is compiled using Web Assembly, we get a different result. If you want to try it, copy the above program and run it here.

Spoiler alert: It doesn’t print anything.

However, if you change the program slightly:

package main import ( "fmt" ) func main() { const name, age = "Kim", 22 // add a newline character fmt.Printf("%s is %d years old.\n", name, age) }
Code language: Go (go)

Then it may print the expected:

Kim is 22 years old.

thought if you run the two programs back to back, you may actually find that this is printed instead:

Kim is 22 years old.Kim is 22 years old.
Code language: CSS (css)


When compiled to Web Assembly, the fmt.Printf function is writing to a buffer, and that buffer is not cleared until a newline character is printed to standard out. In other words, you can call fmt.Printf as many times as you want, but nothing is printed until a \n character comes through standard output.

Take a look at the writeSync() code in Go’s wasm_exec.js, which is a required include to execute Go Web Assembly in the browser:

writeSync(fd, buf) { outputBuf += decoder.decode(buf); const nl = outputBuf.lastIndexOf("\n"); if (nl != -1) { console.log(outputBuf.substr(0, nl)); outputBuf = outputBuf.substr(nl + 1); } return buf.length; }
Code language: Go (go)

As you can see, console.log() is only called on the buffer if a newline is found within the output string, otherwise the output is just appended to the stateful outputBuf.

My current working theory is that it was implemented this way because there is no way to print to the console in a browser without appending a newline. JavaScript’s console.log() always appends a newline.

Have questions or feedback?

Follow and hit me up on Twitter @q_vault if you have any questions or comments. If I’ve made a mistake in the article, please let me know so I can get it corrected!

Leave a Comment