Kembali ke Artikel

Belajar Golang dari Nol #6: Perulangan for dan Percabangan

Solusi IT

Di Belajar Golang dari Nol #5 kita sudah kenalan dengan slice dan map. Waktu itu kita sempat memakai for range sekilas untuk membaca isinya, tapi belum dibedah dalam. Sekarang giliran materi itu dituntaskan. Di bagian keenam ini kita bahas perulangan dan percabangan di Go: for dengan semua bentuknya, for range sampai tuntas, break dan continue, if else, switch, sampai label untuk loop bersarang.

Dua materi ini adalah otot utama program. Hampir semua logika, dari menghitung total belanja sampai menyaring data kotor, dibangun dari perulangan dan percabangan. Jadi kita jalan pelan seperti biasa, satu konsep, satu contoh, langsung praktik.

for, Satu-satunya Perulangan di Go

Kalau kamu pernah menyentuh bahasa lain, mungkin kamu terbiasa dengan while, do while, dan for sebagai tiga hal berbeda. Go memangkas semuanya jadi satu kata kunci saja: for. Tidak ada while di Go. Satu kata kunci, tiga cara pakai.

Bentuk klasik: init, kondisi, post

Ini bentuk yang paling sering kamu temui. Ada tiga bagian yang dipisah titik koma: inisialisasi, kondisi, dan apa yang dilakukan setiap akhir putaran.

package main

import "fmt"

func main() {
	for i := 1; i <= 5; i++ {
		fmt.Println("Putaran ke", i)
	}
}

Bacanya seperti resep: mulai dari i bernilai 1, ulangi selama i masih 5 atau kurang, dan setiap selesai satu putaran tambahkan i sebanyak satu. Program ini mencetak lima baris, dari putaran 1 sampai 5.

Bentuk while: kondisi saja

Buang bagian init dan post, sisakan kondisinya. Hasilnya persis while di bahasa lain.

saldo := 100000
for saldo > 0 {
	fmt.Println("Sisa saldo:", saldo)
	saldo -= 30000
}

Selama saldo masih di atas nol, loop terus jalan. Begitu saldo habis, loop berhenti sendiri. Anggap saja seperti main game dengan koin: selama koin masih ada, kamu boleh main terus.

Bentuk tanpa kondisi: loop tak berujung

Tulis for polos tanpa apa pun, maka loop akan berputar selamanya. Ini bukan bug, ini fitur. Server web misalnya, memang harus terus hidup menunggu request. Tapi untuk program biasa, kamu wajib menyediakan pintu keluar lewat break.

hitung := 0
for {
	hitung++
	fmt.Println("Masih jalan, hitung:", hitung)
	if hitung == 3 {
		break
	}
}

Tanpa break di situ, program ini tidak akan pernah selesai dan terminal kamu penuh angka. Kalau itu terjadi, tekan Ctrl+C untuk menghentikannya.

for range: Cara Nyaman Menyusuri Slice dan Map

Di bagian 5 kita sudah pakai for range sekilas. Sekarang kita bongkar aturannya satu per satu, karena bentuk inilah yang paling sering kamu tulis sehari-hari.

Range pada slice

Saat dipakai pada slice, range memberi dua nilai setiap putaran: index dan isinya.

buah := []string{"mangga", "jeruk", "salak"}

for i, nama := range buah {
	fmt.Println(i, nama)
}

Output:

0 mangga
1 jeruk
2 salak

Sering kali kamu hanya butuh isinya, tidak peduli index-nya. Di sinilah underscore berperan. Tanda _ artinya kamu bilang ke Go: nilai ini sengaja saya abaikan. Ini penting karena Go menolak compile kalau ada variabel yang dideklarasikan tapi tidak dipakai.

for _, nama := range buah {
	fmt.Println(nama)
}

Sebaliknya, kalau kamu cuma butuh index, tulis satu variabel saja: for i := range buah. Nilainya otomatis hanya index.

Range pada map

Pada map, dua nilai yang diberikan adalah key dan value.

stok := map[string]int{
	"mangga": 10,
	"jeruk":  5,
	"salak":  8,
}

for nama, jumlah := range stok {
	fmt.Println(nama, "=", jumlah)
}

Nah, ini catatan yang sering bikin pemula bingung. Urutan hasil range pada map itu acak. Jalankan program yang sama dua kali, urutannya bisa beda. Ini disengaja oleh pembuat Go supaya programmer tidak menggantungkan logika pada urutan map. Jadi kalau output map kamu terlihat berantakan urutannya, program kamu tidak rusak. Memang begitu sifatnya. Kalau butuh urutan yang pasti, kumpulkan dulu key-nya ke slice, urutkan, lalu loop slice itu.

break dan continue

Dua kata ini adalah rem dan gas di dalam loop. break menghentikan loop sepenuhnya. continue melompati sisa putaran saat ini dan langsung lanjut ke putaran berikutnya.

Contoh nyata untuk continue: menyaring data yang tidak valid. Misal kamu punya daftar nilai ujian, tapi ada beberapa angka aneh yang harus dilewati.

nilai := []int{80, -5, 90, 200, 75}

for _, n := range nilai {
	if n < 0 || n > 100 {
		continue
	}
	fmt.Println("Nilai valid:", n)
}

Angka -5 dan 200 dilompati, sisanya dicetak. Sedangkan break cocok saat kamu mencari sesuatu dan ingin berhenti begitu ketemu, supaya tidak buang tenaga memeriksa sisa data.

daftar := []string{"Andi", "Budi", "Citra", "Dewi"}
dicari := "Citra"

for i, nama := range daftar {
	if nama == dicari {
		fmt.Println("Ketemu di index", i)
		break
	}
}

if, else if, dan else

Percabangan di Go bentuknya sederhana. Kondisi tidak perlu tanda kurung, tapi kurung kurawal wajib ada.

skor := 78

if skor >= 85 {
	fmt.Println("Grade A")
} else if skor >= 70 {
	fmt.Println("Grade B")
} else {
	fmt.Println("Belum lulus")
}

Go mengecek dari atas ke bawah dan berhenti di kondisi pertama yang cocok. Skor 78 masuk Grade B, karena syarat Grade A gagal lebih dulu.

if dengan statement pendek

Ini gaya khas Go yang akan sering kamu lihat di kode orang lain. Kamu boleh menaruh satu statement pendek sebelum kondisi, dipisah titik koma. Masih ingat pola comma ok saat mengecek isi map di bagian 5? Biasanya pola itu ditulis begini:

stok := map[string]int{"mangga": 10}

if jumlah, ok := stok["mangga"]; ok {
	fmt.Println("Stok mangga:", jumlah)
} else {
	fmt.Println("Mangga tidak ada di data")
}

Variabel jumlah dan ok lahir di dalam if itu dan hanya hidup di situ. Setelah blok if selesai, keduanya lenyap. Ini bagus, karena variabel bantu tidak berserakan mengotori bagian lain fungsi.

switch: if else Berantai yang Lebih Rapi

Kalau cabangnya banyak, if else berantai mulai capek dibaca. switch hadir untuk itu.

hari := "sabtu"

switch hari {
case "sabtu", "minggu":
	fmt.Println("Akhir pekan")
case "jumat":
	fmt.Println("Sebentar lagi libur")
default:
	fmt.Println("Hari kerja")
}

Perhatikan satu case boleh menampung beberapa nilai sekaligus, dipisah koma. default jalan kalau tidak ada case yang cocok.

Ada satu perbedaan besar dengan bahasa seperti C atau JavaScript: switch di Go tidak butuh break. Begitu satu case cocok dan selesai dijalankan, Go otomatis keluar dari switch. Kamu tidak akan kena bug klasik lupa break yang bikin eksekusi bocor ke case berikutnya. Kalau kamu memang sengaja ingin lanjut ke case di bawahnya, ada kata kunci fallthrough. Cukup tahu saja dulu, praktiknya jarang sekali dipakai.

switch tanpa kondisi

Bentuk ini favorit banyak programmer Go. Tulis switch tanpa apa pun, lalu tiap case berisi kondisi boolean. Hasilnya pengganti if else berantai yang jauh lebih enak dibaca.

skor := 78

switch {
case skor >= 85:
	fmt.Println("Grade A")
case skor >= 70:
	fmt.Println("Grade B")
default:
	fmt.Println("Belum lulus")
}

Sama seperti if else, pengecekan berjalan dari atas ke bawah dan berhenti di yang pertama cocok.

Label: Keluar dari Loop Bersarang

Satu materi kecil sebelum latihan. break biasa hanya menghentikan loop terdalam. Kalau kamu punya loop di dalam loop dan ingin keluar dari semuanya sekaligus, pakai label.

luar:
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			if i*j >= 4 {
				break luar
			}
			fmt.Println(i, j)
		}
	}

break luar langsung melompat keluar dari kedua loop. Jujur saja, label jarang dipakai di kode sehari-hari. Cukup tahu bahwa fitur ini ada, supaya tidak bingung saat menemukannya di kode orang lain.

Latihan: Rekap Penjualan Mingguan

Sekarang kita gabungkan semua materi hari ini plus struct dari bagian 4 dan slice dari bagian 5. Skenarionya: kamu punya catatan transaksi toko selama seminggu. Sebagian transaksi batal dan harus dilewati. Sisanya dihitung totalnya, dirata-rata, dan diberi kategori nominal pakai switch.

package main

import "fmt"

type Transaksi struct {
	ID     int
	Produk string
	Nilai  int
	Batal  bool
}

func main() {
	transaksi := []Transaksi{
		{ID: 1, Produk: "Kaos Polos", Nilai: 150000, Batal: false},
		{ID: 2, Produk: "Jaket Hoodie", Nilai: 450000, Batal: false},
		{ID: 3, Produk: "Topi Baseball", Nilai: 75000, Batal: true},
		{ID: 4, Produk: "Celana Chino", Nilai: 320000, Batal: false},
		{ID: 5, Produk: "Kemeja Flanel", Nilai: 260000, Batal: false},
		{ID: 6, Produk: "Sandal Jepit", Nilai: 35000, Batal: true},
		{ID: 7, Produk: "Sepatu Lari", Nilai: 780000, Batal: false},
	}

	total := 0
	jumlahValid := 0

	fmt.Println("=== Rekap Penjualan Mingguan ===")

	for _, t := range transaksi {
		if t.Batal {
			fmt.Printf("Transaksi #%d (%s) batal, dilewati\n", t.ID, t.Produk)
			continue
		}

		var kategori string
		switch {
		case t.Nilai >= 500000:
			kategori = "besar"
		case t.Nilai >= 200000:
			kategori = "sedang"
		default:
			kategori = "kecil"
		}

		fmt.Printf("#%d %-15s Rp%-8d kategori %s\n", t.ID, t.Produk, t.Nilai, kategori)

		total += t.Nilai
		jumlahValid++
	}

	fmt.Println("--------------------------------")
	fmt.Println("Transaksi valid :", jumlahValid)
	fmt.Println("Total penjualan : Rp", total)

	if jumlahValid > 0 {
		rata := total / jumlahValid
		fmt.Println("Rata-rata       : Rp", rata)
	}
}

Jalankan dengan go run main.go. Hasilnya:

=== Rekap Penjualan Mingguan ===
#1 Kaos Polos      Rp150000   kategori kecil
#2 Jaket Hoodie    Rp450000   kategori sedang
Transaksi #3 (Topi Baseball) batal, dilewati
#4 Celana Chino    Rp320000   kategori sedang
#5 Kemeja Flanel   Rp260000   kategori sedang
Transaksi #6 (Sandal Jepit) batal, dilewati
#7 Sepatu Lari     Rp780000   kategori besar
--------------------------------
Transaksi valid : 5
Total penjualan : Rp 1960000
Rata-rata       : Rp 392000

Coba telusuri alurnya pelan-pelan. Loop for range menyusuri slice of struct. continue melewati dua transaksi yang batal, jadi keduanya tidak ikut total. Switch tanpa kondisi memberi label kategori berdasarkan nominal. Terakhir, if di bawah memastikan pembagian rata-rata hanya jalan kalau ada transaksi valid, supaya program tidak membagi dengan nol.

Sebagai latihan mandiri, coba ubah programnya sedikit. Tambahkan variabel penghitung untuk tiap kategori, lalu cetak berapa transaksi besar, sedang, dan kecil di bagian rekap. Semua bahannya sudah kamu pegang.

Rangkuman dan Bagian Selanjutnya

Hari ini kamu sudah menguasai alat kontrol alur di Go:

  • for adalah satu-satunya perulangan, dengan tiga bentuk: klasik, gaya while, dan tanpa kondisi
  • for range menyusuri slice dan map, dengan catatan urutan map selalu acak
  • break menghentikan loop, continue melompati satu putaran
  • if bisa membawa statement pendek, cocok untuk pola comma ok
  • switch di Go otomatis berhenti per case, tanpa perlu break, dan bentuk tanpa kondisinya menggantikan if else berantai
  • label dipakai untuk keluar dari loop bersarang, meski jarang dibutuhkan

Di bagian 7 kita masuk ke topik yang sering dianggap seram padahal sebenarnya ramah: Pointer di Go: Memahami Alamat Memori Tanpa Pusing. Sampai ketemu di sana.

Seri ini ditulis dari pengalaman tim Arrazy membangun berbagai sistem aplikasi untuk bisnis di Indonesia.

BACA JUGA

Artikel Lainnya di Kategori Golang

Ingin Membaca Artikel Lainnya?

Temukan lebih banyak insight dan tips tentang teknologi dan bisnis digital.

Lihat Semua Artikel