Rumah > pembangunan bahagian belakang > Golang > Apakah penangguhan dalam Go? Bagaimana cara menggunakannya?

Apakah penangguhan dalam Go? Bagaimana cara menggunakannya?

藏色散人
Lepaskan: 2021-09-01 15:52:43
ke hadapan
2578 orang telah melayarinya

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)}
Salin selepas log masuk

output:

参数a=1,参数b=2,两数之和为3
sum函数finished
sum函数即将返回
Salin selepas log masuk

Malah, setiap coroutine mengekalkan dua tindanan panggilan.

  • Satu ialah timbunan panggilan fungsi biasa. Dalam timbunan ini, dua panggilan bersebelahan mempunyai hubungan panggilan. Panggilan yang dibuat pada tindanan lewat dipanggil oleh panggilan yang diletakkan pada tindanan awal. Panggilan terawal yang ditolak dalam timbunan ini ialah panggilan permulaan coroutine yang sepadan.
  • Timbunan lain ialah timbunan panggilan tertunda yang dinyatakan di atas. Tiada hubungan panggilan antara mana-mana dua panggilan dalam timbunan panggilan tertunda.

tunda penilaian parameter fungsi

  • Untuk panggilan fungsi tertunda, parameter sebenar adalah yang dipanggil pada kali ini Dinilai apabila ditolak ke dalam timbunan panggilan tertunda.
  • Ungkapan dalam badan fungsi tanpa nama akan dinilai satu demi satu apabila fungsi itu dilaksanakan, tidak kira sama ada fungsi dipanggil secara normal atau tertunda.
    Contoh 1:
package mainimport  "fmt"func  Print(a int) {fmt.Println("defer函数中a的值=", a)}func  main() {a := 10defer  Print(a)a = 1000fmt.Println("a的值=", a)}
Salin selepas log masuk

output:

a的值= 1000
defer函数中a的值= 10
Salin selepas log masuk

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)
            }()
        }
    }()}
Salin selepas log masuk

output:

a= 2
a= 1
a= 0

b= 3
b= 3
b= 3
Salin selepas log masuk

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)
        }
    }()}
Salin selepas log masuk

output:

a= 2
a= 1
a= 0

b= 2
b= 1
b= 0
Salin selepas log masuk

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("程序正常退出~~~")}
Salin selepas log masuk

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
Salin selepas log masuk

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("程序正常退出~~~")}
Salin selepas log masuk

output:

恐慌被恢复了: runtime error: integer pide by zero
程序正常退出~~~
Salin selepas log masuk

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!

Label berkaitan:
sumber:learnku.com
Kenyataan Laman Web ini
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
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan