Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Mengapakah `defer func() { fmt.Println(i) }()` mencetak "44444" dalam Go, manakala `defer func(n int) { fmt.Println(n) }(i)` mencetak "43210" dengan betul ?

Mengapakah `defer func() { fmt.Println(i) }()` mencetak "44444" dalam Go, manakala `defer func(n int) { fmt.Println(n) }(i)` mencetak "43210" dengan betul ?

DDD
DDDasal
2024-11-10 18:54:02421semak imbas

Why does `defer func() { fmt.Println(i) }()` print

Panggilan Fungsi Tertunda dan Tangkapan Penutupan

Dalam Go, pernyataan penangguhan membenarkan kami melaksanakan fungsi sejurus sebelum fungsi sekeliling kembali. Satu aspek penting penangguhan ialah cara ia mengendalikan penutupan.

Dalam coretan kod ini:

package main

import "fmt"

func main() {
    var whatever [5]struct{}

    for i := range whatever {
        fmt.Println(i)
    } // part 1

    for i := range whatever {
        defer func() { fmt.Println(i) }()  // part 2
    }

    for i := range whatever {
        defer func(n int) { fmt.Println(n) }(i)  // part 3
    }
}

Bahagian 1 hanya mencetak nilai i dari 0 hingga 4. Bahagian 2, bagaimanapun, menunjukkan tingkah laku yang menarik. Daripada mencetak nilai jangkaan 0 hingga 4, ia mengeluarkan "44444."

Ini kerana penutupan dalam bahagian 2 menangkap pembolehubah i. Apabila penutupan dilaksanakan kemudian, pembolehubah i mempunyai nilai yang dimilikinya dalam lelaran terakhir pernyataan julat, iaitu 4. Akibatnya, semua fungsi tertunda memanggil cetakan 4.

Sebaliknya, sebahagian 3 tidak menangkap sebarang pembolehubah luar. Menurut spesifikasi Go, "setiap kali pernyataan 'tunda' dilaksanakan, nilai fungsi dan parameter untuk panggilan dinilai seperti biasa dan disimpan semula tetapi fungsi sebenar tidak digunakan." Ini bermakna setiap panggilan fungsi tertunda mempunyai nilai parameter 'n' yang berbeza, iaitu nilai 'i' pada masa pernyataan 'tunda' dilaksanakan.

Oleh itu, bahagian 3 dengan betul mencetak "43210" kerana panggilan fungsi tertunda dilaksanakan dalam susunan LIFO (masuk terakhir, keluar dahulu) sebelum fungsi sekeliling kembali.

Adalah penting untuk diingat bahawa ungkapan fungsi dalam 'menunda f()' tidak dilaksanakan pada masa penyataan penangguhan dilaksanakan, manakala ungkapan dalam 'menunda f(e)' dinilai serta-merta.

Atas ialah kandungan terperinci Mengapakah `defer func() { fmt.Println(i) }()` mencetak "44444" dalam Go, manakala `defer func(n int) { fmt.Println(n) }(i)` mencetak "43210" dengan betul ?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn