Go – Hằng số

Trong ngôn ngữ lập trình Go, chúng ta sử dụng thuật ngữ constant để miêu tả các gía trị không đổi như là 51.34true"Hello". Những giá trị không đổi này còn được gọi là literals

Hằng số có thể là bất kỳ kiểu dữ liệu cơ bản nào như là hằng số integer, hằng số floating hay một string literal. Ngoài ra còn có hằng số enumeration.

Các hằng số được xử lý như một biến bình thường ngoại trừ việc giá trị của nó sẽ không thể chỉnh sửa sau khi định nghĩa.

Hằng số Ví dụ
Hằng số integer 100067413
Hằng số floating 4.56128.372
Hằng số boolean truefalse
Hằng số rune 'C''ä'
Hằng số complex 2.7i3 + 5i
Hằng số string "Hello""Rajeev"

 

Khai báo một hằng số

Literals là một hằng số mà không cần tên. Để khai báo hằng số và đặt tên cho nó, chúng ta có thể sử dụng từ khoá const như sau

const myFavLanguage = "Python"
const sunRisesInTheEast = true

Chúng ta cũng có thể chỉ định kiểu như

const a int = 1234
const b string = "Hi"

Chúng ta cũng có thể khai báo nhiều hằng số trong một câu lệnh

const country, code = "Vietnam", 84

const (
	employeeId string = "E101"
	salary float64 = 50000.0
)

Các hằng số, như chúng ta mong muốn, không thể bị thay đổi. Nghĩa là, không thể gán lại hằng số cho một giá trị khác sau khi nó đã được khởi tạo

const a = 123
a = 321 // Biên dịch lỗi (không thể gán lại hằng số)

Hằng số không gán kiểu

Bất kỳ hằng số nào trong Golang, được đặt tên hoặc không đặt tên, đều có thể không cần gán kiểu trừ khi định nghĩa cho nó một kiểu rõ ràng. Hãy cùng xem ví dụ sau đây, tất cả các hằng số đều không gán kiểu

1       // hằng số integer không gán kiểu
4.5     // hằng số floating không gán kiểu
true    // hằng số boolean không gán kiểu
"Hello" // hằng số string không gán kiểu

Chúng không được gán kiểu cho dù chúng ta có đặt tên cho nó

const a = 1
const f = 4.5
const b = true
const s = "Hello"

Giá trị 1 là một integer, 4.5 là một float, và "hello" là một string. Nhưng chúng chỉ là các giá trị và chưa được gán một kiểu cố định, như là int32 hoặc float64 hoặc string, điều đó sẽ bắt buộc chúng phải tuân theo quy tắc kiểu nghiêm ngặt trong Go.

Thực tế rằng giá trị 1 không được gán kiểu cho phép chúng ta gán nó cho bất kỳ biến nào mà có kiểu tương thích với integer.

var myInt int = 1
var myFloat float64 = 1
var myComplex complex64 = 1

Mặc dù giá trị 1 không được gán kiểu, nó là một integer không gán kiểu. Nên nó chỉ có thể được sử dụng ở nơi integer được cho phép. Bạn không thể gán nó cho một biến string hoặc boolean.

Tương tự như vậy, hằng số floating không gán kiểu như là 4.5 có thể sử dụng bất kỳ chỗ nào kiểu floating cho phép

var myFloat32 float32 = 4.5
var myComplex64 complex64 = 4.5

Trong Golang, chúng ta có thể tạo một bí danh kiểu bằng cách sử dụng từ khoá type như sau

type RichString string  // Bí danh kiểu của `string`

Do đặc tính được định kiểu mạnh mẽ trong Go, bạn sẽ không thể gán một biến string cho biến RichString

var myString string = "Hello"
var myRichString RichString = myString // không chạy.

Nhưng chúng ta có thể gán hằng số string không được gán kiểu cho biến RichString bởi vì nó tương thích với string

const myUntypedString = "Hello"
var myRichString RichString = myUntypedString  // Chạy!

Hằng số và suy luận kiểu: Giá trị mặc định

Go hỗ trợ suy luận kiểu. Nó có thể suy luận ra kiểu của một biến từ giá trị mà nó được khởi tạo. Nên bạn có thể khai báo một biến với một giá trị khởi tạo mà không cần thông tin về kiểu, và Go sẽ tự động xác định kiểu cho nó

var a = 5  // Trình biên dịch Go tự động suy luận ra kiểu của biến `a`

Bạn có thể tìm hiểu rõ hơn trong bài viết trước về kiểu dữ liệu trong Golang.

Hằng số được gán kiểu

Trong Golang, hằng số được định kiểu khi chúng ta chỉ định kiểu rõ ràng trong khai báo như sau

const typedInt int = 1  // Hằng số được định kiểu

Cũng giống như các biến, tất cả các quy tắc của hệ thống kiểu trong Go áp dụng cho hằng số được gán kiểu. Ví dụ, bạn không thể gán kiểu hằng số integer cho biến float

var myFloat64 float64 = typedInt  // Biên dịch lỗi

Với các hằng số được định kiểu, bạn sẽ mất đi tính linh động so với hằng số không được định kiểu như là gán chúng cho biến bất kỳ với kiểu tương thích hoặc pha trộn chúng với các toán tử toán học. Nên bạn chỉ khai báo kiểu cho hằng số nếu nó thực sự cần thiết. Ngoài ra chỉ nên khai báo hằng số không gán kiểu.

Các biểu thức

Một thực tế rằng, hằng số không gán kiểu cho phép chúng ta có thể pha trộn chúng bằng các biểu thức một cách thoải mái.

Nên bạn có thể có một biểu thức hằng số có thể chứa hỗn hợp các hằng số không gán kiểu khác nhau miễn là những hằng số này là tương thích với nhau.

const a = 5 + 7.5 // Hợp lệ
const b = 12/5    // Hợp lệ
const c = 'z' + 1 // Hợp lệ

const d = "Hey" + true // Không hợp lệ (string và boolean không tương thích)

Tính toán của biểu thức và kết quả của nó tuân theo quy tắc nhất định.

1. Toán tử so sánh giữa 2 hằng số không gán kiểu luôn trả về một kiểu hằng số boolean.

const a = 7.5 > 5        // true
const b = "xyz" < "uvw"  // false

2. Đối với các toán tử khác (ngoại trừ shift)

  • Nếu cả 2 toán hạng là cùng kiểu, kết quả trả về là cùng kiểu. Ví dụ biểu thức 25 / 2 thì kết quả trả về là 12 chứ không phải 12.5. Vì cả hai toán hạng đều là integer, nên kết quả được cắt ngắn thành số nguyên.
  • Nếu các toán hạng là khác kiểu, kết quả của kiểu toán hạng theo một quy tắc rộng hơn integer < rune < floating-point < complex
    const a = 25/2      // 12 (integer)
    const b = (6+8i)/2  // (3+4i) (complex)
  • Toán tử shift hơi phức tạp một chút. Trước hết, có một số yêu cầu
    • Toán hạng bên phải của biểu thức shift phải có một kiểu integer không dấu hoặc một hằng số không gán kiểu, có thể biểu thị giá trị kiểu uint
    • Toán hạng bên trải phải có một kiểu integer hoặc là một hằng số không gán kiểu, có thể biểu thị giá trị kiểu int

Nếu toán tử bên trái của biểu thức shift là hằng số không gán kiểu, kết qủa sẽ là một hằng số integer không gán kiểu. Trường hợp còn lại kết quả sẽ cùng kiểu với toán hạng bên trái.

const a = 1 << 5          // 32 (integer)
const b = int32(1) << 4   // 16 (int32) 
const c = 16.0 >> 2       // 4 (integer) - 16.0 có thể biểu diễn giá trị kiểu `int`
const d = 32 >> 3.0       // 4 (integer) - 3.0 có thể biểu diễn giá trị kiểu `uint`

const e = 10.50 << 2      // trái luật (10.50 không thể biểu diễn giá trị kiểu `int`)
const f = 64 >> -2        // trái luật (toán hạng bên phải là một int không dấu hoặc hằng số không gán kiểu tương thích với `uint`)

Ví dụ về biểu thức hằng số

Hãy cùng xem ví dụ về biểu thức hằng số sau

package main
import "fmt"

func main() {
  var result = 25/2
  fmt.Printf("result is %v which is of type %T\n", result, result)
}

Kết quả

result is 12 which is of type int

Vì cả 25 và 2 đều là int nên kết quả trả về cắt ngắn là 12

Để nhận được kết quả chính xác, chúng ta cần làm như sau

// sử dụng một giá trị float cho tử số hoặc mẫu số
var result = 25.0/2
// Hoặc rõ ràng cho tử số hoặc mẫu số
var result = float64(25)/2

Hãy cùng xem một ví dụ khác

package main
import "fmt"

func main() {
	var result = 4.5 + (10 - 5) * (3 + 2)/2
	fmt.Println(result)
}

Kết quả sẽ là gì? Nó không phải là 17.

Kết quả thực tế của nó sẽ là 16.5. Hãy cùng lướt qua từng phần tính toán để hiểu tại sao kết quả là 16.5

4.5 + (10 - 5) * (3 + 2)/2
          ↓
  4.5 + (5) * (3 + 2)/2
          ↓
   4.5 + (5) * (5)/2
          ↓
     4.5 + (25)/2
          ↓
      4.5 + 12
          ↓
        16.5

Kết quả bị sai bởi vì 25 / 2 được làm tròn thành 12.

Để nhận được kết quả chính xác, bạn cần chỉnh sửa như sau

// sử dụng float giá trị cho tử số hoặc mẫu số
var result = 4.5 + (10 - 5) * (3 + 2)/2.0
// Định kiểu rõ ràng cho tử số hoặc mẫu số
var result = 4.5 + float64((10 - 5) * (3 + 2))/2

 

 

You May Also Like

About the Author: Nguyen Dinh Thuc

Leave a Reply

Your email address will not be published.