Ekspresi 2 + 3 * 4 mengandung dua operator, tetapi hasilnya hanya satu: 14 atau 20, tergantung operator mana yang dijalankan lebih dulu. Aturan yang menentukan urutan tersebut disebut operator precedence, dan setiap bahasa mempunyai tabel prioritasnya sendiri. Go memilih tabel yang ringkas dengan lima tingkat untuk operator biner. Pada chapter penutup Section ini kita membaca tabel resminya, membuktikan tiap aturan lewat program, lalu belajar kapan tanda kurung wajib ditambahkan demi kejelasan — dan kapan tanda kurung justru menyesatkan pembaca.
Tabel Prioritas Resmi Go #
Spesifikasi Go menetapkan lima tingkat prioritas untuk operator biner, dari yang paling tinggi (5) hingga paling rendah (1):
| Tingkat | Operator |
|---|---|
| 5 | * / % << >> & &^ |
| 4 | + - | ^ |
| 3 | == != < <= > >= |
| 2 | && |
| 1 | || |
Tiga aturan tambahan melengkapi tabel di atas. Pertama, operator unary seperti -x, !b, ^x, dan &x mengikat paling kuat — lebih kuat daripada semua operator biner. Kedua, operator biner dengan tingkat yang sama dievaluasi dari kiri ke kanan (left associative). Ketiga, tabel ini hanya mengatur operator ekspresi: ++ dan -- bukan ekspresi, dan assignment = adalah statement, sehingga keduanya tidak ikut diurutkan.
Membuktikan Urutan Evaluasi #
Program berikut menguji setiap aturan tersebut dengan pasangan ekspresi: satu versi tanpa tanda kurung dan satu versi dengan tanda kurung yang mengelompokkan sebaliknya:
package main
import "fmt"
func main() {
// * lebih tinggi dari +
fmt.Println("2 + 3 * 4 =", 2+3*4)
fmt.Println("(2 + 3) * 4 =", (2+3)*4)
// << lebih tinggi dari +, bukan sebaliknya
fmt.Println("1 << 2 + 3 =", 1<<2+3)
fmt.Println("1 << (2 + 3) =", 1<<(2+3))
// Operator setara dievaluasi dari kiri ke kanan
fmt.Println("100 / 10 / 2 =", 100/10/2)
fmt.Println("100 / (10 / 2) =", 100/(10/2))
// Operator unary mengikat paling kuat
fmt.Println("-2 + 3 =", -2+3)
fmt.Println("-(2 + 3) =", -(2 + 3))
// && lebih tinggi dari ||
aktif, penuh, kosong := true, false, false
fmt.Println("aktif || penuh && kosong =", aktif || penuh && kosong)
fmt.Println("(aktif || penuh) && kosong =", (aktif || penuh) && kosong)
}Output yang Dihasilkan:
2 + 3 * 4 = 14
(2 + 3) * 4 = 20
1 << 2 + 3 = 7
1 << (2 + 3) = 32
100 / 10 / 2 = 5
100 / (10 / 2) = 20
-2 + 3 = 1
-(2 + 3) = -5
aktif || penuh && kosong = true
(aktif || penuh) && kosong = falseMari kita telaah baris demi baris program di atas:
- Baris 7-8 (
2 + 3 * 4dan(2 + 3) * 4): Operator*berada di tingkat 5, lebih tinggi daripada+di tingkat 4, sehingga3 * 4dihitung lebih dulu dan hasilnya 14. Tanda kurung memaksa penjumlahan berjalan lebih dulu dan mengubah hasil menjadi 20. - Baris 11-12 (
1 << 2 + 3dan1 << (2 + 3)): Pergeseran<<juga tingkat 5, sehingga1 << 2dievaluasi lebih dulu menjadi 4, lalu dijumlahkan 3 menjadi 7. Banyak pembaca mengira hasilnya1 << 5, padahal versi tersebut menghasilkan 32 — contoh klasik kesalahan membaca prioritas. - Baris 15-16 (
100 / 10 / 2dan100 / (10 / 2)): Dua operator/setingkat dievaluasi dari kiri ke kanan:(100 / 10) / 2menghasilkan 5. Mengganti pengelompokan dengan tanda kurung mengubah hasil menjadi 20 karena pembagian kedua yang dijalankan lebih dulu. - Baris 19-20 (
-2 + 3dan-(2 + 3)): Unary minus mengikat lebih kuat daripada+biner, sehingga-2terbentuk dulu dan hasilnya 1. Tanpa operator unary,-(2 + 3)menandakan negasi dari hasil penjumlahan, yaitu -5. - Baris 23-25 (
aktif, penuh, kosong := ...dst.): Operator&&(tingkat 2) menang atas||(tingkat 1). Ekspresiaktif || penuh && kosongdibacaaktif || (penuh && kosong)sehingga hasilnyatrue; pengelompokan eksplisit(aktif || penuh) && kosongmenghasilkanfalse. Tiga variable bool dipakai di sini agar tiap operand berbeda dan urutan pengikatannya terlihat jelas.
Tanda Kurung untuk Kejelasan #
Tabel prioritas menjawab pertanyaan “siapa lebih dulu” secara teknis, tetapi tidak menjamin kode mudah dibaca manusia. Praktik yang baik di komunitas Go: tuliskan tanda kurung setiap kali operator dari tingkat yang berbeda bercampur dengan cara yang tidak lazim, terutama pada pergeseran bit seperti 1 << (2 + 3) di atas. Sebaliknya, pengelompokan yang sudah jelas seperti (a + b) * c atau (admin & tulis) != 0 pada chapter Operator Bitwise
cukup ditulis langsung sebagai a + b * c bila memang itu maksudnya.
Referensi #
- Spesifikasi Go: Operator precedence — tabel prioritas resmi beserta aturan asosiasi.
- Spesifikasi Go: Operators — daftar lengkap operator beserta operand dan kelasnya.
- Effective Go — panduan gaya penulisan Go dari tim pengembangnya.
Dengan tabel prioritas di tangan, kita sudah sanggup membaca ekspresi Go apa pun barunya. Seluruh bekal Section ini — aritmatika, perbandingan, logika, bitwise, assignment, increment, pointer, dan prioritas — akan langsung terpakai pada Section berikutnya: pernyataan if dan else yang mengubah hasil perbandingan menjadi keputusan program, dimulai dari chapter If dan Else
.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
prioritas.go
Unduh berkaspackage main
import "fmt"
func main() {
// * lebih tinggi dari +
fmt.Println("2 + 3 * 4 =", 2+3*4)
fmt.Println("(2 + 3) * 4 =", (2+3)*4)
// << lebih tinggi dari +, bukan sebaliknya
fmt.Println("1 << 2 + 3 =", 1<<2+3)
fmt.Println("1 << (2 + 3) =", 1<<(2+3))
// Operator setara dievaluasi dari kiri ke kanan
fmt.Println("100 / 10 / 2 =", 100/10/2)
fmt.Println("100 / (10 / 2) =", 100/(10/2))
// Operator unary mengikat paling kuat
fmt.Println("-2 + 3 =", -2+3)
fmt.Println("-(2 + 3) =", -(2 + 3))
// && lebih tinggi dari ||
aktif, penuh, kosong := true, false, false
fmt.Println("aktif || penuh && kosong =", aktif || penuh && kosong)
fmt.Println("(aktif || penuh) && kosong =", (aktif || penuh) && kosong)
}