Constants

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

What is a constant?

Constants in Go is used to denote fixed static values such as

95 
"I love Go" 
67.89 

and so on. Constants are generally used to represent values that do not change throughout the life time of an application.

Declaring a constant

The keyword const is used to declare a constant in Go. Let’s see how to declare a constant by means an example.

 1package main
 2
 3import (
 4	"fmt"
 5)
 6
 7func main() {
 8	const a = 50
 9	fmt.Println(a)
10}

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.

 1package main
 2
 3import (
 4	"fmt"
 5)
 6
 7func main() {
 8	const (
 9		retryLimit = 4
10		httpMethod = "GET"
11	)
12
13	fmt.Println(retryLimit)
14	fmt.Println(httpMethod)
15}

Run in playground

In the above program, we have declared 2 constants retryLimit and httpMethod. The above program prints,

4
GET

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 (neither addressable nor a map index expression).

1package main
2
3func main() {  
4    const a = 55 //allowed
5    a = 89 //reassignment not allowed
6}

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.

 1package main
 2
 3import (
 4	"fmt"
 5	"math"
 6)
 7
 8func main() {
 9	var a = math.Sqrt(4) //allowed
10	fmt.Println(a)
11	const b = math.Sqrt(4) //not allowed
12	fmt.Println(b)
13}

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:11:12: math.Sqrt(4) (value of type float64) is not 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?

 1package main
 2
 3import (
 4	"fmt"
 5)
 6
 7func main() {
 8	const n = "Sam"
 9	var name = n
10	fmt.Printf("type %T value %v", name, name)
11
12}

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. 9, 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 name string = "Hello World"

name 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.

 1package main
 2
 3import "fmt"
 4
 5func main() {
 6	var defaultName = "Sam" //allowed
 7	type myString string
 8	var customName myString = "Sam" //allowed
 9	customName = defaultName        //not allowed
10	fmt.Println(customName)
11}

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:9:15: cannot use defaultName (variable of type string) as myString value in assignment

To make the above program work, defaultName must be converted to type myString. This is done in the following program in line no. 9

 1package main
 2
 3import "fmt"
 4
 5func main() {
 6	var defaultName = "Sam" //allowed
 7	type myString string
 8	var customName myString = "Sam"    //allowed
 9	customName = myString(defaultName) //allowed
10	fmt.Println(customName)
11}

Run in playground

The above program will print Sam

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.

1package main
2
3func main() {
4	const trueConst = true
5	type myBool bool
6	var defaultBool = trueConst //allowed
7	var customBool myBool = trueConst //allowed
8	defaultBool = customBool //not allowed
9}

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.

 1package main
 2
 3import (
 4	"fmt"
 5)
 6
 7func main() {
 8	const c = 5
 9	var intVar int = c
10	var int32Var int32 = c
11	var float64Var float64 = c
12	var complex64Var complex64 = c
13	fmt.Println("intVar", intVar, "\nint32Var", int32Var, "\nfloat64Var", float64Var, "\ncomplex64Var", complex64Var)
14}

Run in playground

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

 1package main
 2
 3import (
 4	"fmt"
 5)
 6
 7func main() {
 8	var i = 5
 9	var f = 5.6
10	var c = 5 + 6i
11	fmt.Printf("i's type is %T, f's type is %T, c's type is %T", i, f, c)
12}

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.

 1package main
 2
 3import (
 4	"fmt"
 5)
 6
 7func main() {
 8	const c = 5
 9	var intVar int = c
10	var int32Var int32 = c
11	var float64Var float64 = c
12	var complex64Var complex64 = c
13	fmt.Println("intVar", intVar, "\nint32Var", int32Var, "\nfloat64Var", float64Var, "\ncomplex64Var", complex64Var)
14}

Run in playground

In the program above, the value of c is 5 and the syntax of c 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 based on the context where they are used. var intVar int = c requires c to be int so it becomes an int constant. var complex64Var complex64 = c requires c 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.

 1package main
 2
 3import (
 4	"fmt"
 5)
 6
 7func main() {
 8	var a = 5.9 / 8
 9	fmt.Printf("a's type is %T and value is %v", a, a)
10}

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.

I hope you liked this tutorial. Please leave your feedback and comments. Please consider sharing this tutorial on twitter or LinkedIn. Have a good day.

Previous tutorial - Types            Next tutorial - Functions