Happy New Year!

January 1, 2025

I’ve been on an unannounced, unplanned, month-long hiatus, what with moving my family across the globe. But with the new year starting, and the worst of the chaos behind me, I’m going to try to get back in the saddle again, and pick up where I left off.


And what better way to initialize 2025 than with talking about init?

Program initialization

Package initialization—variable initialization and the invocation of init functions—happens in a single goroutine, sequentially, one package at a time. An init function may launch other goroutines, which can run concurrently with the initialization code. However, initialization always sequences the init functions: it will not invoke the next one until the previous one has returned.

I think this is pretty clear, and intuitive. As the program initializes each package, any init functions in that package (and remember, there can be more than one per package, or even per file!), are run, one at a time, in a single goroutine.

If you don’t want your program initialization to wait for your init function to complete running, you have the option to launch a go routine from within such a function:

func init() {
  fmt.Println("init 1")
  go func() {
    time.Sleep(time.Second)
    fmt.Println("init 1b")
  }()
}

func init() {
  fmt.Println("init 2")
}

This will output:

init 1
init 2
init 1b

However, be advised that this is almost always a bad idea. First off, just in general, init functions should be used minimally, if at all.

Second, if your init function does something time consuming, and you throw it into a go routine, you need to make sure that there’s a lock of some sort, to ensure that something doesn’t try to use the uninitialized data before it’s ready. Certainly doable, but can be a hassle, hard to debug, and is often (almost always) a sign of a poor architecture. Look for alternatives.


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


Program initialization

I wasn’t exactly planning to take last week off from the daily emails, but with Thanksgiving preparations, and still living out of a suitcase, it just happened that way. But I’m back now, and ready to talk about Program initialization Program initialization The packages of a complete program are initialized stepwise, one package at a time. If a package has imports, the imported packages are initialized before initializing the package itself.


init functions

We’ve been looking at the order of package variable initialization. What if these rules are confusing? Or even non-desterministic for you? Or maybe you simply want to do something more advanced than is feasible in package variable declarations. Is there an alternative? There is! Package initialization … Variables may also be initialized using functions named init declared in the package block, with no arguments and no result parameters. func init() { … } Note that package variables can be initialized, but not declared within an init function.


Program execution

Program execution A complete program is created by linking a single, unimported package called the main package with all the packages it imports, transitively. The main package must have package name main and declare a function main that takes no arguments and returns no value. func main() { … } Program execution begins by initializing the program and then invoking the function main in package main. When that function invocation returns, the program exits.

Get daily content like this in your inbox!

Subscribe