Bootstrapping

September 27, 2024

A quick note to say that I’m taking next week off, for a move. I expect to return October 4 with more Boldy Go: Daily emails. Until then!


We’re down to the final two built-in functions in Go. And these are probably functions you should not be using, except possibly in throw-away test code or during debugging.

Bootstrapping

Current implementations provide several built-in functions useful during bootstrapping. These functions are documented for completeness but are not guaranteed to stay in the language. They do not return a result.

Function   Behavior

print      prints all arguments; formatting of arguments is implementation-specific
println    like print but prints spaces between arguments and a newline at the end

Implementation restriction: print and println need not accept arbitrary argument types, but printing of boolean, numeric, and string types must be supported.

So if you’re not supposed to use these, why do they exist? And what should you use instead?

Well, as the section title implies, these functions exist largely for historical reasons, and were used during the bootstrapping of the language. Before the fmt package existed (more on that in a moment), it was handy to have a simple way to print out debug messages. Thus print and println. They’re still often useful for such things. Especially if you don’t want to bloat your code by importing fmt—a concern mostly reserved for embedded systems, since it’s otherwise virtually impossible to build a Go program that doesn’t import fmt.

So what do you use instead? The fmt package provides a number of alternatives, which are much more flexible and appropriate for normal use.

fmt.Print and fmt.Println are the direct replacements for print and println, respectively:

fmt.Print("Hello, ")
fmt.Println("世界", 123, true)
print("Hello, ")
println("世界", 123, true)

outputs:

Hello, 世界 123 true
Hello, 世界 123 true

Addtionally, the fmt family of functions support many more types than the built-in functions do:

var x struct{}
fmt.Print(x) // {}
print(x)     // illegal types for operand: print struct {}

What’s more, these functions could, in theory, be removed from the language in the future. So best not to rely on them. 😁

Quotes from The Go Programming Language Specification Language version go1.23 (June 13, 2024)


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Context cancelation

As already mentioned, the context.Context type serves two purposes: It manages cancelation signals, and it allows passing request-scoped data. In my opinion, these two purposes are distinct enough that they probably should be handled by two separate mechanisms. But alas, that’s not what we have. However, I think it’s still useful to think of the two uses as distinct. Most often (at least in a well-designed application), the primary purpose of a context is the propegation of cancelation signals.


Context plumbing

Monday we looked at a very high-level view of what problems the context package is meant to solve. Namely, to propagate cancelation signales and/or request-scoped values through the call stack of an application. Today we’ll take a brief look at how context “plumbing” works—and answer they why of all those mysterious context.Context function parameters you’ve probably seen, being passed around more than a virus in a daycare. Overview … Incoming requests to a server should create a Context, and outgoing calls to servers should accept a Context.


context

Hey! My apologies for being absent for the last few weeks. I’ve been incredibly busy closing on a new house and moving. We’re still settling, but it’s time to start this up again. So today I’m starting a short series on context! Specifically, I’ll be going through the context package in the standard library, explaining what it does, and offering my advice, much like I went through the Go spec in the past.

Get daily content like this in your inbox!

Subscribe