İlk olarak, en son yapmak yana, hatta ulaşılamayan gibi, fonksiyonun ilk satırı olmalıdır kurtarmak için ertelenmiş işlevi kayıt ettikleri satır/kod defer
zaten panikler ve böylece önce ertelenmiş işlev, panik durumunu geri yükleyecektir.
Yani bu şekilde
do()
işlevini değiştirin:
func do() {
defer func() {
if err := recover(); err != nil {
fmt.Println("Restored:", err)
}
}()
str := "abc"
fmt.Print(str[3])
}
İkincisi: Eğer sadece bir kez main()
bitirir aday olacağını hangi ertelenmiş fonksiyonunda wg.Defer()
dediğimiz gibi bu tek başına, kodunuzu çalışmasını sağlamaz - çünkü asla hangi main()
numaranızda wg.Wait()
'u arayın. Yani wg.Wait()
, wg.Done()
çağrılarını bekler, ancak wg.Done()
çağrıları, wg.Wait()
geri döndürene kadar çalıştırılmaz. Bu bir kilitlenme. Sen ertelenmiş işlevinde, do()
işlevinden wg.Done()
çağırmalıdır
, böyle bir şey:
var wg sync.WaitGroup
func do() {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
wg.Done()
}()
str := "abc"
fmt.Print(str[3])
}
func main() {
for i := 0; i < 1; i++ {
wg.Add(1)
go do()
}
wg.Wait()
fmt.Println("This line should be printed after all those invocations fail.")
}
Çıkış (Go Playground üzerinde denemek):
Restored: runtime error: index out of range
This line should be printed after all those invocations fail.
Bu tabii gerekiyordu wg
değişkenini genel kapsamına taşıyın. Başka bir seçenek de argüman olarak do()
'a geçmek olabilir. Bu şekilde gitmeye karar verirseniz, bir işaretçiyi WaitGroup
'a iletmeniz gerektiğini unutmayın, yalnızca bir kopyanın geçirilmesi gerekir (WaitGroup
bir struct
türüdür) ve bir kopyanın kopyasını WaitGroup.Done()
çağırmak, orijinal üzerinde etkili olmayacaktır. WaitGroup
do()
geçmesiyle birlikte
:
func do(wg *sync.WaitGroup) {
defer func() {
if err := recover(); err != nil {
fmt.Println("Restored:", err)
}
wg.Done()
}()
str := "abc"
fmt.Print(str[3])
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 1; i++ {
wg.Add(1)
go do(&wg)
}
wg.Wait()
fmt.Println("This line should be printed after all those invocations fail.")
}
Çıktı aynıdır. Bu varyantı Go Playground numaralı telefondan deneyin.