Constants

Welcome to tutorial no. 5 in our Golang tutorial series.

What is a constant?

The term constant in Go is used to denote fixed values such as

95  
"I love Go" 
67.89  

and so on.

Declaring a constant

The keyword const is used to declare a constant. Let's see how to declare a constant using an example.

package main

import (  
    "fmt"
)

func main() {  
    const a = 50
    fmt.Println(a)
}

Run in playground

In the above code a is a constant and it is assigned the value 50.

Declaring a group of constants

There is also another syntax to define a group of constants using a single statement. An example to define a group of constants using this syntax is provided below.

package main

import (  
    "fmt"
)

func main() {  
    const (
        name = "John"
        age = 50
        country = "Canada"
    )
    fmt.Println(name)
    fmt.Println(age)
    fmt.Println(country)

}

Run in playground

In the above program, we have declared 3 constants name, age and country. The above program prints,

John  
50  
Canada  

Constants, as the name indicate, cannot be reassigned again to any other value. In the program below, we are trying to assign another value 89 to a. This is not allowed since a is a constant. This program will fail to run with compilation error cannot assign to a.

package main

func main() {  
    const a = 55 //allowed
    a = 89 //reassignment not allowed
}

Run in playground

The value of a constant should be known at compile time. Hence it cannot be assigned to a value returned by a function call since the function call takes place at run time.

package main

import (  
    "math"
)

func main() {  
    var a = math.Sqrt(4)   //allowed
    const b = math.Sqrt(4) //not allowed
}

Run in playground

In the above program, a is a variable and hence it can be assigned to the result of the function math.Sqrt(4) (We will discuss functions in more detail in a separate tutorial).

b is a constant and the value of b needs to be known at compile time. The function math.Sqrt(4) will be evaluated only during run time and hence const b = math.Sqrt(4) fails to compile with error

./prog.go:9:8: const initializer math.Sqrt(4) is not a constant

String Constants, Typed and Untyped Constants

Any value enclosed between double quotes is a string constant in Go. For example, strings like "Hello World", "Sam" are all constants in Go.

What type does a string constant belong to? The answer is they are untyped.

A string constant like "Hello World" does not have any type.

const hello = "Hello World"  

In the above line of code, the constant hello doesn't have a type.

Go is a strongly typed language. All variables require an explicit type.
How does the following program which assigns a variable name to an untyped constant n work?

package main

import (  
    "fmt"
)

func main() {  
    const n = "Sam"
    var name = n
    fmt.Printf("type %T value %v", name, name)

}

Run in playground

The answer is untyped constants have a default type associated with them and they supply it if and only if a line of code demands it. In the statement var name = n in line no. 8, name needs a type and it gets it from the default type of the string constant n which is a string.

Is there a way to create a typed constant? The answer is yes. The following code creates a typed constant.

const typedhello string = "Hello World"  

typedhello in the above code is a constant of type string.

Go is a strongly typed language. Mixing types during the assignment is not allowed. Let's see what this means with the help of a program.

package main

func main() {  
        var defaultName = "Sam" //allowed
        type myString string
        var customName myString = "Sam" //allowed
        customName = defaultName //not allowed

}

Run in playground

In the above code, we first create a variable defaultName and assign it to the constant Sam. The default type of the constant Sam is a string, so after the assignment defaultName is of type string.

In the next line, we create a new type myString which is an alias of string.

Then we create a variable customName of type myString and assign the constant Sam to it. Since the constant Sam is untyped, it can be assigned to any string variable. Hence this assignment is allowed and customName gets the type myString.

Now we have a variable defaultName of type string and another variable customName of type myString. Even though we know that myString is an alias of string, Go's strong typing policy disallows variables of one type to be assigned to another. Hence the assignment customName = defaultName is not allowed and the compiler throws the error ./prog.go:7:20: cannot use defaultName (type string) as type myString in assignment

Boolean Constants

Boolean constants are no different from string constants. They are two untyped constants true and false. The same rules for string constants apply to booleans so we will not repeat them here. The following is a simple program to explain boolean constants.

package main

func main() {  
    const trueConst = true
    type myBool bool
    var defaultBool = trueConst //allowed
    var customBool myBool = trueConst //allowed
    defaultBool = customBool //not allowed
}

Run in playground

The above program is self-explanatory.

Numeric Constants

Numeric constants include integers, floats and complex constants. There are some subtleties in numeric constants.

Let's look at some examples to make things clear.

package main

import (  
    "fmt"
)

func main() {  
    const a = 5
    var intVar int = a
    var int32Var int32 = a
    var float64Var float64 = a
    var complex64Var complex64 = a
    fmt.Println("intVar",intVar, "\nint32Var", int32Var, "\nfloat64Var", float64Var, "\ncomplex64Var",complex64Var)
}

Run in playground

In the program above, the const a is untyped and has a value 5. You may be wondering what is the default type of a and if it does have one, how do we then assign it to variables of different types. The answer lies in the syntax of a. The following program will make things more clear.

package main

import (  
    "fmt"
)

func main() {  
    var i = 5
    var f = 5.6
    var c = 5 + 6i
    fmt.Printf("i's type is %T, f's type is %T, c's type is %T", i, f, c)

}

Run in playground

In the program above, the type of each variable is determined by the syntax of the numeric constant. 5 is an integer by syntax, 5.6 is a float and 5 + 6i is a complex number by syntax. When the above program is run, it prints

i's type is int, f's type is float64, c's type is complex128  

With this knowledge, let's try to understand how the below program worked.

package main

import (  
    "fmt"
)

func main() {  
    const a = 5
    var intVar int = a
    var int32Var int32 = a
    var float64Var float64 = a
    var complex64Var complex64 = a
    fmt.Println("intVar",intVar, "\nint32Var", int32Var, "\nfloat64Var", float64Var, "\ncomplex64Var",complex64Var)
}

Run in playground

In the program above, the value of a is 5 and the syntax of a is generic. It can represent a float, integer or even a complex number with no imaginary part. Hence it is possible to be assigned to any compatible type. The default type of these kinds of constants can be thought of as being generated on the fly depending on the context. var intVar int = a requires a to be int so it becomes an int constant. var complex64Var complex64 = a requires a to be a complex number and hence it becomes a complex constant. Pretty neat :).

Numeric Expressions

Numeric constants are free to be mixed and matched in expressions and a type is needed only when they are assigned to variables or used in any place in code which demands a type.

package main

import (  
    "fmt"
)

func main() {  
    var a = 5.9 / 8
    fmt.Printf("a's type is %T and value is %v", a, a)
}

Run in playground

In the program above, 5.9 is a float by syntax and 8 is an integer by syntax. Still, 5.9/8 is allowed as both are numeric constants. The result of the division is 0.7375 is a float and hence variable a is of type float. The output of the program is

a's type is float64 and value is 0.7375  

This brings us to the end of this tutorial. Please share your valuable feedback and comments.

If you would like to advertise on this website, hire me, or if you have any other development requirements please email to naveen[at]golangbot[dot]com.

Previous tutorial - Types            Next tutorial - Functions

Naveen Ramanathan

Naveen Ramanathan is a software engineer with interests in Go, Docker, Kubernetes, Swift, Python, and Web Assembly. You can contact him by emailing to naveen[at]golangbot[dot]com.