Function value memperkuat kode kita sepanjang section ini: disimpan, dikirim, dikembalikan, ditangkap closure. Namun setiap tipe di Go punya zero value, dan tipe fungsi tidak kecuali — nilainya adalah nil. Nilai fungsi nil muncul secara alami di struct field yang belum diisi, callback opsional, hingga pencarian key yang tidak ada pada map fungsi. Chapter penutup ini membahas perilaku nil pada fungsi: bentuknya, cara mengujinya, dan panik yang menanti pemanggil yang lupa memeriksa.

Zero Value Tipe Fungsi #

Variabel bertipe fungsi yang dideklarasikan tanpa nilai awal otomatis berisi nil, sama seperti pointer yang belum menunjuk apa pun:

go
var f func() int // zero value function adalah nil.
fmt.Println("f == nil:", f == nil)
fmt.Printf("Tipe f: %T\n", f)

Pengujian f == nil adalah satu-satunya perbandingan yang sah untuk nilai fungsi. Kompilator menolak pembandingan dua fungsi dengan pesan func can only be compared to nil — dua fungsi dengan isi identik pun tidak bisa dinyatakan sama. Verb format %T tetap menampilkan tipe func() int meskipun nilainya nil, karena tipe dan isi variabel adalah dua hal terpisah.

Memanggil nil: Program Panic #

Pemanggilan f() saat f bernilai nil tidak ditolak kompiler — galatnya muncul saat runtime. Berkas error-nil-func.go di bawah sengaja memanggil fungsi bernilai nil untuk membuktikannya:

go
package main

import "fmt"

func main() {
	var f func() int = nil
	fmt.Println("Memanggil fungsi bernilai nil...")
	f()
}

Output yang Dihasilkan:

text
Memanggil fungsi bernilai nil...
panic: runtime error: invalid memory address or nil pointer dereference

Runtime menghentikan program dengan panic nil pointer dereference karena tidak ada kode yang bisa dieksekusi. Setelah dua baris di atas, go run masih mencetak baris sinyal SIGSEGV, stack trace, dan exit status 2 — baris-baris itu memuat alamat memori dan path yang berbeda tiap komputer, sehingga tidak kita salin utuh. Ingat selalu frasa ini: program panic, program berhenti total.

Pola Pemeriksaan Sebelum Memanggil #

Pola penangkalnya sederhana: periksa f == nil sebelum memanggil, lalu beri jalur default. Fungsi jalankan berikut menerima callback opsional dan menggantinya dengan nilaiDefault saat callback tidak diisi:

go
// jalankan menjalankan f dengan aman: nilai nil diganti nilaiDefault.
func jalankan(f func() int) int {
	if f == nil {
		fmt.Println("f bernilai nil, memakai fungsi bawaan")
		return nilaiDefault()
	}
	return f()
}

Dua cabang itu menghasilkan pemanggilan yang selalu aman: jalankan(nil) menempuh jalur default, jalankan(tujuh) mengeksekusi callback aslinya. Pola yang sama bekerja untuk parameter opsional pada struct konfigurasi — si pengonsumsi boleh tidak mengisi field callback, dan pemanggilan selalu melewati pemeriksaan nil lebih dulu.

Program Utuh #

Berkas function-nil-demo.go menunjukkan zero value, verb %T, dan pola pemeriksaan dalam satu program. Jalankan dari direktori chapter:

bash
go run function-nil-demo.go

Output yang Dihasilkan:

text
f == nil: true
Tipe f: func() int
f bernilai nil, memakai fungsi bawaan
jalankan(nil) = 42
jalankan(tujuh) = 7

Mari kita telaah baris demi baris program di atas:

  1. Baris 16 (func jalankan(f func() int) int): menerima callback yang boleh berupa nil — kontrak opsional di tanda tangannya.
  2. Baris 17–20 (if f == nil { ... }): cabang pemeriksaan yang mengganti callback kosong dengan nilaiDefault() sebelum ada pemanggilan berisiko.
  3. Baris 21 (return f()): pemanggilan callback asli yang dijamin aman karena sudah lolos pemeriksaan.
  4. Baris 25 (var f func() int): deklarasi tanpa nilai — zero value tipe fungsi adalah nil, terbukti dari f == nil: true.
  5. Baris 27 (fmt.Printf("Tipe f: %T\n", f)): verb %T menampilkan tipe fungsi lengkap func() int meskipun isinya nil.

Kita kini menutup section Fungsi dengan perlengkapan lengkap: deklarasi, parameter, nilai kembalian berganda, variadic, fungsi sebagai nilai, closure, recursion, hingga pengaman nil. Struktur data Go siap menjadi tahap berikutnya — dimulai dari kumpulan nilai berurut pada section Array, Slice, dan Map .

Referensi #

Berkas Sumber

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

error-nil-func.go

Unduh berkas
go
package main

import "fmt"

func main() {
	var f func() int = nil
	fmt.Println("Memanggil fungsi bernilai nil...")
	f()
}

function-nil-demo.go

Unduh berkas
go
package main

import "fmt"

// nilaiDefault dipakai saat callback tidak diisi.
func nilaiDefault() int {
	return 42
}

// tujuh adalah contoh fungsi konkrit yang siap dipakai sebagai callback.
func tujuh() int {
	return 7
}

// jalankan menjalankan f dengan aman: nilai nil diganti nilaiDefault.
func jalankan(f func() int) int {
	if f == nil {
		fmt.Println("f bernilai nil, memakai fungsi bawaan")
		return nilaiDefault()
	}
	return f()
}

func main() {
	var f func() int // zero value function adalah nil.
	fmt.Println("f == nil:", f == nil)
	fmt.Printf("Tipe f: %T\n", f)

	fmt.Println("jalankan(nil) =", jalankan(nil))
	fmt.Println("jalankan(tujuh) =", jalankan(tujuh))
}