Pola hasil, err pada chapter sebelumnya bekerja baik, tetapi ada satu sumber kebingungan yang tersisa: urutan. Ketika tipe kembalian sama — misalnya (int, int) — pemanggil harus menghafal posisi mana yang terkecil dan mana yang terbesar. Go menyediakan perbaikan kecil yang berdampak besar: nilai kembalian boleh diberi nama langsung di tanda kurung deklarasi. Pada chapter ini kita akan memakai named return values beserta bentuk return tanpa isi (naked return), lalu melihat interaksinya yang unik dengan defer.
Memberi Nama Nilai Kembalian #
Nama ditulis sebelum tipe untuk setiap nilai kembalian, seperti parameter: (hasil int, err error). Efeknya ada dua. Pertama, dokumentasi pemanggil menjadi eksplisit — tanda tangan bagi(a, b int) (hasil int, err error) terbaca sebagai “hasil pembagian dan status galat” tanpa perlu menebak urutan. Kedua, variabel hasil dan err otomatis tersedia di dalam badan fungsi sebagai variabel biasa yang sudah terdeklarasi dengan nilai nolnya:
// bagi memakai named return values hasil dan err.
func bagi(a, b int) (hasil int, err error) {
if b == 0 {
err = errors.New("pembagi tidak boleh nol")
return // naked return: mengirim hasil=0 dan err.
}
hasil = a / b
return // naked return: mengirim hasil dan err=nil.
}Perhatikan bahwa badan fungsi tidak lagi mendeklarasikan hasil dan err, cukup mengisi keduanya dengan operator =. Nilai awal variabel kembalian adalah zero value masing-masing tipe — 0 untuk int dan nil untuk error — sehingga jalur gagal di atas cukup mengisi err saja dan hasil tetap 0.
Naked Return #
Statement return tanpa nilai mengirim variabel kembalian apa adanya. Pada jalur gagal bagi, return mengirim pasangan hasil (masih 0) dan err (sudah terisi). Pada jalur sukses, hasil sudah diisi a / b sementara err tetap nil, sehingga return telanjang mengirim keduanya dengan benar. Pemanggil tidak melihat perbedaan apa pun: hasil, err := bagi(12, 3) tetap menghasilkan 4 dan nil, sama persis dengan bentuk anonim di chapter sebelumnya.
Interaksi dengan defer #
Nama kembalian punya satu kegunaan lanjutan yang penting: defer bisa mengubah nilai yang akhirnya dikirim pemanggil. Fungsi yang di-defer berjalan setelah statement return menyalin variabel kembalian, tetapi sebelum kontrol benar-benar kembali — sehingga penulisan hasil += 100 di dalamnya menambah nilai yang diterima pemanggil:
// bungkus menaikkan nilai kembalian lewat defer.
func bungkus(angka int) (hasil int) {
defer func() {
hasil += 100
}()
hasil = angka * 2
return
}Tanpa nama kembalian, trik ini mustahil karena fungsi defer tidak punya variabel hasil untuk ditulis. Pemakaian nyatanya bukan menambah angka, melainkan memastikan pembersihan: menandai error tambahan, mencatat durasi, atau memperbaiki status sebelum nilai sampai ke pemanggil. Kita sudah membahas urutan eksekusi defer pada chapter Defer
; pola ini kelak muncul lagi di pembahasan error.
Program Utuh #
Berkas named-return.go menjalankan bagi bernama kembalian dan bungkus ber-defer dalam satu program. Jalankan dari direktori chapter:
go run named-return.goOutput yang Dihasilkan:
4 <nil>
0 pembagi tidak boleh nol
bungkus(5) = 110Mari kita telaah baris demi baris program di atas:
- Baris 9 (
func bagi(a, b int) (hasil int, err error)): mendeklarasikan variabel kembalianhasildanerryang otomatis tersedia di badan fungsi. - Baris 11 (
err = errors.New(...)): jalur gagal hanya mengisierr;hasilmempertahankan zero value0. - Baris 12 dan 15 (
returntanpa nilai): dua naked return mengirim pasanganhasildanerrapa adanya — jalur gagal mengirim0dan galat, jalur sukses mengirim hasil bagi dannil. - Baris 18–25 (fungsi
bungkus): fungsi yang di-defermenambah100padahasilsetelahreturnmenyalin nilaiangka * 2. - Baris 27–35 (isi
main): memanggilbagidua kali — hasil4 <nil>untuk pembagian sukses dan0 pembagi tidak boleh noluntuk pembagi nol — lalu mencetakbungkus(5)yang menjadi110karena sentuhandefer.
Baris 4 <nil> memperlihatkan pencetakan pasangan nilai dan error secara mentah: fmt.Println menampilkan nil dalam bentuk teksnya <nil>. Ketika jumlah argumen fleksibel justru yang kita butuhkan — misalnya fungsi penjumlah yang menerima dua maupun sepuluh angka — Go menyediakan parameter variadic, bahasan chapter Variadic Function
.
Referensi #
- Function declarations — Go Spec — aturan resmi nama nilai kembalian.
- Effective Go: multiple returns — penjelasan pola hasil dan galat.
- Defer, panic, and recover — Go Blog
— perilaku
deferterhadap nilai kembalian.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
named-return.go
Unduh berkaspackage main
import (
"errors"
"fmt"
)
// bagi memakai named return values hasil dan err.
func bagi(a, b int) (hasil int, err error) {
if b == 0 {
err = errors.New("pembagi tidak boleh nol")
return // naked return: mengirim hasil=0 dan err.
}
hasil = a / b
return // naked return: mengirim hasil dan err=nil.
}
// bungkus menaikkan nilai kembalian lewat defer.
func bungkus(angka int) (hasil int) {
defer func() {
hasil += 100
}()
hasil = angka * 2
return
}
func main() {
hasil, err := bagi(12, 3)
fmt.Println(hasil, err)
hasil, err = bagi(12, 0)
fmt.Println(hasil, err)
fmt.Println("bungkus(5) =", bungkus(5))
}