Định nghĩa

Khái niệm constant (hằng số) được sử dụng trong Go để thể hiện những giá trị cố định như 5, -89, "I love Go", 67.89,...
Cùng xem đoạn code sau:

var a int 50
var b string = "I love Go"

Ở đoạn code trên a và b được gán cho các hằng số là 50 và "I love Go". Từ khóa constđược sử dụng để thể hiện những hằng số như 50 hay "I love Go". Mặc dù chúng ta không sử dụng bất kì từ khóa const nào ở đoạn code trên, nhưng bản chất, chúng là những hằng số trong Go.
Hằng số tức là những giá trị không thể thay đổi, do vậy đoạn code dưới đây sẽ dưới đây sẽ báo lỗi không thể gán lại giá trị cho a.

package main

func main() {
    const a = 55 
    a = 89 //cannot assign to a
}

Giá trị của 1 hằng số cần được biết ngay tại thời gian biên dịch. Do vậy nó không thể được gán 1 giá trị được trả bởi 1 function, bởi vì function chỉ trả về kết quả khi chạy chương trình.

package main

import (  
    "fmt"
    "math"
)

func main() {  
    fmt.Println("Hello, playground")
    var a = math.Sqrt(4) //chạy bình thường với từ khóa var
    const b = math.Sqrt(4)//lỗi , const initializer math.Sqrt(4) is not a constant
}

Ở chương trình trên, a chỉ là 1 biến bình thường được khai báo bằng từ khóa var, do vậy nó có thể được gán giá trị trả về của function math.Sqrt(4).
Còn b là 1 hằng số và giá trị của nó cần được tính ngay tại thời gian biên dịch. Nhưng funcion math.Sqrt(4) chỉ chạy và trả về kết quả khi chạy chương trình, do vậy đoạn code trên báo lỗi.

String constant (Hằng số chuỗi)

Mọi giá trị nằm trong cặp dấu ngoặc kép đều là hằng số chuỗi trong Go. Ví dụ, các chuỗi như "Hello World" hay "Golang" đều là hằng số trong Go.
Vậy kiểu của 1 hằng số chuỗi là gì? Câu trả lời là untyped (không có kiểu).
1 hằng số chuỗi như "Hello World" không có kiểu gì.

const hello = "Hello World"

Ở trường hợp trên, chúng ta gán "Hello World" cho hằng số hello. Vậy hằng số hellocó kiểu là gì? Câu trả lời vẫn là untyped
Go là 1 ngôn ngữ rất quan trọng kiểu dữ liệu của các biến. Mọi biến đều cần 1 kiểu dữ liệu rõ rang. Cùng xem đoạn code bên dưới và thử suy nghĩ xem vậy biến name sẽ có kiểu dữ liệu là gì khi được gán cho 1 hằng số không kiểu (untyped const) "Sam"?

package main

import (  
    "fmt"
)

func main() {  
    var name = "Sam"
    fmt.Printf("type %T value %v", name, name) // type string value Sam
}

Câu trả lời ở đây là untyped const có kiểu dữ liệu mặc định của chúng, và chúng chỉ cung cấp nó khi có dòng lệnh nào yêu cầu điều đó. Ở dòng lệnh var name = "Sam", biến name cần 1 kiểu dữ liệu và nó sẽ lấy từ kiểu dữ liệu mặc định của 1 hằng số chuỗi, tức là kiểu chuỗi (string).
Câu hỏi tiếp theo được đặt ra là, vậy có cách nào tạo 1 hằng số có kiểu xác định? Cùng xem đoạn code dưới đây:

const typedhello string = "Hello World" 

Biến typedhello ở đoạn code trên là hằng số có kiểu là string.
Việc gán 1 giá trị có kiểu dữ liệu khác cho 1 biến không được chấp nhận trong Go.

package main

func main() {  
        var defaultName = "Sam" //chạy bình thường
        type myString string
        var customName myString = "Sam" //chạy bình thường
        customName = defaultName //lỗi

}

Ở đoạn code trên, đầu tiên chúng ta tạo 1 biến là defaultName và gán cho nó 1 hằng số chuỗi là "Sam". Kiểu dữ liệu mặc định của "Sam" là string, do vậy defaultName có kiểu dữ liệu là string.
Dòng tiếp theo khai báo kiểu myString có kiểu nền là string. 
Sau đó, chúng ta tạo biến customName có kiểu dữ liệu là myString, và gán cho nó hằng số chuỗi là "Sam". Vì hằng số "Sam" là untyped, do vậy nó có thể gán cho bất kì biến string nào, nên phép gán này được cho phép, và customName nhận kiểu dữ liệu là myString.
Như vậy, chúng ta có biến defaultName có kiểu string, và biến customName có kiểu là myString. Và mặc dù myString có kiểu nền là string, Go vẫn không chấp nhận gán giá trịcủa 1 kiểu dữ liệu cho 1 biến có kiểu dữ liệu khác. Do vậy, dòng cuối cùng sẽ báo lỗi main.go:7:20: cannot use defaultName (type string) as type myString in assignment.

Hằng số boolean

Hằng số boolean có 2 giá trị là true và false. Những quy tắc của hằng số chuỗi cũng được áp dụng cho boolean.

package main

func main() {  
    const trueConst = true
    type myBool bool
    var defaultBool = trueConst //chạy bình thường
    var customBool myBool = trueConst //chạy bình thường
    defaultBool = customBool //lỗi do 2 biến có kiểu khác nhau
}

Hằng số Số (numeric constant)

Numeric constant bao gồm hằng số tự nhiên (integer), thập phân (float) và các hằng số phức hợp (complex). Ngoài ra còn có thêm 1 số biến thể khác nữa.
Cùng xem ví dụ sau:

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)
}

Ở chương trình trên, hằng số a không có kiểu(untyped) và gía trị là 5. Chắc bạn sẽ thắc mắc rằng, vậy kiểu dữ liệu mặc định của a là gì, và nếu a có kiểu dữ liệu mặc định, thì làm thế nào chúng ta gán được nó cho các biến có kiểu dữ liệu khác. Câu trả lời nằm ở cú pháp của a. Cùng xem đoạn code dưới để tìm câu trả lời.

package main

import (  
    "fmt"
)

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

Ở chương trình trên, mỗi kiểu dữ được định nghĩa bởi cú pháp của hằng số Số. 5 là 1 số nguyên theo cú pháp, 5.6 là 1 số thập phân và 5 + 6i là 1 số phức hợp. Do vậy, khi chương trình chạy, nó sẽ in ra i's type int, f's type float64, c's type complex128.
Quay lại với ví dụ ở trên:

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)
}

Ở chương trình này, giá trị của a là 5 và cú pháp của nó sẽ là biểu thị chung của số (tức là nó có thể là float, integer hay là 1 số phức hợp). Do vậy, nó có thể gán cho bất kì biến nào khác có kiểu dữ liệu là sô. var intVar int = a cần kiểu dữ liệu là int do vậy nó trở thành 1 hằng số int. var complex64Var complex64 = a cần a là 1 kiểu dữ liệu phức hợp nên nó trở thành kiểu dữ liệu phức hợp. Rất linh động phải không nào.

Biểu thức số học

Numeric constant có thể được sử dụng thoaỉ mái trong các biểu thức, và kiểu của nó chỉ cần khi nó được gán cho 1 biến khác, hoặc sử dụng ở những đoạn code yêu cầu trả về kiểu dữ liệu của nó.

package main

import (  
    "fmt"
)

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

Ở chương trình trên, 5.9 là 1 số thập phân và 8 là 1 số nguyên. Tuy nhiên biểu thức 5.9/8 vẫn chạy được bình thường. Kết quả của biểu thức là 0.7375 là 1 số thập phân, do vậy biến a có kiểu là float. Chương trình sẽ trả về kết quả là a's type float64 value 0.7375.
Như vậy chúng ta đã tìm hiểu qua về hằng số trong Go. Ở phần tiếp theo, chúng ta sẽ cùng nhau tìm hiểu về Function.

Bài viết được dịch từ https://golangbot.com/constants/.