Hằng số trong Go
Giá trị của hằng số không thể thay đổi trong thời gian chạy, một khi đã gán giá trị thì không thể sửa đổi, giá trị của nó chỉ có thể đến từ:
- Giá trị chữ
- Định danh hằng số khác
- Biểu thức hằng số
- Chuyển đổi kiểu có kết quả là hằng số
- iota
Hằng số chỉ có thể là kiểu dữ liệu cơ bản, không thể là
- Các kiểu khác ngoài kiểu cơ bản như cấu trúc, interface, slice, mảng, v.v.
- Giá trị trả về của hàm
Giá trị của hằng số không thể bị sửa đổi, nếu không sẽ không thể biên dịch
Khởi tạo
Khai báo hằng số cần dùng từ khóa const, hằng số khi khai báo phải khởi tạo một giá trị, và kiểu của hằng số có thể bỏ qua, ví dụ
const name string = "Jack" // Giá trị chữ
const msg = "hello world" // Giá trị chữ
const num = 1 // Giá trị chữ
const numExpression = (1+2+3) / 2 % 100 + num // Biểu thức hằng sốNếu chỉ khai báo mà không chỉ định giá trị, sẽ không thể biên dịch
const name stringTrình biên dịch báo lỗi
missing init expr for nameKhai báo hàng loạt hằng số có thể dùng () để bao lại nhằm nâng cao khả năng đọc, có thể tồn tại nhiều () để đạt hiệu quả phân nhóm.
const (
Count = 1
Name = "Jack"
)
const (
Size = 16
Len = 25
)Trong cùng một nhóm hằng số, các hằng số phía sau hằng số đã được gán giá trị có thể không cần gán giá trị, giá trị của nó mặc định là giá trị của hằng số trước đó, ví dụ
const (
A = 1
B // 1
C // 1
D // 1
E // 1
)iota
iota là một định danh hằng số tích hợp, thường được sử dụng để biểu thị số thứ tự số nguyên không kiểu trong một khai báo hằng số, thường được sử dụng trong ngoặc đơn.
const iota = 0Xem một vài ví dụ sử dụng
const (
Num = iota // 0
Num1 // 1
Num2 // 2
Num3 // 3
Num4 // 4
)Cũng có thể viết như sau
const (
Num = iota*2 // 0
Num1 // 2
Num2 // 4
Num3 // 6
Num4 // 8
)Cũng có thể
const (
Num = iota << 2*3 + 1 // 1
Num1 // 13
Num2 // 25
Num3 = iota // 3
Num4 // 4
)Thông qua một vài ví dụ trên có thể phát hiện, iota là tăng dần, biểu thức giá trị iota của hằng số đầu tiên sử dụng iota, dựa trên sự thay đổi của giá trị số thứ tự sẽ tự động gán cho các hằng số tiếp theo, cho đến khi được đặt lại bằng const mới, số thứ tự này thực chất là số dòng mã tương đối, là số dòng tương đối so với dòng bắt đầu của nhóm hiện tại, xem ví dụ dưới đây
const (
Num = iota<<2*3 + 1 // 1 Dòng thứ nhất
Num2 = iota<<2*3 + 1 // 13 Dòng thứ hai
_ // 25 Dòng thứ ba
Num3 //37 Dòng thứ tư
Num4 = iota // 4 Dòng thứ năm
_ // 5 Dòng thứ sáu
Num5 // 6 Dòng thứ bảy
)Trong ví dụ sử dụng định danh ẩn danh _ để chiếm một vị trí dòng, có thể thấy giá trị của iota về bản chất là hiệu số giữa dòng mà iota đang ở so với dòng đầu tiên của nhóm const hiện tại. Và các nhóm const khác nhau thì không ảnh hưởng lẫn nhau.
Enum
Ngôn ngữ Go không thiết kế riêng một kiểu dữ liệu cho enum, không giống như các ngôn ngữ khác thường có một enum để biểu thị. Thông thường trong Go, đều thông qua kiểu tùy chỉnh + const + iota để thực hiện enum, dưới đây là một ví dụ đơn giản
type Season uint8
const (
Spring Season = iota
Summer
Autumn
Winter
)Các enum này thực chất là số, Go cũng không hỗ trợ chuyển đổi trực tiếp thành chuỗi, nhưng chúng ta có thể thêm phương thức cho kiểu tùy chỉnh để trả về biểu diễn chuỗi của nó, thực hiện interface Stringer là được.
func (s Season) String() string {
switch s {
case Spring:
return "mùa xuân"
case Summer:
return "mùa hè"
case Autumn:
return "mùa thu"
case Winter:
return "mùa đông"
}
return ""
}Như vậy là đã thực hiện một enum đơn giản. Bạn cũng có thể thông qua công cụ chính thức Stringer để tự động tạo enum.
Tuy nhiên nó có những nhược điểm sau:
Không an toàn kiểu, vì
Seasonlà kiểu tùy chỉnh, có thể thông qua chuyển đổi kiểu bắt buộc để chuyển đổi các số khác thành kiểu đógoSeason(6)Rườm rà, biểu diễn chuỗi cần tự mình thực hiện
Khả năng biểu đạt yếu, vì
constchỉ hỗ trợ kiểu dữ liệu cơ bản, nên các giá trị enum này cũng chỉ có thể được biểu thị bằng chuỗi và số
Tại sao không hỗ trợ enum ở cấp độ ngôn ngữ là điều mà tác giả rất không thể hiểu được, tôi cho rằng điều này chắc chắn là lợi大于弊.
