Keputusan dalam program jarang bergantung pada satu kondisi saja. Sistem login misalnya perlu memastikan bahwa alamat email terisi DAN kata sandi cukup panjang; program unduhan perlu tahu apakah berkas belum ada ATAU ukurannya berubah. Go menggabungkan kondisi-kondisi seperti itu dengan tiga operator logika yang bekerja khusus pada nilai bool. Pada chapter ini kita mempelajari ketiganya, lalu membuktikan lewat output program bahwa Go mengevaluasi kondisi secara hemat: jika hasil sudah pasti, kondisi sisanya tidak dibaca sama sekali.
Tiga Operator Logika #
Tabel berikut merangkum tiga operator logika pada Go:
| Operator | Nama | Contoh | Hasil |
|---|---|---|---|
&& | AND logika | true && false | false |
|| | OR logika | true || false | true |
! | NOT logika | !true | false |
Operator && menghasilkan true hanya jika kedua operand true. Operator || menghasilkan true jika minimal satu operand true. Operator ! menerima satu operand dan membalik nilainya. Ketiganya hanya menerima nilai bool — ekspresi seperti 1 && 2 ditolak compiler karena Go tidak mengubah angka menjadi nilai kebenaran secara diam-diam, berbeda dengan kebiasaan bahasa C atau JavaScript.
Membuktikan Short-Circuit Evaluation #
Ciri terpenting && dan || adalah short-circuit evaluation. Ketika && menemukan operand kiri bernilai false, Go langsung menghasilkan false tanpa mengevaluasi operand kanan, karena apa pun nilai operand kanan, hasilnya sudah pasti false. Aturan yang sama berlaku pada ||: operand kiri true membuat hasil pasti true, sehingga operand kanan dilewati. Program berikut membuktikannya dengan sebuah fungsi yang mencetak pesan setiap kali dipanggil — fungsi adalah blok kode bernama yang akan kita bahas tuntas pada Section Fungsi
; saat ini cukup ketahui bahwa catatPemeriksaan selalu mencetak satu baris lalu mengembalikan true:
package main
import "fmt"
// catatPemeriksaan mencetak pesan setiap kali dipanggil, lalu mengembalikan true.
func catatPemeriksaan(nama string) bool {
fmt.Println(" -> catatPemeriksaan(\"" + nama + "\") dipanggil")
return true
}
func main() {
// Operand kanan TIDAK dievaluasi karena hasil sudah pasti
fmt.Println("A: false && catatPemeriksaan(\"gudang\")")
fmt.Println(" hasil:", false && catatPemeriksaan("gudang"))
fmt.Println("B: true || catatPemeriksaan(\"gudang\")")
fmt.Println(" hasil:", true || catatPemeriksaan("gudang"))
// Operand kanan DIPANGGIL karena hasil belum pasti
fmt.Println("C: true && catatPemeriksaan(\"toko\")")
fmt.Println(" hasil:", true && catatPemeriksaan("toko"))
fmt.Println("D: false || catatPemeriksaan(\"toko\")")
fmt.Println(" hasil:", false || catatPemeriksaan("toko"))
// Operator NOT membalik nilai bool
stokTersedia := false
kehabisan := !stokTersedia
fmt.Println("kehabisan:", kehabisan)
}Output yang Dihasilkan:
A: false && catatPemeriksaan("gudang")
hasil: false
B: true || catatPemeriksaan("gudang")
hasil: true
C: true && catatPemeriksaan("toko")
-> catatPemeriksaan("toko") dipanggil
hasil: true
D: false || catatPemeriksaan("toko")
-> catatPemeriksaan("toko") dipanggil
hasil: true
kehabisan: trueBukti short-circuit terlihat jelas pada urutan output di atas. Mari kita telaah baris demi baris program:
- Baris 6-9 (
func catatPemeriksaan ...): Fungsi ini mencetak satu baris pesan setiap kali dijalankan, lalu mengembalikantrue. Kehadiran baris pesan pada output menjadi penanda bahwa operand kanan benar-benar dievaluasi. - Baris 14 (
false && catatPemeriksaan("gudang")): Hasil&&sudah pastifalsekarena operand kirifalse, sehingga fungsi tidak dipanggil — tidak ada baris-> catatPemeriksaan("gudang")pada output. - Baris 16 (
true || catatPemeriksaan("gudang")): Hasil||sudah pastitruekarena operand kiritrue. Operand kanan kembali dilewati dan fungsi tidak mencetak apa pun. - Baris 20 dan 22 (
true && catatPemeriksaan("toko")danfalse || catatPemeriksaan("toko")): Hasil kedua ekspresi masih bergantung pada operand kanan, sehingga fungsi dipanggil dan baris-> catatPemeriksaan("toko")muncul tepat sebelum hasilnya dicetak. - Baris 25-27 (
stokTersedia ... fmt.Println("kehabisan:", kehabisan)): Operator!membalikfalsemenjaditrue. NOT tidak mengenal short-circuit karena hanya memiliki satu operand.
Manfaat Praktis Short-Circuit #
Short-circuit bukan sekadar optimasi kecepatan; fitur ini menjaga keamanan ekspresi. Pola yang paling sering dipakai adalah memeriksa prasyarat yang murah sebelum operasi yang berisiko:
if p != nil && *p > 0 {
fmt.Println("nilai positif:", *p)
}Potongan kode di atas membaca nilai lewat pointer p hanya setelah yakin p bukan nil. Jika && mengevaluasi kedua operand tanpa peduli hasil, ekspresi *p > 0 akan membaca pointer nil dan membuat program panic. Urutan pemeriksaan seperti ini disebut guard clause dan akan sering kita pakai pada chapter Operator Pointer
serta berbagai chapter berikutnya.
Referensi #
- Spesifikasi Go: Logical operators
— definisi resmi
&&,||, dan!beserta aturan evaluasinya. - Spesifikasi Go: Operators — tabel seluruh operator Go dan pembagian kelasnya.
- A Tour of Go: Basics — tur resmi yang memperkenalkan operator logika.
Operator & dan | yang sempat disinggung di atas punya peran jauh lebih besar dari sekadar menggantikan &&: keduanya memanipulasi bit di dalam bilangan. Chapter Operator Bitwise
membahas cara kerja AND, OR, XOR, shift, dan pemakaian nyatanya untuk menyimpan permission dalam satu bilangan.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
logika.go
Unduh berkaspackage main
import "fmt"
// catatPemeriksaan mencetak pesan setiap kali dipanggil, lalu mengembalikan true.
func catatPemeriksaan(nama string) bool {
fmt.Println(" -> catatPemeriksaan(\"" + nama + "\") dipanggil")
return true
}
func main() {
// Operand kanan TIDAK dievaluasi karena hasil sudah pasti
fmt.Println("A: false && catatPemeriksaan(\"gudang\")")
fmt.Println(" hasil:", false && catatPemeriksaan("gudang"))
fmt.Println("B: true || catatPemeriksaan(\"gudang\")")
fmt.Println(" hasil:", true || catatPemeriksaan("gudang"))
// Operand kanan DIPANGGIL karena hasil belum pasti
fmt.Println("C: true && catatPemeriksaan(\"toko\")")
fmt.Println(" hasil:", true && catatPemeriksaan("toko"))
fmt.Println("D: false || catatPemeriksaan(\"toko\")")
fmt.Println(" hasil:", false || catatPemeriksaan("toko"))
// Operator NOT membalik nilai bool
stokTersedia := false
kehabisan := !stokTersedia
fmt.Println("kehabisan:", kehabisan)
}