Golang中的常量
常量在任何时候都不能改变其值的,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'