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:

go
// 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:

go
// 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:

bash
go run named-return.go

Output yang Dihasilkan:

text
4 <nil>
0 pembagi tidak boleh nol
bungkus(5) = 110

Mari kita telaah baris demi baris program di atas:

  1. Baris 9 (func bagi(a, b int) (hasil int, err error)): mendeklarasikan variabel kembalian hasil dan err yang otomatis tersedia di badan fungsi.
  2. Baris 11 (err = errors.New(...)): jalur gagal hanya mengisi err; hasil mempertahankan zero value 0.
  3. Baris 12 dan 15 (return tanpa nilai): dua naked return mengirim pasangan hasil dan err apa adanya — jalur gagal mengirim 0 dan galat, jalur sukses mengirim hasil bagi dan nil.
  4. Baris 18–25 (fungsi bungkus): fungsi yang di-defer menambah 100 pada hasil setelah return menyalin nilai angka * 2.
  5. Baris 27–35 (isi main): memanggil bagi dua kali — hasil 4 <nil> untuk pembagian sukses dan 0 pembagi tidak boleh nol untuk pembagi nol — lalu mencetak bungkus(5) yang menjadi 110 karena sentuhan defer.

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 #

Berkas Sumber

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

named-return.go

Unduh berkas
go
package 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))
}