Welcome To Golang By Example

Constant in Go (Golang)

This is the  chapter 9 of the golang comprehensive tutorial series. Refer to this link for other chapters of the series – Golang Comprehensive Tutorial Series

Next Tutorial – For Loop
Previous Tutorial –Functions

Now let’s check out the current tutorial. Below is the table of contents for current tutorial.

Overview

A constant is anything that doesn’t change its value. In Go const can be either of type string, numeric, boolean, and characters.

A constant can be declared using the const keyword. A important point to be noted is that the value has to be assigned while declaring a constant. It is unlike variables where value can be assigned later.

const c string = "circle"
const c = "circle"
const (
  c = "circle"
  s = "square"
)

Important Points

package main
func main() {
    const a int = 8
    a = 9
}

Error:

main.go:5:4: cannot assign to a
package main
const name = "test"
func main() {
    const a = getValue()
}
func getValue() int {
    return 1
}

Error:

const initializer getValue() is not a constant
package main
import "fmt"
const a = 123
func main() {
    const a = 456
    fmt.Println(a)
}

Output:

456

Typed and Untyped Constants

Now coming to very important topic. In go constant are treated in a different way than any other language. GO has a very strong type system that doesn’t allow implicit conversion between any of the types. Even with the same numeric types no operation is allowed without explicit conversion. For eg you cannot add a int32 and int64 value. To add those either int32 has to be explicitly converted to int64 or vice versa. However untyped constant have the flexibility of temporary escape from the GO’s type system as we will see in this article

Typed Constant

A const declared specifying the type in the declaration is a typed constant. For example below we are declaring a const of type int32

const a int32 = 8

This const a can only be assigned to a variable of type int32. If you assign it to a variable of any other type it will raise an error . For the illustration see below program.

package main

func main() {
    const a int32 = 8

    var i1 int32
    var i2 int64

    i1 = a
    i2 = a
}

Output:

cannot use a (type int32) as type int64 in assignment

Untyped Constant

An untyped constant is a constant whose type has not been specified. A untyped constant in GO can be either named or unnamed. In both cases it doesn’t have any type associated with it.

Examples of unnamed untyped constant.

123        //Default hidden type is int
"circle"   //Default hidden type is string
5.6.       //Default hidden type is float64
true       //Default hidden type is bool
'a'        //Default hidden type is rune
3+5i       //Default hidden type is complex128

Examples of named untyped constant

const a = 123        //Default hidden type is int
const b = "circle"   //Default hidden type is string
const c = 5.6       //Default hidden type is float64
const d = true       //Default hidden type is bool
const e = 'a'        //Default hidden type is rune
const f = 3+5i       //Default hidden type is complex128

Untyped constant  does have a default hidden type. For example below table illustrates hidden default types for numerics, strings, characters and boolean

Default Hidden type for Constants

Integersint
Floatsfloat64
Complex Numberscomplex128
Stringsstring
Booleansbool
Charactersint32 or rune

When you print any untyped constant using fmt.Printf it will print the default hidden type. See below program and output for both unnamed and named  untyped constant.

package main

import "fmt"

func main() {
    //Unanamed untyped constant
    fmt.Printf("Type: %T Value: %v\n", 123, 123)
    fmt.Printf("Type: %T Value: %v\n", "circle", "circle")
    fmt.Printf("Type: %T Value: %v\n", 5.6, 5.6)
    fmt.Printf("Type: %T Value: %v\n", true, true)
    fmt.Printf("Type: %T Value: %v\n", 'a', 'a')
    fmt.Printf("Type: %T Value: %v\n", 3+5i, 3+5i)

    //Named untyped constant
    const a = 123      //Default hidden type is int
    const b = "circle" //Default hidden type is string
    const c = 5.6      //Default hidden type is float64
    const d = true     //Default hidden type is bool
    const e = 'a'      //Default hidden type is rune
    const f = 3 + 5i   //Default hidden type is complex128

    fmt.Println("")
    fmt.Printf("Type: %T Value: %v\n", a, a)
    fmt.Printf("Type: %T Value: %v\n", b, b)
    fmt.Printf("Type: %T Value: %v\n", c, c)
    fmt.Printf("Type: %T Value: %v\n", d, d)
    fmt.Printf("Type: %T Value: %v\n", e, e)
    fmt.Printf("Type: %T Value: %v\n", f, f)
}

Output:

Type: int Value: 123
Type: string Value: circle
Type: float64 Value: 5.6
Type: bool Value: true
Type: int32 Value: 97
Type: complex128 Value: (3+5i)

Type: int Value: 123
Type: string Value: circle
Type: float64 Value: 5.6
Type: bool Value: true
Type: int32 Value: 97
Type: complex128 Value: (3+5i)

The above program prints int32 instead of rune as rune is an alias for int32

The default type of a named or unnamed constant type will become type of a variable they are assigned to . For example in below code variable a will get its  type from  the default type of unnamed constant 123 which is int.

var a = 123

Let’s see a program illustrating above points for all unnamed type constant

package main
import "fmt"
func main() {
    //Untyped
    var u = 123      //Default hidden type is int
    var v = "circle" //Default hidden type is string
    var w = 5.6      //Default hidden type is float64
    var x = true     //Default hidden type is bool
    var y = 'a'      //Default hidden type is rune
    var z = 3 + 5i   //Default hidden type is complex128
    fmt.Printf("Type: %T Value: %v\n", u, u)
    fmt.Printf("Type: %T Value: %v\n", v, v)
    fmt.Printf("Type: %T Value: %v\n", w, w)
    fmt.Printf("Type: %T Value: %v\n", x, x)
    fmt.Printf("Type: %T Value: %v\n", y, y)
    fmt.Printf("Type: %T Value: %v\n", z, z)
}

Output

Type: int Value: 123
Type: string Value: circle
Type: float64 Value: 5.6
Type: bool Value: true
Type: int32 Value: 97
Type: complex128 Value: (3+5i)

Now the question which comes to the mind is what is the use of untyped constant.  The use of untyped constant is that the type of the constant will be decided depending upon the type of variable they are being assigned to.  Sounds confusing? Let’s see with an example.

Pi constant value in math package is declared as below.

const Pi = 3.14159265358979323846264338327950288419716939937510582097494459

Notice that the type is not specified it only has a hidden default type (which is float64 here).  Let’s see a code

package main
import (
    "fmt"
    "math"
)
func main() {
    var f1 float32
    var f2 float64
    f1 = math.Pi
    f2 = math.Pi

    fmt.Printf("Type: %T Value: %v\n", math.Pi, math.Pi)
    fmt.Printf("Type: %T Value: %v\n", f1, f1)
    fmt.Printf("Type: %T Value: %v\n", f2, f2)
}

Output

Type: float64 Value: 3.141592653589793
Type: float32 Value: 3.1415927
Type: float64 Value: 3.141592653589793

Notice the above program.

Depending upon use case an untyped constant can be assigned to a low precision type (float32) or a high precision type(float64)

Naming Conventions

Naming conventions for constant is the same as naming conventions for variables.

Global Constant

Like any other variable, a constant will be global within a package if it is declared at the top of a file outside the scope of any function. For example, in the below program name will be a global constant available throughout the main package in any function. Do note that the const name will not be available outside the main package. For it to be available outside the main package it has to start with a capital letter.

See the below code. It also shows the example of a local constant within a package.

package main

import "fmt"

const name = "test"

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

func testGlobal() {
    fmt.Println(name)
    //The below line will give compiler error as a is a local constant
    //fmt.Println(a)

Types of Constants

Constant can be of four types:

String Constant

In go string constant is represented in two ways

Below program shows a example of a

package main

import "fmt"

func main() {
	type myString string

	//Typed String constant
	const aa string = "abc"
	var uu = aa
	fmt.Println("Untyped named string constant")
	fmt.Printf("uu: Type: %T Value: %v\n\nn", uu, uu)

	//Below line will raise a compilation error
	//var v myString = aa

	//Untyped named string constant
	const bb = "abc"
	var ww myString = bb
	var xx = bb
	fmt.Println("Untyped named string constant")
	fmt.Printf("ww: Type: %T Value: %v\n", ww, ww)
	fmt.Printf("xx: Type: %T Value: %v\n\n", xx, xx)

	//Untyped unnamed string constant
	var yy myString = "abc"
	var zz = "abc"
	fmt.Println("Untyped unnamed string constant")
	fmt.Printf("yy: Type: %T Value: %v\n", yy, yy)
	fmt.Printf("zz: Type: %T Value: %v\n", zz, zz)

}

Output:

Untyped named string constant
uu: Type: string Value: abc

nUntyped named string constant
ww: Type: main.myString Value: abc
xx: Type: string Value: abc

Untyped unnamed string constant
yy: Type: main.myString Value: abc
zz: Type: string Value: abc

In the above program, we created a new type myString in code.

type myString string

Also above program shows the example of

Let’s understand each of them and their behaviour

Typed string constant

It is defined as below

const aa string = "abc"

Notice in above that below line will cause a compilation error. This is because of typed string constant aa is of type string. So below line will cause compilation error as it cannot be assigned to variable of type myString

var v myString = aa

But typed string constant can be assigned to a variable created with var keyword like below

var uu = aa

Untyped named string constant

It is defined as below

const bb = "abc"

Untyped named string constant can be assigned to variable of type myString as well variable created with var keyword because it is untyped so type of the constant will be decided depending upon the type of variable they are being assigned to.

var ww myString = bb
var xx = bb

Untyped unnamed string constant.

It is like below

abc

Untyped unnamed string constant can be assigned to variable of type myString as well variable created with var keyword because it is untyped so type of the constant will be decided depending upon the type of variable they are being assigned to.

var yy myString = "abc"
var zz = "abc"

Numeric Constant

Numeric constant are further divided into three types

A untyped integer constant (both named and unnamed) can be assigned to int types, float types and complex . This is because an int value can be int or float or complex. For eg int value 123 can be

On the basis of similar logic an untyped float constant can be assigned to all floats and complex types but not integer because for eg a float 5.3 cannot be an integer.

On the basis of similar logic, an untyped complex constant can be assigned to  complex types but not integer and float because for eg a float 5i+3 cannot be an integer or a float

See below program illustrating the above point. In the program we have example for

package main

import "fmt"

func main() {
	//Typed int constant
	const aa int = 123
	var uu = aa
	fmt.Println("Typed named integer constant")
	fmt.Printf("uu: Type: %T Value: %v\n\n", uu, uu)

	//Below line will raise a compilation error
	//var v int32 = aa

	//Untyped named int constant
	const bb = 123
	var ww = bb
	var xx int32 = bb
	var yy float64 = bb
	var zz complex128 = bb
	fmt.Println("Untyped named integer constant")
	fmt.Printf("ww: Type: %T Value: %v\n", ww, ww)
	fmt.Printf("xx: Type: %T Value: %v\n", xx, xx)
	fmt.Printf("yy: Type: %T Value: %v\n", yy, yy)
	fmt.Printf("zz: Type: %T Value: %v\n\n", zz, zz)

	//Untyped unnamed int constant
	var ll = 123
	var mm int32 = 123
	var nn float64 = 123
	var oo complex128 = 123
	fmt.Println("Untyped unnamed integer constant")
	fmt.Printf("ll: Type: %T Value: %v\n", ll, ll)
	fmt.Printf("mm: Type: %T Value: %v\n", mm, mm)
	fmt.Printf("nn: Type: %T Value: %v\n", nn, nn)
	fmt.Printf("oo: Type: %T Value: %v\n", oo, oo)
}

Output

Typed named integer constant
uu: Type: int Value: 123

Untyped named integer constant
ww: Type: int Value: 123
xx: Type: int32 Value: 123
yy: Type: float64 Value: 123
zz: Type: complex128 Value: (123+0i)

Untyped unnamed integer constant
ll: Type: int Value: 123
mm: Type: int32 Value: 123
nn: Type: float64 Value: 123
oo: Type: complex128 Value: (123+0i)

Now above program shows example of a

Let’s understand each of them and their behavior

Typed integer constant

It is defined as below

const aa int = 123

Typed integer constant can be assigned to a variable created with var keyword like below

var uu = aa

It will raise compilation error when assigned to another int type. So below raises compilation error as aa variable is already of type int

var v int32 = aa

Untyped named integer constant

It is defined as below

const bb = 123

Untyped named integer constant can be assigned to any int type, any float type and any complex number type and also to any variable created with var keyword. So below works

var ww = bb
var xx int32 = bb
var yy float64 = bb
var zz complex128 = bb

Untyped unnamed integer constant

It is as below

123

Untyped named integer constant can be assigned to any int type, any float type and any complex number type and also to any variable created with var keyword. So below works

var ww = 123
var xx int32 = 123
var yy float64 = 123
var zz complex128 = 123

Numeric Expressions

Due to untyped nature of constant numeric constants, different numeric constant type can be mixed and matched up to form a expression

package main
import "fmt"
func main() {
    var p = 5.2 / 3
    fmt.Printf("p: Type: %T Value: %v\n", p, p)
}

Output:

p: Type: float64 Value: 1.7333333333333334

Boolean Constant

There are two untyped boolean constant true and false.  Below is the program illustrating a boolean constant. 

package main

import "fmt"

func main() {
	type myBool bool

	//Typed Boolean constant
	const aa bool = true
	var uu = aa
	fmt.Println("Typed named boolean constant")
	fmt.Printf("uu: Type: %T Value: %v\n\n", uu, uu)

	//Below line will raise a compilation error
	//var vv myBool = aa

	//Untyped named boolean constant
	const bb = true

	var ww myBool = bb
	var xx = bb
	fmt.Println("Untyped named boolean constant")
	fmt.Printf("ww: Type: %T Value: %v\n", ww, ww)
	fmt.Printf("xx: Type: %T Value: %v\n\n", xx, xx)

	//Untyped unnamed boolean constant
	var yy myBool = true
	var zz = true
	fmt.Println("Untyped unnamed boolean constant")
	fmt.Printf("yy: Type: %T Value: %v\n", yy, yy)
	fmt.Printf("zz: Type: %T Value: %v\n", zz, zz)
}

Output:

Typed named boolean constant
uu: Type: bool Value: true

Untyped named boolean constant
ww: Type: main.myBool Value: true
xx: Type: bool Value: true

Untyped unnamed boolean constant
yy: Type: main.myBool Value: true
zz: Type: bool Value: true

In the above program, we created a new type myBool

type myBool bool

Also above program shows the example of

Let’s understand each of them and their behaviour

Typed boolean constant

It is defined as below

const aa bool = true

Notice in above that below line will cause a compilation error. This is because variable aa is of typed boolean constant . So below line will cause compilation error as it cannot be assigned to variable of type myBool

var v mybool = aa

But typed string constant can be assigned to a variable created with var keyword like below

var uu = aa

Untyped named boolean constant

It is defined as below

const bb = true

Untyped named string constant can be assigned to variable of type myBool as well variable created with var keyword because it is untyped so type of the constant will be decided depending upon the type of variable they are being assigned to.

var ww mybool = bb
var xx = bb

Untyped unnamed boolean constant

It is like below

true

Untyped unnamed string constant can be assigned to variable of type myBool as well variable created with var keyword because it is untyped so type of the constant will be decided depending upon the type of variable they are being assigned to.

var yy mybool = true
var zz = true

Character Constant

Below is the program illustrating a character constant.

package main

import "fmt"

func main() {
	type myChar int32

	//Typed character constant
	const aa int32 = 'a'
	var uu = aa
	fmt.Println("Untyped unnamed character constant")
	fmt.Printf("uu: Type: %T Value: %v\n\n", uu, uu)

	//Below line will raise a compilation error
	//var vv myBool = aa

	//Untyped named character constant
	const bb = 'a'

	var ww myChar = bb
	var xx = bb
	fmt.Println("Untyped named character constant")
	fmt.Printf("ww: Type: %T Value: %v\n", ww, ww)
	fmt.Printf("xx: Type: %T Value: %v\n\n", xx, xx)

	//Untyped unnamed character constant
	var yy myChar = 'a'
	var zz = 'a'
	fmt.Println("Untyped unnamed character constant")
	fmt.Printf("yy: Type: %T Value: %v\n", yy, yy)
	fmt.Printf("zz: Type: %T Value: %v\n", zz, zz)
}

Output:

Untyped unnamed character constant
uu: Type: int32 Value: 97

Untyped named character constant
ww: Type: main.myChar Value: 97
xx: Type: int32 Value: 97

Untyped unnamed character constant
yy: Type: main.myChar Value: 97
zz: Type: int32 Value: 97

In the above program, we created a new type myChar

type myChar int32

Also above program shows the example of

Let’s understand each of them and their behaviour

Typed character constant

It is defined as below

const aa int32 = 'a'

Notice in above that below line will cause a compilation error. This is because variable aa is of type int32. So below line will cause compilation error as it cannot be assigned to variable of type myChar

var v myChar = aa

But typed string constant can be assigned to a variable created with var keyword like below

var uu = aa

Untyped named character constant

It is defined as below

const bb = 'a'

Untyped named string constant  can be assigned to variable of type myChar as well variable created with var keyword because it is untyped so type of the constant will be decided depending upon the type of variable they are being assigned to.

var ww myChar = bb
var xx = bb

Untyped unnamed character constant.

It is like below

'a'

Untyped unnamed string constant can be assigned to variable of type myChar as well variable created with var keyword because it is untyped so type of the constant will be decided depending upon the type of variable they are being assigned to.

var yy myChar = 'a'
var zz = 'a'

Conclusion

This is all about const keyword in Golang. Hope you have liked this article. Do share feedback in comments.

Next Tutorial – For Loop
Previous Tutorial –Functions