Qualified identifiers

September 15, 2023

One of the features of Go I found most discomforting when I started using the language, was that of qualifiers. Depending on which previous languages you may have experience with, you may find them perfectly natural, or entirely strange. Let’s see what they are…

Qualified identifiers

A qualified identifier is an identifier qualified with a package name prefix. Both the package name and the identifier must not be blank.

QualifiedIdent = PackageName "." identifier .

A qualified identifier accesses an identifier in a different package, which must be imported. The identifier must be exported and declared in the package block of that package.

math.Sin // denotes the Sin function in package math

Let’s illustrate with a complete (but trivial) example. Suppose we have a package foo:

package foo

const Foo = "the fooiest"

Now to the exported symbol Foo from another package, we need to both import the foo package, and use a qualified identifier:

package main

import "foo"

var x = foo.Foo

By way of comparison, this the rough equivalent of the following in JavaScript, which doesn’t use qualifiers.

import { foo } from "foo";

var x = foo;

As an aside, you can avoid the use of qualified identifiers in Go by using “dot imports”, but it’s generally frowned upon (and I honestly wish this wasn’t possible). Please don’t do this, but here’s what it would look like:

package main
import . "foo"

var x = Foo

Quotes from The Go Programming Language Specification Version of August 2, 2023


Share this

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

Unsure? Browse the archive .

Related Content


Uniqueness of identifiers

Uniqueness of identifiers Given a set of identifiers, an identifier is called unique if it is different from every other in the set. Two identifiers are different if they are spelled differently, or if they appear in different packages and are not exported. Otherwise, they are the same. This is pretty simple stuff, but it’s obviously worth being explicit. foo and bar are obviously different identifiers. Further, a in package foo, and a in package bar are different identifiers, because although they are spelled the same, they are not exported, and are in different packages.


An example package

Today we have something a bit different. Just a sample package. An example package Here is a complete Go package that implements a concurrent prime sieve. package main import "fmt" // Send the sequence 2, 3, 4, … to channel 'ch'. func generate(ch chan<- int) { for i := 2; ; i++ { ch <- i // Send 'i' to channel 'ch'. } } // Copy the values from channel 'src' to channel 'dst', // removing those divisible by 'prime'.


Blank imports & import side effects

Yesterday I promised to teach you the one dirty trick they don’t want you to know about, to get around Go’s restriction on circular imports. It’s explained in this sentence, the last from the spec on the topic of imports. Import declarations … To import a package solely for its side-effects (initialization), use the blank identifier as explicit package name: import _ "lib/math" Did you catch it? It’s very subtle.

Get daily content like this in your inbox!

Subscribe