Pelajaran modul (4/5)
Penutupan dan berfungsi sebagai nilai
Di Go, fungsi adalah nilai kelas satu: fungsi dapat ditetapkan ke dalamnya variabel, diteruskan ke fungsi lain, dan dikembalikan. Penutupan adalah a fungsi literal (anonim) yang menangkap variabel dari lingkungan di mana ia didefinisikan.
Fungsi literal
Sebuah fungsi tanpa nama, ditulis sebaris. Anda segera meneleponnya atau menugaskannya:
greet := func(name string) {
fmt.Println("ciao", name)
}
greet("Anna")
// invocata immediatamente:
func() { fmt.Println("subito") }()Jenis greet adalah func(string).
Menangkap lingkungan: penutupan
Fungsi literal dapat membaca dan memodifikasi variabel yang terlihat di dalamnya cakupan leksikalnya, bahkan setelah fungsi luarnya kembali:
func counter() func() int {
n := 0
return func() int {
n++
return n
}
}
c := counter()
fmt.Println(c(), c(), c()) // 1 2 3n "hidup" selama setidaknya satu penutupan merujuknya. Setiap panggilan ke
counter() membuat n baru dan mandiri.
Penutupan sebagai panggilan balik
Pola yang sangat umum:
nums := []int{3, 1, 2}
sort.Slice(nums, func(i, j int) bool {
return nums[i] < nums[j]
})Penutupan menangkap nums dan menentukan pemesanan.
Berfungsi sebagai parameter
Untuk menerima suatu fungsi sebagai parameter, tuliskan tipenya:
func apply(nums []int, f func(int) int) []int {
out := make([]int, len(nums))
for i, n := range nums {
out[i] = f(n)
}
return out
}
double := func(x int) int { return x * 2 }
apply([]int{1, 2, 3}, double) // [2 4 6]Jika tanda tangan sulit dibaca, tentukan tipe alias:
type Transform func(int) int
func apply(nums []int, f Transform) []int { ... }Cobalah
Definisikan counter() yang mengembalikan penutupan: setiap panggilan ke penutupan menambah dan mengembalikan penghitung internal.
Tunjukkan petunjuk
`n` harus dideklarasikan SEBELUM pengembalian; penutupan menangkapnya.
Solusi tersedia setelah 3 upaya
Tetapkan ke f fungsi literal yang mencetak 'ciao', lalu panggil.
Tunjukkan petunjuk
Sintaks: `f := func() { ... }` lalu `f()`.
Solusi tersedia setelah 3 upaya
Apa yang dicetak ini? (hati-hati terhadap cakupan penutupan)
mk := func() func() int {
x := 0
return func() int { x++; return x }
}
a := mk()
b := mk()
fmt.Println(a(), a(), b())Rekap
- Fungsinya kelas satu: dapat dialihkan, dapat dilewati, dapat dikembalikan.
- Fungsi literal:
func(params) ret { ... }, anonim. - Penutupan: menangkap variabel lingkup leksikal, membuatnya tetap hidup.
- Tipe fungsi eksplisit dalam parameter:
func(int) int. - Sejak Go 1.22, setiap iterasi for memiliki salinan variabel loopnya sendiri.