There are two identifiers that we can use in Go that do not create a binding to a thing…
Declarations and scope
…
The blank identifier may be used like any other identifier in a declaration, but it does not introduce a binding and thus is not declared. In the package block, the identifier
init
may only be used forinit
function declarations, and like the blank identifier it does not introduce a new binding.
We’ve talked about the blank identifier before in other contexts. In this context, what matters is that we can use the blank identifier for things that would normally be bound to a scope, such as within a file or function. The use of the blank identifier means that the result that would have been bound to a named identifier, is instead discarded. No binding takes place. And the blank identifier can be repeated ad nauseam without risk of re-declaring or shadowing.
func getAnswer() string {
// The second value, an error, is discarded
answer, _ := readAnswerFromSource()
return answer
}
What many don’t realize is that init
follows similear rules. init
isn’t ignored the same way that _
is, but it doesn’t bind to anything, making it a special case of a function name that can be repeated. This is perfectly valid within the same package, or even the same file:
package main
import "fmt"
func main() {
}
func init() {
fmt.Println("init 1")
}
func init() {
fmt.Println("init 2")
}
Output:
init 1
init 2
See it on the playground.
Quotes from The Go Programming Language Specification Version of December 15, 2022