Setiap bilangan bulat di dalam memori hanyalah rangkaian bit bernilai 0 dan 1. Ketika program perlu bekerja pada level tersebut — misalnya menyimpan banyak penanda dalam satu bilangan atau memproses data biner — kita memakai operator bitwise. Go menyediakan AND, OR, XOR, AND NOT, serta pergeseran bit ke kiri dan ke kanan. Pada chapter ini kita mencoba setiap operator dengan visualisasi biner, membaca tabel kebenaran per bit, lalu menerapkan pola yang paling sering dipakai di dunia nyata: mask permission.
Daftar Operator Bitwise #
Tabel berikut merangkum operator bitwise pada Go. Seluruh operator hanya bekerja pada tipe bilangan bulat, bukan pada float maupun bool:
| Operator | Nama | Contoh | Hasil |
|---|---|---|---|
& | AND | 0b1010 & 0b0110 | 0b0010 |
| | OR | 0b1010 | 0b0110 | 0b1110 |
^ | XOR (biner) | 0b1010 ^ 0b0110 | 0b1100 |
^ | NOT (unary) | ^c, c uint8 = 0b0000_1010 | 0b1111_0101 |
&^ | AND NOT | 0b1010 &^ 0b0110 | 0b1000 |
<< | Geser kiri | 1 << 3 | 8 |
>> | Geser kanan | 16 >> 2 | 4 |
Operator ^ mempunyai dua makna tergantung posisi. Di antara dua operand, ^ adalah XOR: hasilnya 1 hanya jika kedua bit berbeda. Di depan satu operand, ^ adalah NOT yang membalik seluruh bit. Operator &^ membersihkan bit: setiap bit 1 pada operand kanan dipaksa menjadi 0 pada hasil.
Tabel Kebenaran per Bit #
Karena operator bitwise memproses setiap bit secara mandiri, tabel kebenaran satu bit berikut merangkum tiga operator utama:
| a | b | a & b | a | b | a ^ b |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 1 | 0 | 0 | 1 | 1 |
| 1 | 1 | 1 | 1 | 0 |
Program berikut menerapkan tabel tersebut pada dua bilangan empat bit, lalu mencoba unary NOT dan pergeseran bit. Literal 0b1010 adalah notasi biner; Go juga mendukung notasi heksadesimal seperti 0xF:
package main
import "fmt"
func main() {
a := 0b1010 // desimal 10
b := 0b110 // desimal 6
fmt.Printf("a = %04b (%d)\n", a, a)
fmt.Printf("b = %04b (%d)\n", b, b)
fmt.Printf("a & b = %04b (%d)\n", a&b, a&b)
fmt.Printf("a | b = %04b (%d)\n", a|b, a|b)
fmt.Printf("a ^ b = %04b (%d)\n", a^b, a^b)
fmt.Printf("a &^ b = %04b (%d)\n", a&^b, a&^b)
// ^ sebagai operator unary: membalik semua bit (NOT)
var c uint8 = 0b0000_1010
fmt.Printf("^c = %08b (%d)\n", ^c, ^c)
// Pergeseran bit ke kiri dan ke kanan
fmt.Printf("1 << 3 = %d\n", 1<<3)
fmt.Printf("16 >> 2 = %d\n", 16>>2)
// Jumlah pergeseran tidak dibatasi lebar tipe
var kecil uint8 = 1
var geser uint = 9
fmt.Println("kecil << geser =", kecil<<geser)
}Output yang Dihasilkan:
a = 1010 (10)
b = 0110 (6)
a & b = 0010 (2)
a | b = 1110 (14)
a ^ b = 1100 (12)
a &^ b = 1000 (8)
^c = 11110101 (245)
1 << 3 = 8
16 >> 2 = 4
kecil << geser = 0Mari kita telaah baris demi baris program di atas:
- Baris 6-7 (
a := 0b1010danb := 0b110): Kedua variable memakai literal biner:0b1010adalah 10 desimal dan0b110adalah 6 desimal. Notasi biner memudahkan kita membaca bitnya. - Baris 11 (
a & b): AND membandingkan kedua bilangan bit demi bit; hanya bit yang1di kedua tempat tetap1, menghasilkan0010. - Baris 12-13 (
a | bdana ^ b): OR menghasilkan1110karena bit1dari operand mana pun ikut terbawa. XOR menghasilkan1100; hanya bit yang berbeda antara kedua operand yang bernilai1. - Baris 14 (
a &^ b): AND NOT menghapus bit0110dari1010dan menyisakan1000— gunakan operator ini untuk mematikan penanda. - Baris 17-18 (
var c uint8 ... ^c): Unary NOT membalik kedelapan bitc:0000_1010menjadi1111_0101(245). Tipeuint8dipakai agar mudah dibaca; padaint8, bit paling kiri adalah penanda tanda. - Baris 21-22 (
1 << 3dan16 >> 2): Geser kiri mengalikan dengan 2 sebanyak tiga kali (1menjadi8); geser kanan membagi dengan 2 sebanyak dua kali (16menjadi4). - Baris 25-27 (
kecil << geser): Jumlah pergeseran tidak dibatasi lebar tipe: menggeseruint8sebanyak 9 kali mendorong seluruh bit keluar, sehingga hasilnya0.
Mask Permission: Praktik Nyata Bitwise #
Pola paling populer operator bitwise adalah bit mask: beberapa penanda disimpan dalam satu bilangan, satu bit untuk setiap penanda. Ketiga konstanta berikut dideklarasikan seperti pada chapter Konstanta :
package main
import "fmt"
const (
baca = 1 << 0 // 001 = 1
jalankan = 1 << 1 // 010 = 2
tulis = 1 << 2 // 100 = 4
)
func main() {
// OR menggabungkan beberapa permission menjadi satu mask
admin := baca | jalankan | tulis
tamu := baca
fmt.Printf("admin = %03b (%d)\n", admin, admin)
fmt.Printf("tamu = %03b (%d)\n", tamu, tamu)
// AND menguji apakah satu permission aktif
fmt.Println("admin bisa tulis :", admin&tulis != 0)
fmt.Println("tamu bisa tulis :", tamu&tulis != 0)
// AND NOT mencabut permission dari mask
editor := admin &^ jalankan
fmt.Printf("editor = %03b (%d)\n", editor, editor)
fmt.Println("editor bisa jalankan:", editor&jalankan != 0)
}Output yang Dihasilkan:
admin = 111 (7)
tamu = 001 (1)
admin bisa tulis : true
tamu bisa tulis : false
editor = 101 (5)
editor bisa jalankan: falseMari kita telaah bagian-bagian penting program di atas:
- Baris 6-8 (
const ( baca = 1 << 0 ... )): Ketiga konstanta adalah pergeseran dari angka 1 sehingga setiap penanda menempati bit yang berbeda;1 << 2sekaligus mendokumentasikan posisinya. - Baris 13 (
admin := baca | jalankan | tulis): OR menggabungkan tiga penanda menjadi mask111(7) — satu bilangan kecil menyimpan tiga permission. - Baris 20-21 (
admin&tulis != 0): AND menguji satu bit: hasilnya tidak nol hanya jika bittulisaktif. Operator&mengikat lebih kuat daripada!=; tanda kurung(admin & tulis) != 0juga sah untuk kejelasan. - Baris 24 (
editor := admin &^ jalankan): AND NOT mencabut satu penanda tanpa mengganggu bit lain:111menjadi101(5). Pola|untuk memasang dan&^untuk mencabut dipakai luas pada konfigurasi sistem operasi dan packageflag.
Referensi #
- Spesifikasi Go: Operators — tabel resmi seluruh operator bitwise dan operandnya.
- Spesifikasi Go: Arithmetic operators — aturan pergeseran bit, termasuk shift count besar dan perbedaan signed/unsigned.
- Package math/bits — kumpulan fungsi manipulasi bit dari standard library.
Bekerja pada level bit sering diikuti operasi “ubah sedikit, simpan kembali” — misalnya menyalakan satu bit lalu menyimpannya pada variable yang sama. Chapter Assignment Operator
memperkenalkan bentuk ringkas |= dan &^= untuk pola tersebut.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
bitwise-demo.go
Unduh berkaspackage main
import "fmt"
func main() {
a := 0b1010 // desimal 10
b := 0b110 // desimal 6
fmt.Printf("a = %04b (%d)\n", a, a)
fmt.Printf("b = %04b (%d)\n", b, b)
fmt.Printf("a & b = %04b (%d)\n", a&b, a&b)
fmt.Printf("a | b = %04b (%d)\n", a|b, a|b)
fmt.Printf("a ^ b = %04b (%d)\n", a^b, a^b)
fmt.Printf("a &^ b = %04b (%d)\n", a&^b, a&^b)
// ^ sebagai operator unary: membalik semua bit (NOT)
var c uint8 = 0b0000_1010
fmt.Printf("^c = %08b (%d)\n", ^c, ^c)
// Pergeseran bit ke kiri dan ke kanan
fmt.Printf("1 << 3 = %d\n", 1<<3)
fmt.Printf("16 >> 2 = %d\n", 16>>2)
// Jumlah pergeseran tidak dibatasi lebar tipe
var kecil uint8 = 1
var geser uint = 9
fmt.Println("kecil << geser =", kecil<<geser)
}
perizinan.go
Unduh berkaspackage main
import "fmt"
const (
baca = 1 << 0 // 001 = 1
jalankan = 1 << 1 // 010 = 2
tulis = 1 << 2 // 100 = 4
)
func main() {
// OR menggabungkan beberapa permission menjadi satu mask
admin := baca | jalankan | tulis
tamu := baca
fmt.Printf("admin = %03b (%d)\n", admin, admin)
fmt.Printf("tamu = %03b (%d)\n", tamu, tamu)
// AND menguji apakah satu permission aktif
fmt.Println("admin bisa tulis :", admin&tulis != 0)
fmt.Println("tamu bisa tulis :", tamu&tulis != 0)
// AND NOT mencabut permission dari mask
editor := admin &^ jalankan
fmt.Printf("editor = %03b (%d)\n", editor, editor)
fmt.Println("editor bisa jalankan:", editor&jalankan != 0)
}