Constant types

July 11, 2023

Long-time readers may recall that constants may be typed or untyped. Today we expore the details of how such constants are declared.

Constant declarations

If the type is present, all constants take the type specified, and the expressions must be assignable to that type, which must not be a type parameter. If the type is omitted, the constants take the individual types of the corresponding expressions. If the expression values are untyped constants, the declared constants remain untyped and the constant identifiers denote the constant values. For instance, if the expression is a floating-point literal, the constant identifier denotes a floating-point constant, even if the literal’s fractional part is zero.

const Pi float64 = 3.14159265358979323846
const zero = 0.0         // untyped floating-point constant
const (
	size int64 = 1024
	eof        = -1  // untyped integer constant
)
const a, b, c = 3, 4, "foo"  // a = 3, b = 4, c = "foo", untyped integer and string constants
const u, v float32 = 0, 3    // u = 0.0, v = 3.0

While the quoted examples are fairly thorough, they aren’t as explicit as I might like, so let me offer my own examples.

First, the simplest constant declaration leaves us with an untyped constant, and includes just the name and value:

const foo = 1 // Untyped numeric constant

We can add an explicit type to get a typed constant:

const foo int = 1

We can also declare multiple constants together:

const foo, bar = 1, "thing" // Untyped numeric and untyped string constant

If we add a type to such a multi-declaration, though, it applies to all constants in the list:

const foo, bar int = 1, "thing" // Invalid, because "thing" cannot be assigned int

You can still group constants of different types in a single const cluase, however:

const (
  foo int = 1          // typed int const
  bar string = "thing" // typed string const
  baz = 0.0            // Untyped float const
)

Quotes from The Go Programming Language Specification Version of December 15, 2022

Share this

Related Content

Declaring variable types

Today I’ll be love coding again. I hope you can join me! I’ll be working on the backlog for my open-source CouchDB SDK, https://kivik.io/. First some light refactoring, then adding a long-missing feature. Join me to see how many mistakes a senior Go dev makes while coding. We ended last week with a look at variable declarations. Today we continue that, with a look at how a variable’s type is determined.

Constants, typed vs untyped

Constants … Constants may be typed or untyped. Now that’s interesting. And powerful. This is one of the features of Go I featured in my recent video 10 Reasons I Like Go. This feature really helps bridge the gap between the convenience of dynamically typed languages, and the safety of statically typed languages. Let’s look at the details… Literal constants, true, false, iota, and certain constant expressions containing only untyped constant operands are untyped.

Zero values of slices and maps

Composite literals … Note that the zero value for a slice or map type is not the same as an initialized but empty value of the same type. Let’s look at examples so we can understand exactly what is being stated here. Recall that when you declare a variable of a given type, the default value is the zero value for the type: var s1 []string // Zero value for slice var m1 map[string]int // Zero value for map What the spec is telling us is that the zero value of a slice or map is not the same as an initialized, but empty, slice or map: