16. if, else, dan switch
Sejauh ini, program selalu berjalan dengan cara yang sama setiap
kali. Bab ini menambahkan kondisi: pertanyaan yang
dijawab true atau false. Jawaban itu
menentukan blok kode mana yang dijalankan. Seperti sebelumnya, contoh
pendek hanya menampilkan baris yang masuk ke dalam
main.
Membandingkan nilai
Kondisi dibangun dari operator perbandingan. Setiap operator membandingkan dua nilai dan memberikan sebuah bool.
| Operator | Arti |
|---|---|
== |
sama dengan |
!= |
tidak sama dengan |
< |
kurang dari |
> |
lebih dari |
<= |
kurang dari atau sama dengan |
>= |
lebih dari atau sama dengan |
fmt.Println(7 == 7) // true
fmt.Println(7 == 8) // false
fmt.Println("a" == "A") // false (huruf besar-kecil berpengaruh)
fmt.Println(7 != 8) // true
fmt.Println(3 < 5) // true
fmt.Println(3 >= 3) // trueOperator kesamaan adalah == (dua tanda sama dengan).
Satu = adalah penugasan, yang mengubah
variabel. Jadi if x = 7 { berhenti dengan:
syntax error: cannot use assignment x = 7 as value
Perbaikannya adalah if x == 7 {.
Pernyataan if
if menjalankan satu blok kode hanya ketika kondisinya
benar.
age := 16
if age >= 18 {
fmt.Println("You can vote.")
}Baca dari kiri ke kanan: kalau umurnya setidaknya 18, cetak
pesannya. Di sini age bernilai 16, jadi program tidak
mencetak apa-apa.
Ada tiga aturan bentuknya:
- Tidak ada tanda kurung di sekitar kondisi. Kamu
boleh mengetiknya, dan Go menerimanya, tetapi ekstensi VS Code
menghapusnya saat kamu menyimpan file (ekstensi itu menjalankan alat
bernama
gofmt). - Kurung kurawal wajib ada, bahkan untuk satu baris.
Kalau dihilangkan, Go berhenti dengan
syntax error: unexpected newline, expected { after if clause. {pembuka berada di baris yang sama denganif. Kamu sudah melihat alasannya di Bab 10: akhir baris bisa mengakhiri sebuah pernyataan. Kalau{berada di barisnya sendiri, muncul error yang sama.
Beri indentasi pada isi blok dengan tab. gofmt dan
ekstensi VS Code melakukannya untukmu. Indentasi itu untuk manusia;
kurung kurawal adalah yang memberi tahu Go di mana blok berakhir.
else untuk kasus
lainnya
else berjalan ketika kondisinya salah. Bersama
if, ia mencakup kedua kemungkinan tepat satu kali:
age := 16
if age >= 18 {
fmt.Println("You can vote.")
} else {
fmt.Println("Not old enough to vote yet.")
}Output:
Not old enough to vote yet.
Tepat satu fmt.Println yang berjalan, tidak pernah
keduanya.
else harus berada di baris yang sama dengan
} penutup milik if. Menulisnya seperti ini
terlihat masuk akal:
if age >= 18 {
fmt.Println("You can vote.")
}
else {
fmt.Println("Not old enough to vote yet.")
}tetapi } di akhir barisnya menyelesaikan seluruh
pernyataan if, sehingga Go lalu menemukan else
yang tidak punya pasangan.
Buka exercises/16/02-else-on-new-line.go. File ini tidak
bisa dikompilasi. Saat pertama dijalankan, ia mencetak:
# command-line-arguments
exercises\16\02-else-on-new-line.go:15:2: syntax error: unexpected else, expected }
Baris 15, kolom 2 adalah else. Pindahkan ke atas supaya
barisnya menjadi } else {, lalu jalankan file itu lagi.
else if untuk rantai
kondisi
Untuk lebih dari dua kasus, sambungkan dengan else if.
Go mencoba setiap kondisi secara berurutan dan berhenti pada yang
pertama bernilai benar:
score := 73
if score >= 90 {
fmt.Println("Grade: A")
} else if score >= 80 {
fmt.Println("Grade: B")
} else if score >= 70 {
fmt.Println("Grade: C")
} else if score >= 60 {
fmt.Println("Grade: D")
} else {
fmt.Println("Grade: F")
}Urutan itu penting: Go mengambil kecocokan pertama. Dengan
score >= 60 di atas, setiap nilai lulus akan mendapat
D, dan tidak ada yang melihat A, B, atau C.
Buka exercises/16/01-grade.go. Ubah score
lalu jalankan. Coba nilai tepat di batas (60, 70, 80, 90) untuk
memastikan >= menyertakannya.
Variabel yang dibuat di dalam blok
Variabel yang dideklarasikan dengan := di dalam blok
hanya ada sampai } penutup blok itu. Kode ini terlihat
baik-baik saja, tetapi tidak bisa dikompilasi:
score := 73
if score >= 60 {
result := "pass"
} else {
result := "fail"
}
fmt.Println(result)result declared and not used
result declared and not used
undefined: result
Di sini ada dua variabel terpisah bernama result, satu
di setiap blok, dan tidak ada yang dibaca. Di baris terakhir keduanya
sudah hilang. Perbaikannya adalah mendeklarasikan variabel
sebelum if, lalu memakai = biasa di
dalam blok:
score := 73
var result string
if score >= 60 {
result = "pass"
} else {
result = "fail"
}
fmt.Println(result) // passvar tanpa nilai, dari Bab 11, adalah cara yang biasa
untuk menulis ini. Kamu akan sering memakai bentuk ini.
switch
untuk satu nilai dan banyak kasus
Ketika sebuah rantai terus membandingkan nilai yang sama,
switch menyatakannya dengan lebih rapi. Ini
exercises/16/03-switch.go:
class := "Mage"
switch class {
case "Warrior":
fmt.Println("Starts with a sword.")
case "Mage":
fmt.Println("Starts with a staff.")
case "Rogue", "Thief":
fmt.Println("Starts with a dagger.")
default:
fmt.Println("Starts with nothing.")
}Output:
Starts with a staff.
Go membandingkan class dengan setiap case
dari atas ke bawah dan menjalankan yang pertama cocok. Beberapa hal yang
perlu diketahui:
- Sebuah case tidak berlanjut ke case berikutnya.
Ketika barisnya selesai, seluruh
switchselesai, dan Go lanjut ke kode sesudahnya. Kamu tidak perlu menulis apa pun untuk menghentikannya. (Go punya kata kuncifallthroughyang mengubah perilaku ini. Kamu jarang membutuhkannya, dan buku ini tidak memakainya.) - Satu case bisa mendaftar beberapa nilai, dipisahkan koma, seperti
"Rogue", "Thief". defaultberjalan ketika tidak ada case yang cocok. Bagian ini tidak wajib, dan ia adalahelsemilikswitch.
Buka exercises/16/03-switch.go. Isi class
dengan "Thief" lalu jalankan, kemudian dengan
"Cook". Case mana yang berjalan setiap kali?
switch tanpa nilai
Tulis switch tanpa nilai, dan setiap case
memegang kondisinya sendiri. Go menjalankan case pertama yang kondisinya
benar. Ini keputusan yang sama dengan rantai if, dalam
bentuk yang lebih rapi:
score := 73
switch {
case score >= 90:
fmt.Println("Grade: A")
case score >= 80:
fmt.Println("Grade: B")
case score >= 70:
fmt.Println("Grade: C")
case score >= 60:
fmt.Println("Grade: D")
default:
fmt.Println("Grade: F")
}Output:
Grade: C
Bandingkan dengan rantai else if tadi: urutannya sama,
hasilnya sama. Pakai yang lebih enak dibaca. Kebanyakan programmer Go
memilih switch ketika rantai punya lebih dari dua atau tiga
cabang. Filenya adalah
exercises/16/04-switch-no-value.go.
Kondisi hanya boleh ada di switch tanpa
nilai. Kalau nilainya tetap ditulis, kode gagal, karena Go harus
membandingkan int dengan bool:
score := 73
switch score {
case score >= 90:
fmt.Println("Grade: A")
}cannot convert score >= 90 (untyped bool value) to type int
Menggabungkan kondisi dengan
&&, ||, !
Terkadang satu perbandingan saja tidak cukup. Go punya tiga operator logika yang menggabungkan bool:
| Operator | Arti |
|---|---|
&& |
benar kalau kedua sisi benar |
|| |
benar kalau salah satu sisi benar |
! |
membalik benar menjadi salah dan salah menjadi benar |
level := 12
hasKey := true
if level >= 10 && hasKey {
fmt.Println("You can enter the dungeon.")
}
if level < 10 || !hasKey {
fmt.Println("You are blocked.")
}Output:
You can enter the dungeon.
Ini adalah exercises/16/05-and-or-not.go. Baca
&& sebagai "dan", || sebagai "atau",
dan !hasKey sebagai "tidak punya kunci".
Mengambil keputusan dari teks
Bab 14 menyebut bahwa strings.Contains cocok dipasangkan
dengan if. Karena ia memberikan bool, panggilan itu bisa
menjadi seluruh kondisi:
message := "a dragon is sleeping in the cave"
if strings.Contains(message, "dragon") {
fmt.Println("Be careful.")
} else {
fmt.Println("All clear.")
}Output:
Be careful.
Hal yang sama berlaku untuk strings.HasPrefix dan
strings.HasSuffix:
command := "go north"
if strings.HasPrefix(command, "go ") {
fmt.Println("You walk.")
}Output:
You walk.
Untuk memeriksa apakah pengguna mengetik sesuatu, bandingkan dengan
string kosong. Hanya bool yang boleh masuk ke if, aturan
yang akan dibahas lebih dekat di Bab 17, jadi perbandingannya harus
ditulis lengkap. Kalau pengguna menekan Enter tanpa mengetik nama:
reader := bufio.NewReader(os.Stdin)
fmt.Print("What is your name? ")
text, _ := reader.ReadString('\n')
name := strings.TrimSpace(text)
if name != "" {
fmt.Println("Hello, " + name)
} else {
fmt.Println("No name was entered.")
}Output:
What is your name?
No name was entered.
Buka exercises/16/07-empty-answer.go dan jalankan dua
kali: sekali dengan nama, dan sekali langsung menekan Enter. Lalu buka
exercises/16/06-contains.go dan ubah kata di dalam
message supaya cabang yang lain berjalan.
PR
Starter PR ada di exercises/16/homework/. Setiap starter
bisa langsung dijalankan dan mencetak satu baris pengganti. Kalau
soalnya membaca input, komentar paling atas starter menunjukkan import
yang kamu butuhkan.
Soal 1 — Genap atau ganjil
Buka exercises/16/homework/01-even-or-odd.go. Minta
sebuah angka. Cetak even atau odd berdasarkan
apakah n % 2 bernilai 0.
Soal 2 — Gerbang level
Buka exercises/16/homework/02-level-gate.go. Ada dua
variabel di bagian atas: level (angka) dan
hasKey (bool). Cetak
You can enter the dungeon. hanya kalau pemain setidaknya
level 10 dan punya kunci. Kalau tidak, cetak salah satu
dari:
Level too low.(kalau hanya levelnya yang bermasalah),Missing the key.(kalau levelnya cukup tetapi kuncinya tidak ada),Level too low and missing the key.(kalau keduanya salah).
Soal 3 — Huruf nilai
Buka exercises/16/homework/03-grade-letter.go. Minta
nilai (0 sampai 100). Cetak huruf nilai A, B, C, D, atau F dengan batas
yang sama seperti contoh di bab ini. Gunakan switch tanpa
nilai.
Tantangan — Terbesar dari tiga
Buka exercises/16/homework/04-largest-of-three.go. Tiga
variabel berisi tiga angka. Cetak yang terbesar, dengan if
dan operator perbandingan. Go punya max bawaan, tetapi
jangan memakainya di sini; menyusun perbandingannya itulah intinya.
Tambahannya: tangani nilai seri dengan rapi (kalau dua angka sama-sama
terbesar, cetak nilai itu sekali).
Stuck atau sudah selesai? Buka halaman solusi PR.