Banyak keputusan dalam program bergantung pada nilai yang harus dihitung lebih dulu: hasil konversi teks menjadi angka, hasil pencarian data, atau status sebuah operasi. Tanpa fitur khusus, kita terpaksa mendeklarasikan variabel sementara di luar if, lalu variabel tersebut menetap di fungsi padahal hanya dipakai sekali. Go mengatasinya dengan bentuk if yang memiliki initializer: satu statement singkat yang dijalankan tepat sebelum kondisi dievaluasi. Pada chapter ini kita memakai pola tersebut untuk konversi angka dengan strconv.Atoi dan memahami ruang lingkup variabelnya yang sengaja dibuat sempit.

Masalah Variabel Sementara #

Mari kita lihat versi tanpa initializer lebih dulu. Kode berikut mengubah teks menjadi angka, memeriksa galatnya, lalu memakai hasilnya:

go
nilai, err := strconv.Atoi(input)
if err != nil {
	fmt.Println("Konversi gagal:", err)
} else {
	fmt.Println("Angka:", nilai)
}

Kode di atas sah dan berjalan benar, tetapi variabel nilai dan err kini menempati seluruh sisa fungsi. Pembaca kode harus memindai ke bawah untuk memastikan apakah kedua variabel dipakai lagi, dan nama nilai atau err tidak bisa dipakai ulang untuk keperluan lain tanpa menimpa nilai lama. Pada fungsi panjang, tumpukan variabel sementara semacam ini cepat membuat kode sulit dibaca.

Bentuk if dengan Initializer #

Go memperbolehkan if diawali satu statement pendek sebelum kondisi, dipisahkan tanda titik koma. Bentuk lengkapnya adalah if statement; kondisi { ... }. Statement di sisi kiri dieksekusi tepat sebelum kondisi dievaluasi, dan variabel yang dideklarasikan di sana hanya hidup di dalam rantai if/else tersebut. Program berikut memakai bentuk ini dua kali untuk mengonversi dua input berbeda — satu input angka yang sah dan satu input teks yang gagal dikonversi:

go
package main

import (
	"fmt"
	"strconv"
)

func main() {
	input := "42"

	if nilai, err := strconv.Atoi(input); err != nil {
		fmt.Println("Konversi gagal:", err)
	} else {
		fmt.Printf("Input %q dikonversi menjadi angka %d\n", input, nilai)
	}

	salah := "empat puluh dua"

	if nilai, err := strconv.Atoi(salah); err != nil {
		fmt.Println("Konversi gagal:", err)
	} else {
		fmt.Printf("Input %q dikonversi menjadi angka %d\n", salah, nilai)
	}

	fmt.Println("Program selesai tanpa berhenti di tengah jalan.")
}

Jalankan program dari direktori chapter dengan perintah berikut:

bash
go run if-initializer.go

Output yang Dihasilkan:

text
Input "42" dikonversi menjadi angka 42
Konversi gagal: strconv.Atoi: parsing "empat puluh dua": invalid syntax
Program selesai tanpa berhenti di tengah jalan.

Mari kita telaah baris demi baris program di atas:

  1. Baris 3-6 (import "fmt" dan strconv): mengimpor dua package — fmt untuk mencetak output dan strconv untuk konversi teks menjadi angka.
  2. Baris 10 (input := "42"): menyimpan input pertama berupa string yang berisi angka.
  3. Baris 12 (if nilai, err := strconv.Atoi(input); err != nil): bagian sebelum titik koma memanggil strconv.Atoi yang mengembalikan dua nilai — angka hasil konversi dan galat. Kondisi err != nil memeriksa apakah galat terjadi.
  4. Baris 13 (fmt.Println("Konversi gagal:", err)): cabang ini berjalan ketika err tidak nil; detail pesannya diberikan oleh strconv.
  5. Baris 15 (fmt.Printf(...)): cabang else berjalan ketika konversi berhasil. Variabel nilai dari initializer tetap dapat dibaca di sini karena cabang else masih satu rantai dengan if.
  6. Baris 19-25 (salah := "empat puluh dua" dan if kedua): memakai nama nilai dan err kembali tanpa konflik, karena variabel dari initializer if pertama sudah tidak hidup lagi setelah rantainya selesai.
  7. Baris 27: mencetak pesan penutup. Program tidak pernah berhenti di tengah jalan meski ada input yang gagal dikonversi, karena kedua cabang hanya mencetak pesan.

Ruang Lingkup yang Sempit dan Pola err != nil #

Variabel dari initializer tidak dapat diakses setelah rantai if/else selesai. Menambahkan fmt.Println(nilai) setelah blok pada contoh di atas membuat kompilator menolak program dengan pesan undefined: nilai. Pembatasan ini disengaja: variabel yang hidupnya pendek membuat pembaca kode langsung tahu bahwa variabel tersebut hanya relevan untuk satu keputusan.

Bentuk if v, err := operasi(); err != nil adalah idiom paling sering Anda temui di Go, mulai dari membaca berkas sampai query database. Galat di Go adalah nilai biasa yang dikembalikan fungsi — bukan mekanisme lempar-terkecuali — sehingga pengecekan seperti ini mengalir alami di dalam if. Kita akan membedah tipe error secara tuntas pada Section Error Handling .

Percabangan bertingkat yang panjang bukan satu-satunya cara menyusun keputusan. Ketika program membandingkan satu nilai terhadap banyak kemungkinan, switch memberikan bentuk yang jauh lebih rapi — topik chapter berikutnya.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

if-initializer.go

Unduh berkas
go
package main

import (
	"fmt"
	"strconv"
)

func main() {
	input := "42"

	if nilai, err := strconv.Atoi(input); err != nil {
		fmt.Println("Konversi gagal:", err)
	} else {
		fmt.Printf("Input %q dikonversi menjadi angka %d\n", input, nilai)
	}

	salah := "empat puluh dua"

	if nilai, err := strconv.Atoi(salah); err != nil {
		fmt.Println("Konversi gagal:", err)
	} else {
		fmt.Printf("Input %q dikonversi menjadi angka %d\n", salah, nilai)
	}

	fmt.Println("Program selesai tanpa berhenti di tengah jalan.")
}