Trong hướng dẫn này chúng ta sẽ tìm hiểu câu lệnh switch là gì, cách khai báo câu lệnh switch, các ví dụ về cách sử dụng câu lệnh switch case trong Go.
Switch là một câu lệnh điều kiện đánh giá một biểu thức và so sánh nó với một danh sách các kết quả phù hợp có thể có và thực thi khối mã tương ứng. Có thể coi đây là một cách tuyệt vời để thay thế các câu lệnh if else phức tạp.
Một chương trình ví dụ có giá trị hơn trăm lời nói. Hãy bắt đầu với một ví dụ đơn giản sẽ lấy số ngón tay làm đầu vào và xuất ra tên của ngón tay đó :). Ví dụ: 1 là ngón cái, 2 là ngón trỏ, v.v.
package main
import (
"fmt"
)
func main() {
finger := 4
fmt.Printf("Finger %d is ", finger)
switch finger {
case 1:
fmt.Println("Thumb")
case 2:
fmt.Println("Index")
case 3:
fmt.Println("Middle")
case 4:
fmt.Println("Ring")
case 5:
fmt.Println("Pinky")
}
}
Chạy chương trình trong Playground
Trong chương trình trên, lệnh switch finger
ở dòng số 10 so sánh giá trị của finger
với mỗi câu lệnh case
. Các trường hợp được đánh giá từ trên xuống dưới và trường hợp đầu tiên phù hợp với biểu thức được thực thi. Trong trường hợp này, finger
có giá trị 4
và do đó sẽ in ra kết quả sau:
Finger 4 is Ring
Các case trùng lặp có cùng giá trị là không được phép. Nếu bạn cố gắng chạy chương trình bên dưới, trình biên dịch sẽ báo lỗi ./prog.go:19:7: duplicate case 4 in switch previous case at ./prog.go:17:7
package main
import (
"fmt"
)
func main() {
finger := 4
fmt.Printf("Finger %d is ", finger)
switch finger {
case 1:
fmt.Println("Thumb")
case 2:
fmt.Println("Index")
case 3:
fmt.Println("Middle")
case 4:
fmt.Println("Ring")
case 4: //duplicate case
fmt.Println("Another Ring")
case 5:
fmt.Println("Pinky")
}
}
Chạy chương trình trong Playground
Chúng ta chỉ có 5 ngón tay trong bàn tay. Điều gì sẽ xảy ra nếu chúng ta nhập số ngón tay không chính xác? Đây là nơi mà trường hợp mặc định được sử dụng. Trường hợp mặc định sẽ được thực thi khi không có case nào khớp.
package main
import (
"fmt"
)
func main() {
switch finger := 8; finger {
case 1:
fmt.Println("Thumb")
case 2:
fmt.Println("Index")
case 3:
fmt.Println("Middle")
case 4:
fmt.Println("Ring")
case 5:
fmt.Println("Pinky")
default: //default case
fmt.Println("incorrect finger number")
}
}
Chạy chương trình trong Playground
Trong chương trình trên finger
là 8
và nó không khớp với bất kỳ case nào và do đó dòng incorrect finger number
trong trường hợp mặc định được in. Lệnh default
không cần thiết phải là trường hợp cuối cùng trong câu lệnh switch. Nó có thể hiện diện ở bất cứ đâu trong lệnh switch.
Bạn cũng có thể nhận thấy một thay đổi nhỏ trong khai báo của finger
. Nó được khai báo trong chính câu lệnh switch. Câu lệnh switch có thể bao gồm một câu lệnh tùy chọn được thực thi trước khi biểu thức được đánh giá.
Trong dòng số 8, biến finger
được khai báo đầu tiên và sau đó được sử dụng trong biểu thức. Phạm vi của biến finger
trong trường hợp này được giới hạn trong khối lệnh switch.
Có thể gộp nhiều biểu thức trong một case bằng cách tách chúng bằng dấu phẩy.
package main
import (
"fmt"
)
func main() {
letter := "i"
fmt.Printf("Letter %s is a ", letter)
switch letter {
case "a", "e", "i", "o", "u": //multiple expressions in case
fmt.Println("vowel")
default:
fmt.Println("not a vowel")
}
}
Chạy chương trình trong Playground
Chương trình trên tìm xem có phải letter
là một nguyên âm hay không. Đoạn mã case "a", "e", "i", "o", "u":
ở dòng số 11 khớp với bất kỳ nguyên âm nào. Vì i
là một nguyên âm, chương trình này in kết quả như sau:
Letter i is a vowel
Biểu thức trong một câu lệnh switch là tùy chọn và nó có thể bị bỏ qua. Nếu biểu thức bị bỏ qua, lệnh switch được xem là switch true
và mỗi biểu thức case
được đánh giá là true và khối mã tương ứng được thực thi.
package main
import (
"fmt"
)
func main() {
num := 75
switch { // expression is omitted
case num >= 0 && num <= 50:
fmt.Printf("%d is greater than 0 and less than 50", num)
case num >= 51 && num <= 100:
fmt.Printf("%d is greater than 51 and less than 100", num)
case num >= 101:
fmt.Printf("%d is greater than 100", num)
}
}
Chạy chương trình trong Playground
Trong chương trình trên, biểu thức không có trong switch và do đó nó được coi là đúng và mỗi case được đánh giá. case num >= 51 && num <= 100:
trong dòng số 12 là true
và chương trình in ra kết quả sau:
75 is greater than 51 and less than 100
Kiểu switch này có thể coi là phương án thay thế cho nhiều câu lệnh if else
.
Trong Go, điều khiển đi ra khỏi câu lệnh switch ngay sau khi một trường hợp được thực thi. Câu lệnh fallthrough
được sử dụng để chuyển điều khiển cho câu lệnh đầu tiên của case có mặt ngay sau case đã được thực hiện.
Chúng ta hãy viết một chương trình để hiểu về lệnh fallthrough. Chương trình của chúng ta sẽ kiểm tra xem số đầu vào nhỏ hơn 50, 100 hay 200. Ví dụ: nếu chúng ta nhập 75, chương trình sẽ in rằng 75 nhỏ hơn cả 100 và 200. Chúng ta sẽ đạt được điều này bằng cách sử dụng fallthrough
.
package main
import (
"fmt"
)
func number() int {
num := 15 * 5
return num
}
func main() {
switch num := number(); { //num is not a constant
case num < 50:
fmt.Printf("%d is lesser than 50\n", num)
fallthrough
case num < 100:
fmt.Printf("%d is lesser than 100\n", num)
fallthrough
case num < 200:
fmt.Printf("%d is lesser than 200", num)
}
}
Chạy chương trình trong Playground
Biểu thức switch và case không chỉ cần hằng số. Chúng cũng có thể được đánh giá trong thời gian chạy. Trong chương trình trên num
được khởi tạo giá trị trả về của hàm number()
ở dòng số 14.
Điều khiển đến bên trong switch và case được đánh giá. case num < 100:
trong dòng số 18 là true và chương trình sẽ in ra 75 is lesser than 100
. Câu lệnh tiếp theo là fallthrough
.
Khi gặp phải lệnh fallthrough
, điều khiển sẽ chuyển đến câu lệnh đầu tiên của case tiếp theo và cũng được in ra 75 is lesser than 200
. Đầu ra của chương trình là
75 is lesser than 100
75 is lesser than 200
Lệnhfallthrough
nên là câu lệnh cuối cùng trong mộtcase
. Nếu nó hiện diện ở đâu đó ở giữa, trình biên dịch sẽ báo lỗifallthrough statement out of place
.
Có một sự tinh tế cần được xem xét khi sử dụng fallthrough
. Fallthrough sẽ xảy ra ngay cả khi case được đánh giá là false.
Vui lòng xem xét chương trình sau đây.
package main
import (
"fmt"
)
func main() {
switch num := 25; {
case num < 50:
fmt.Printf("%d is lesser than 50\n", num)
fallthrough
case num > 100:
fmt.Printf("%d is greater than 100\n", num)
}
}
Chạy chương trình trong Playground
Trong chương trình trên, biến num
là 25 nhỏ hơn 50 và do đó case ở dòng số 9 được đánh giá là true. Lệnh fallthrough
có mặt ở dòng số 11. Case tiếp theo là case num > 100:
tại dòng số 12 được đánh giá là false vì num < 100. Nhưng lệnh fallthrough không xem xét điều này. Fallthrough sẽ xảy ra ngay cả khi case được đánh giá là false.
Chương trình trên sẽ in ra kết quả sau:
25 is lesser than 50
25 is greater than 100
Vì vậy, hãy chắc chắn rằng bạn hiểu những gì bạn đang làm khi sử dụng lệnh fallthrough.
Một điều nữa là lệnh fallthrough
không thể được sử dụng trong case cuối cùng của một switch vì không còn case nào để fallthrough. Nếu fallthrough
có trong case cuối cùng, nó sẽ dẫn đến lỗi biên dịch sau.
cannot fallthrough final case in switch
Câu lệnh break
có thể được sử dụng để kết thúc sớm một switch trước khi nó hoàn thành. Hãy chỉ sửa đổi ví dụ có sẵn ở trên để hiểu cách hoạt động của lệnh break.
Hãy thêm một điều kiện rằng nếu num
nhỏ hơn 0 thì switch sẽ kết thúc.
package main
import (
"fmt"
)
func main() {
switch num := -5; {
case num < 50:
if num < 0 {
break
}
fmt.Printf("%d is lesser than 50\n", num)
fallthrough
case num < 100:
fmt.Printf("%d is lesser than 100\n", num)
fallthrough
case num < 200:
fmt.Printf("%d is lesser than 200", num)
}
}
Chạy chương trình trong Playground
Trong chương trình trên num
là -5
. Khi điều khiển đến câu lệnh if ở dòng số 10, điều kiện được thỏa mãn vì num < 0. Câu lệnh break kết thúc lệnh switch trước khi nó hoàn thành và chương trình không in bất cứ thứ gì :).
Khi lệnh switch nằm trong vòng lặp for, có thể một vài trường hợp cần kết thúc vòng lặp for sớm. Điều này có thể được thực hiện bằng cách gắn nhãn cho vòng lặp for và thoát khỏi vòng lặp for bằng cách sử dụng nhãn đó bên trong câu lệnh switch. Hãy xem ví dụ viết chương trình tạo một số chẵn ngẫu nhiên.
Chúng ta sẽ tạo một vòng lặp for vô hạn và sử dụng lệnh switch để xác định xem số ngẫu nhiên được tạo ra có phải là số chẵn hay không. Nếu nó là số chẵn, số đã tạo sẽ được in và vòng lặp for được kết thúc bằng cách sử dụng nhãn của nó. Function Intn
của package rand
được sử dụng để tạo ra các số ngẫu nhiên không âm.
package main
import (
"fmt"
"math/rand"
)
func main() {
randloop:
for {
switch i := rand.Intn(100); {
case i%2 == 0:
fmt.Printf("Generated even number %d", i)
break randloop
}
}
}
Chạy chương trình trong Playground
Trong chương trình trên, vòng lặp for được gắn nhãn randloop
ở dòng số 9. Một số ngẫu nhiên được tạo từ 0 đến 99 (không bao gồm 100) bằng cách sử dụng function Intn
ở dòng số 11. Nếu số được tạo là số chẵn, vòng lặp bị dừng ở dòng số 14 bằng cách sử dụng nhãn.
Chương trình này in ra kết quả
Generated even number 18
Xin lưu ý rằng nếu câu lệnh break được sử dụng mà không có nhãn, sẽ chỉ thoát khỏi câu lệnh switch và vòng lặp sẽ tiếp tục chạy. Vì vậy, việc gắn nhãn vòng lặp và sử dụng nó trong câu lệnh break bên trong switch là cần thiết để thoát vòng lặp for bên ngoài.
Trong hướng dẫn tiếp theo, chúng ta sẽ tìm hiểu về mảng (array) trong Go.
Như thường lệ, cảm ơn bạn đã đọc. Hãy chia sẻ những nhận xét và phản hồi có giá trị của bạn.
Bạn có thể vui lòng tắt trình chặn quảng cáo ❤️ để hỗ trợ chúng tôi duy trì hoạt động của trang web.
Trong hướng dẫn này, chúng ta sẽ tìm hiểu phương thức (method) trong Go là gì? Cú pháp khai báo phương thức, so sánh phương thức với hàm, ... trong Go.
Trong hướng dẫn này, chúng ta sẽ tìm hiểu struct là gì, cách khai báo và sử dụng một struct trong Go, struct ẩn danh, so sanh hai struct, ...
Trong hướng dẫn này, chúng ta sẽ tìm hiểu cách con trỏ (pointer) hoạt động trong Go và nó khác với con trỏ trong các ngôn ngữ khác như C và C++ như thế nào.
Chuỗi (string) xứng đáng được đề cập đặc biệt trong Go vì chúng khác biệt trong cách triển khai khi so sánh với các ngôn ngữ khác.