17. Logika boolean secara mendalam
Bab 16 memakai &&, ||, dan
! untuk menggabungkan kondisi. Bab ini melihat lebih dekat
apa yang dilakukan operator-operator itu, dan aturan Go yang paling
ketat tentang kondisi.
Hanya bool yang boleh masuk
ke if
Kondisi harus berupa bool: true atau false,
atau sesuatu yang memberikan salah satunya. Selain itu tidak boleh.
String, angka, atau nilai kosong tidak dianggap benar atau salah di
Go.
Buka exercises/17/01-not-a-bool.go. File ini punya dua
pernyataan if, satu dengan string dan satu dengan angka
1. File ini tidak bisa dikompilasi:
# command-line-arguments
exercises\17\01-not-a-bool.go:13:5: non-boolean condition in if statement
exercises\17\01-not-a-bool.go:17:5: non-boolean condition in if statement
Non-boolean berarti "bukan bool". Kolom 5 adalah tempat kondisi dimulai. Ganti kondisinya dengan perbandingan sungguhan, dengan contoh berikutnya sebagai panduan.
Jadi tulis pertanyaannya secara lengkap. Untuk menanyakan apakah string berisi sesuatu, atau apakah angka bukan nol, dibutuhkan perbandingan:
name := "Keiko"
count := 3
if name != "" {
fmt.Println("Hello, " + name)
}
if count != 0 {
fmt.Println("The count is not zero.")
}Output:
Hello, Keiko
The count is not zero.
Ini butuh beberapa karakter lebih banyak, dan sebagai gantinya
kondisi menyatakan dengan tepat apa yang diuji. name != ""
tidak mungkin salah dibaca. Compiler juga menangkap kesalahannya
untukmu, sebelum program berjalan:
level := 1
if level {
fmt.Println("Has a level.")
}non-boolean condition in if statement
Perbandingan, sekali lagi
Setiap perbandingan dari Bab 16 memberikan bool. String juga bisa
dibandingkan. < dan > membandingkannya
menurut urutan kamus, dengan satu catatan: huruf besar berada sebelum
huruf kecil.
fmt.Println("apple" == "apple") // true
fmt.Println("apple" != "banana") // true
fmt.Println("apple" < "banana") // true
fmt.Println("Zebra" < "apple") // trueKedua sisi perbandingan harus punya tipe yang sama. Go tidak mengubah angka menjadi teks untukmu, atau teks menjadi angka:
score := 73
if score == "73" {
fmt.Println("Seventy-three.")
}invalid operation: score == "73" (mismatched types int and untyped string)
Konversi dulu dengan strconv dari Bab 14, atau
bandingkan dengan angka 73.
&& dan
|| memberikan bool
&& dan || menerima dua bool dan
memberikan satu bool. ! menerima satu bool dan memberikan
satu bool. Lengkapnya:
a |
b |
a && b |
a || b |
!a |
|---|---|---|---|---|
true |
true |
true |
true |
false |
true |
false |
false |
true |
false |
false |
true |
false |
true |
true |
false |
false |
false |
false |
true |
Output exercises/17/02-bools.go mencoba beberapa di
antaranya:
false
false
true
true
false
true
Can enter: true
Karena jawabannya bool, kamu bisa menyimpannya dalam variabel dengan
nama yang baik, lalu memakai variabel itu sebagai kondisi. Variabel bool
boleh berdiri sendiri di dalam if, tanpa perbandingan:
level := 12
hasKey := true
canEnter := level >= 10 && hasKey
if canEnter {
fmt.Println("You can enter the dungeon.")
}
fmt.Println("Can enter:", canEnter)Output:
You can enter the dungeon.
Can enter: true
Ketika && dan || dicampur,
&& didahulukan, seperti * didahulukan
dari +. Pakai tanda kurung kalau kamu ingin urutan lain,
atau kalau tanda kurung membuat barisnya lebih jelas:
fmt.Println(true || false && false) // true
fmt.Println((true || false) && false) // falseNilai default
Pekerjaan yang umum: pakai sebuah nilai kalau ada, dan kalau tidak
ada, pakai nilai cadangan. || tidak bisa melakukan ini,
karena hanya bekerja pada bool:
chosen := ""
move := chosen || "rock"
fmt.Println(move)invalid operation: operator || not defined on chosen (variable of type string)
Bab 11 menunjukkan bahwa variabel kosong sebenarnya tidak kosong. Ia
berisi nilai nol dari tipenya, dan untuk string nilai itu adalah
"". Jadi "tidak ada yang dimasukkan" berarti stringnya sama
dengan "", dan sebuah if memberikan nilai
cadangannya:
typedName := "" // tidak ada yang dimasukkan
name := typedName
if name == "" {
name = "stranger"
}
fmt.Println("Hello, " + name) // Hello, strangerKalau typedName berisi nilai sungguhan,
name akan menyimpannya. Mulai dari nilainya, lalu ganti
hanya kalau nilainya tidak ada. Panjangnya tiga baris, dan kamu akan
sering melihatnya.
Ini bekerja kalau "" tidak mungkin menjadi jawaban
sungguhan. Angka lebih sulit, karena 0 bisa berupa nilai
sungguhan atau bisa juga hasil strconv.Atoi untuk teks yang
salah. Bab 21 menunjukkan cara membedakannya.
Buka exercises/17/03-default.go. chosen
diisi "", jadi move memakai nilai cadangan
"rock". Isi chosen dengan kata sungguhan lalu
jalankan lagi.
Short-circuit: sisi kedua dilewati
&& dan || berhenti begitu
jawabannya pasti:
a && b: kalauasalah, jawabannya salah, danbtidak pernah dihitung.a || b: kalauabenar, jawabannya benar, danbtidak pernah dihitung.
Ini disebut short-circuit evaluation. Dengan ini, pemeriksaan pertama bisa menjaga pemeriksaan kedua, yang hanya berjalan setelah yang pertama lolos:
total := 90
count := 0
// Rata-rata hanya perlu dihitung kalau count bukan nol,
// jadi pemeriksaan count menjaga pembagian.
if count > 0 && total/count > 20 {
fmt.Println("high average")
} else {
fmt.Println("no average to show")
}Output:
no average to show
Karena count > 0 salah, Go tidak pernah menghitung
total/count. Go langsung menuju else. Penjaga
ini dibutuhkan, karena membagi bilangan bulat dengan nol menghentikan
program. Tukar kedua sisinya:
total := 90
count := 0
if total/count > 20 && count > 0 {
fmt.Println("high average")
}Sekarang pembagian berjalan lebih dulu, dan program crash dengan:
panic: runtime error: integer divide by zero
Ini jenis crash yang sama dengan error slice di Bab 12: program berhasil dikompilasi, lalu berhenti saat berjalan.
|| menjaga dengan cara yang sama. Di sini pembagian
hanya dicapai kalau count bukan nol:
total := 90
count := 0
if count == 0 || total/count < 20 {
fmt.Println("nothing special")
}Output:
nothing special
Buka exercises/17/04-short-circuit.go. Jalankan, lalu
tukar kedua sisi && dan jalankan lagi untuk melihat
crash-nya. Terakhir, kembalikan urutannya dan isi count
dengan 3.
! membalik bool
! mengubah true menjadi false
dan false menjadi true. Ini berguna untuk
bertanya "apakah ini tidak ada?" kalau kamu punya bool:
fmt.Println(!true) // false
fmt.Println(!false) // true
hasKey := false
if !hasKey {
fmt.Println("You need a key.")
}Output:
false
true
You need a key.
Seperti ||, ia hanya bekerja pada bool. Untuk menanyakan
hal yang sama tentang string, bandingkan dengan "":
key := ""
if !key {
fmt.Println("You need a key.")
}invalid operation: operator ! not defined on key (variable of type string)
key := ""
if key == "" {
fmt.Println("You need a key.")
}Output:
You need a key.
PR
Starter PR ada di exercises/17/homework/. Setiap starter
bisa langsung dijalankan dan mencetak satu baris pengganti.
Soal 1 — Warna default
Buka exercises/17/homework/01-default-colour.go.
fav berisi sebuah warna atau "". Isi
colour dengan fav, atau dengan
"blue" kalau fav kosong, lalu cetak
Your colour is <colour>. Jalankan sekali dengan
fav := "" dan sekali dengan warna sungguhan.
Soal 2 — Tulis maksudmu
Buka exercises/17/homework/02-explicit-tests.go. Lima
variabel berisi 0, "", false,
"hi", dan 1. Untuk masing-masing, cetak
nilainya dan hasil pemeriksaan yang menanyakan apakah nilainya berbeda
dari nilai nol tipenya, seperti count != 0. Pakai
%q untuk string supaya string kosong terlihat. Mana dari
kelima variabel itu yang tidak butuh perbandingan?
Soal 3 — Pembagian yang dijaga
Buka exercises/17/homework/03-guarded.go. Ada dua angka:
total dan count (yang mungkin 0).
Dengan &&, kalau count lebih dari
0 dan total/count di atas 20, cetak
rata-ratanya dengan dua angka desimal, sebagai float64; kalau tidak,
cetak no high average. Uji dengan count
bernilai 0, 3, dan 10.
Tantangan — Nilai pertama yang ada
Buka exercises/17/homework/04-first-value.go. Tiga
variabel a, b, c masing-masing
berisi string atau "". Dengan switch tanpa
nilai, cetak yang pertama tidak kosong, atau none kalau
ketiganya kosong. Coba berbagai kombinasi.
Stuck atau sudah selesai? Buka halaman solusi PR.