常量在任何时候都不能改变其值的,Golang中常量可以是字符串、枚举、布尔、字符类型。

常量可以使用const关键字来进行声明。重要的一点是常量必须在声明的时候进行赋值,不像其他类型的变量可以在后面进行赋值。

  • 声明常量同时指定类型 - 首先是 const 关键字,然后是变量名称,后面是变量类型。常量必须像上面说的那样进行赋值。
    const c string = "articel"
  • 声明常量不指定类型,这种称为无类型常量,无类型常量有隐式类型。其类型通过被赋值的值的类型来决定。
    const c = "circle"
  • 同时声明多个常量
    const ( 
            c = "circle"
            s = "square"
    )

重点

  • 常量不能在声明后被赋值。下面这个例子就会报编译错误
    package main
    func main() {
        const a int = 8
        a = 9
    }
  • 常量的值必须在编译时就确定。因此一个常量不能被一个运行时的方法赋值。在下面这个程序中一个常量应该在编译过程中被赋值,但是getValue 这个方法只有在运行被调用,因此会在编译时报错。
    package main
    const name = "test"
    func main() {
        const a = getValue()
    }
    func getValue() int{
        return 1
    }

Error:

    const initializer getValue() is not constant
  • 一个产量在内部作用域中声明,和一个变量在外部作用域中声明同名。在内部作用域会隐藏外部作用域声明的常量。
    package main
    import "fmt"
    const a = 123
    func main() {
        const a  = 456
        fmt.Println(a)
    }

Output:

    456

指定类型常量和非指定类型常量

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 save numeric types no operation is allowed without exlicit 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 = 123
    const b = "circle"
    const c = 5.6
    const d = true
    const e = 'a'
    const f = 3+5i

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

Default Hidden type for Constants

inteters int
floats float64
complex numbers complex128
strings string
boolean bool
characters int32 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 type are assigned to.For example in below code variable a will get its type from the default type of unnamed constant 123 witch is int.

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.

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.

  • Due to the untyped nature of math.Pi constant it can be assigned to a variable of type float32 as well as float64. This is otherwise not possible in Go after type is fixed.
  • When we print the type of math.Pi,it prints the default type which is float64

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

Naming Conventions

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

  • A constant name can only start with a letter or an undescore.It can be followed by any number of letters, numbers of underscores after that.

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 four types:

  • Numeric
  • String
  • Character
  • Boolean

string Constant

In go string constant is represented in two ways

  • Any value that is enclosed between double quotes.
  • Any value enclosed between back quotes.

Below program shows a example of

  • Typed string constant
  • Untyped unnamed string constant
  • Untyped named string constant

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

  • Integer
  • Floats
  • Complex Numbers

A untyped integer constant 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

  • A int whose value is 123
  • A float whose value is 123.0
  • A complex whose imaginary part is 0

On the basic of similar logic an untyped float canstant 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 basic of similar logic, an untyped complex constant can be assigned to complex types but not integer and float because for eg a complex cannot be an integer or a float

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

  • Typed integer constant
  • Untyped unnamed integer constant
  • Untyped named integer constant
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)

Numeric Expressions

Due to untyed 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

有两种无类型bool 常量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

  • Typed boolean constant
  • Untyped unnamed boolean constant
  • Untyped named boolean constant

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

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

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 variable created with var keyword like below

var uu = aa

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'