Perulangan

for sebagai satu-satunya perulangan: tiga bentuk dan range.

Daftar isi

Pernyataan for adalah satu-satunya pernyataan perulangan di Go, sehingga seluruh variasi perulangan dituliskan melaluinya. Topik ini membahas tiga bentuknya, yaitu bentuk dengan tiga bagian, bentuk bersyarat setara while, dan bentuk tanpa kondisi. Bagian akhir topik membahas klausa range untuk menjelajah kumpulan data, break untuk menghentikan putaran, dan continue untuk melompat ke iterasi berikutnya. Setiap bentuk diperagakan lewat program utuh yang keluarannya diambil langsung dari eksekusinya.

Bentuk for dengan tiga bagian#

Bentuk lengkap for memuat tiga bagian yang dipisahkan titik koma. Bagian pertama adalah pernyataan init yang dijalankan sekali sebelum putaran pertama, bagian kedua adalah kondisi yang diperiksa sebelum setiap iterasi, dan bagian ketiga adalah pernyataan post yang dijalankan setelah setiap iterasi. Perulangan berhenti ketika kondisi bernilai false. Ketiga bagian itu boleh dikosongkan, tetapi titik koma pemisahnya tetap ditulis. Susunan tiga bagian ini meniru bentuk perulangan pada bahasa turunan C, tetapi ditulis tanpa tanda kurung pengapit.

Program berikut menjumlahkan empat nilai ujian yang tersimpan dalam slice, yaitu kumpulan data berukuran fleksibel. Variabel i bergerak dari 0 sampai 3 karena indeks slice dimulai dari 0, sedangkan len(nilai) menyatakan banyak elemennya.

go rerata.go
package main

import "fmt"

func main() {
	nilai := []int{80, 75, 90, 65}

	total := 0
	for i := 0; i < len(nilai); i++ {
		total += nilai[i]
	}

	fmt.Printf("Jumlah nilai: %d\n", total)
	fmt.Printf("Rata-rata: %.1f\n", float64(total)/float64(len(nilai)))
}
text Keluaran
Jumlah nilai: 310
Rata-rata: 77.5

Pembagian rata-rata mengonversi kedua operan ke float64 terlebih dahulu agar hasil pembagian memuat angka di belakang koma. Verb %.1f kemudian membatasi pencetakan menjadi satu angka desimal. Konversi itu wajib ditulis eksplisit karena pembagian antara dua bilangan bulat di Go membuang bagian desimalnya. Program dijalankan dengan go run rerata.go dari folder kerja tetap:

bash
# siapkan folder kerja untuk topik ini
mkdir -p /tmp/goalur/perulangan
cp rerata.go /tmp/goalur/perulangan/
cd /tmp/goalur/perulangan

# periksa format sebelum menjalankan programnya
gofmt -l .

# jalankan programnya
go run rerata.go
text Keluaran
Jumlah nilai: 310
Rata-rata: 77.5

Bentuk seperti while dan for tanpa kondisi#

Menuliskan kondisi saja tanpa init dan post menghasilkan perulangan yang berperilaku sama seperti while pada bahasa lain, yaitu perulangan yang diperiksa ulang sebelum setiap putaran hingga kondisinya salah. Go tidak memiliki kata kunci while, sehingga bentuk inilah penggantinya. Bentuk ini lazim dipakai ketika banyaknya putaran tidak diketahui lebih dahulu dan bergantung pada keadaan yang berubah.

go sisa.go
package main

import "fmt"

func main() {
	sisa := 30

	for sisa > 0 {
		fmt.Println("Sisa waktu:", sisa, "detik")
		sisa -= 10
	}

	fmt.Println("Waktu habis")
}
text Keluaran
Sisa waktu: 30 detik
Sisa waktu: 20 detik
Sisa waktu: 10 detik
Waktu habis

Nilai sisa berkurang sepuluh pada setiap putaran melalui baris yang berada di dalam badan perulangan. Bentuk berikutnya adalah for tanpa kondisi sama sekali. Bentuk ini ditulis sebagai for { } dan mengulang tanpa henti. Keluar dari putaran mengandalkan break, sedangkan continue melompat langsung ke iterasi berikutnya.

Program berikut memanggil nomor antrean satu per satu. Nomor kelipatan tiga dilewati lewat continue, dan pemanggilan berhenti lewat break ketika nomor melewati tujuh.

go antrean.go
package main

import "fmt"

func main() {
	nomor := 0

	for {
		nomor++
		if nomor%3 == 0 {
			continue
		}
		if nomor > 7 {
			break
		}
		fmt.Println("Nomor antrean dipanggil:", nomor)
	}

	fmt.Println("Loket ditutup")
}
text Keluaran
Nomor antrean dipanggil: 1
Nomor antrean dipanggil: 2
Nomor antrean dipanggil: 4
Nomor antrean dipanggil: 5
Nomor antrean dipanggil: 7
Loket ditutup

Nomor 3 dan 6 tidak tercetak karena continue melompati baris pencetakan pada iterasi itu, sedangkan nomor 8 memicu break sebelum sempat dicetak. Baris “Loket ditutup” dieksekusi setelah perulangan benar-benar berhenti.

range untuk menjelajah kumpulan data#

Klausa range pada for mengambil elemen satu per satu dari kumpulan data tanpa mengurus indeks dan batasnya secara manual. Untuk slice, bentuk for i, v := range nilai memberikan indeks pada i dan salinan nilai elemen pada v di setiap iterasi. Urutan variabelnya selalu indeks terlebih dahulu, sedangkan tanda _ membuang variabel yang tidak dipakai. Bentuk for range nilai tanpa variabel juga sah apabila keduanya tidak diperlukan.

Program berikut mencetak setiap nilai beserta posisinya, lalu menjumlahkan seluruhnya dengan membuang indeksnya:

go rangenilai.go
package main

import "fmt"

func main() {
	nilai := []int{80, 75, 90, 65}

	for i, v := range nilai {
		fmt.Printf("Nilai ke-%d: %d\n", i, v)
	}

	total := 0
	for _, v := range nilai {
		total += v
	}
	fmt.Printf("Jumlah nilai: %d\n", total)
}
text Keluaran
Nilai ke-0: 80
Nilai ke-1: 75
Nilai ke-2: 90
Nilai ke-3: 65
Jumlah nilai: 310

Kedua perulangan menghasilkan jumlah yang sama dengan perhitungan manual pada bentuk tiga bagian, tetapi versi range tidak memuat pengelolaan indeks sama sekali. range juga berlaku untuk peta (map) dan string. Urutan kunjungan pada peta tidak dijamin dan dapat berubah dari satu eksekusi ke eksekusi lain. Pada string, range memberikan posisi byte beserta karakter Unicode pada posisi tersebut.

Kesalahan umum#

Tiga kesalahan berikut sering muncul ketika perulangan mulai ditulis.

  1. Mencari kata kunci while atau do while. Keduanya tidak ada di Go. Compiler memperlakukan while sebagai nama variabel biasa, sehingga barisnya ditolak saat kompilasi. Penggantinya adalah bentuk for yang hanya memuat kondisi:
go Kata kunci while yang tidak ada di Go
// tidak-dijalankan
while sisa > 0 { // error kompilasi: while diperlakukan sebagai nama biasa
	sisa--
}
  1. Urutan variabel range yang tertukar. Indeks selalu menjadi variabel pertama dan nilai elemen menjadi variabel kedua. Pertukaran urutan tetap lolos kompilasi karena keduanya bertipe sama pada slice int, tetapi keluarannya menjadi salah tanpa pesan error apa pun:
go Urutan variabel range yang tertukar
// tidak-dijalankan
for v, i := range nilai {
	fmt.Println(v, i) // v berisi indeks, i berisi nilai elemen
}
  1. Bagian post yang tidak menggerakkan kondisi. Bentuk for i := 0; i < 10; dengan bagian post yang kosong membuat i tidak pernah bertambah, sehingga kondisinya selalu benar dan perulangan tidak berhenti. Pastikan salah satu bagiannya, baik post maupun badan perulangan, menggerakkan kondisi menuju pemberhentian.

Ringkasan#

  • for adalah satu-satunya pernyataan perulangan di Go dan muncul dalam tiga bentuk, yaitu tiga bagian lengkap, kondisi saja, dan tanpa kondisi.
  • Pada bentuk tiga bagian, init dijalankan sekali, kondisi diperiksa sebelum setiap iterasi, dan post dijalankan setelahnya.
  • break menghentikan perulangan lebih awal, sedangkan continue melompat ke iterasi berikutnya.
  • range memberikan indeks terlebih dahulu lalu nilai elemen, dan _ membuang variabel yang tidak dipakai.

Referensi#