Artikel ini diperkenalkan kepada anda oleh ruangan tutorial go language Temanya adalah mengenai pembelajaran dan penggunaan go defer. Saya harap ia dapat membantu rakan yang memerlukan.
Apakah itu penangguhan?
Dalam Go, panggilan fungsi boleh mengikut kata kunci defer
untuk membentuk panggilan fungsi tertunda.
Apabila panggilan fungsi ditangguhkan, ia tidak akan dilaksanakan serta-merta. Ia akan ditolak ke dalam timbunan panggilan tertunda yang diselenggara oleh coroutine semasa. Apabila panggilan fungsi (yang mungkin atau mungkin bukan panggilan tertunda) kembali dan memasuki fasa keluarnya, semua panggilan tertunda yang telah ditolak dalam panggilan fungsi ini akan dilaksanakan dalam susunan terbalik urutan ia ditolak ke dalam timbunan. . Apabila semua panggilan tertunda ini dilaksanakan, panggilan fungsi sebenarnya akan keluar.
Contoh mudah:
package mainimport "fmt"func sum(a, b int) { defer fmt.Println("sum函数即将返回") defer fmt.Println("sum函数finished") fmt.Printf("参数a=%v,参数b=%v,两数之和为%v\n", a, b, a+b)}func main() { sum(1, 2)}
output:
参数a=1,参数b=2,两数之和为3 sum函数finished sum函数即将返回
Malah, setiap coroutine mengekalkan dua tindanan panggilan.
tunda penilaian parameter fungsi
package mainimport "fmt"func Print(a int) {fmt.Println("defer函数中a的值=", a)}func main() {a := 10defer Print(a)a = 1000fmt.Println("a的值=", a)}
output:
a的值= 1000 defer函数中a的值= 10
tunda Cetakan(a) Apabila ia ditambahkan pada timbunan panggilan tertunda, nilai a ialah 5 , jadi Hasil keluaran untuk menangguhkan Cetakan(a) ialah 5
Contoh 2:
package mainimport "fmt"func main() { func() { for i := 0; i < 3; i++ { defer fmt.Println("a=", i) } }() fmt.Println() func() { for i := 0; i < 3; i++ { defer func() { fmt.Println("b=", i) }() } }()}
output:
a= 2 a= 1 a= 0 b= 3 b= 3 b= 3
i dalam gelung fungsi tanpa nama pertama adalah dalam fmt. Println Nilai yang dianggarkan apabila panggilan fungsi ditolak ke dalam timbunan panggilan tertunda, jadi hasil output ialah 2, 1, 0. i dalam fungsi tanpa nama kedua ialah nilai yang dianggarkan semasa fasa keluar panggilan fungsi tanpa nama (i telah menjadi 3 pada masa ini ), jadi output hasil ialah: 3, 3, 3.
Malah, dengan mengubah sedikit panggilan fungsi tanpa nama kedua, anda boleh menjadikannya menghasilkan hasil yang sama seperti fungsi tanpa nama satu:
package mainimport "fmt"func main() { func() { for i := 0; i < 3; i++ { defer fmt.Println("a=", i) } }() fmt.Println() func() { for i := 0; i < 3; i++ { defer func(i int) { fmt.Println("b=", i) }(i) } }()}
output:
a= 2 a= 1 a= 0 b= 2 b= 1 b= 0
Panik dan tangguh pulih
Go tidak menyokong pengecualian membaling dan menangkap, tetapi disyorkan untuk menggunakan nilai pulangan untuk mengembalikan ralat secara eksplisit. Walau bagaimanapun, Go menyokong mekanisme yang serupa dengan pengecualian membaling/menangkap. Mekanisme ini dipanggil mekanisme panik/pulih.
Kita boleh memanggil fungsi terbina dalam panic
untuk menjana panik untuk meletakkan coroutine semasa ke dalam keadaan panik.
Memasuki keadaan panik ialah cara lain untuk panggilan fungsi semasa mula kembali. Sebaik sahaja panggilan fungsi menjana panik, panggilan fungsi akan serta-merta memasuki fasa keluarnya, dan panggilan tertunda yang ditolak ke tindanan dalam panggilan fungsi akan dilaksanakan dalam susunan terbalik urutan ia ditolak.
Dengan memanggil fungsi terbina dalam recover
dalam panggilan fungsi tertunda, panik dalam coroutine semasa boleh dihapuskan, membolehkan coroutine semasa memasuki semula keadaan biasa.
Sebelum coroutine yang panik keluar, panik tidak akan merebak ke coroutine lain. Jika coroutine keluar dalam keadaan panik, ia akan ranap keseluruhan program. Lihat dua contoh berikut:
package mainimport ( "fmt" "time")func p(a, b int) int { return a / b}func main() { go func() { fmt.Println(p(1, 0)) }() time.Sleep(time.Second) fmt.Println("程序正常退出~~~")}
output:
panic: runtime error: integer pide by zero goroutine 6 [running]: main.p(...) /Users/didi/Desktop/golang/defer.go:9 main.main.func1() /Users/didi/Desktop/golang/defer.go:14 +0x12 created by main.main /Users/didi/Desktop/golang/defer.go:13 +0x39exit status 2
Fungsi p panik (pembahagi ialah 0), kerana coroutine tidak mempunyai mekanisme pemulihan panik, menyebabkan keseluruhan program untuk ranap.
Jika coroutine di mana fungsi p terletak menambah pemulihan panik (tunda pulih), program boleh keluar seperti biasa.
package mainimport ( "fmt" "time")func p(a, b int) int { return a / b}func main() { go func() { defer func() { v := recover() if v != nil { fmt.Println("恐慌被恢复了:", v) } }() fmt.Println(p(1, 0)) }() time.Sleep(time.Second) fmt.Println("程序正常退出~~~")}
output:
恐慌被恢复了: runtime error: integer pide by zero 程序正常退出~~~
Untuk lebih banyak ilmu berkaitan golang, sila layari golanglajur tutorial
Atas ialah kandungan terperinci Apakah penangguhan dalam Go? Bagaimana cara menggunakannya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!