2016-01-20 16 views
8

Go, neden kapalı bir kanala yazı yazıyor?Go, neden kapalı bir kanala yazı yazarken panik yapıyor?

bir kanaldan okuma value, ok := <-channel deyim kullanabilir ve böylece Tamam sonuç kapalı bir kanal isabet test edilebilir iken:

// reading from closed channel 

package main 

import "fmt" 

func main() { 
    ch := make(chan int, 1) 
    ch <- 2 
    close(ch) 

    read(ch) 
    read(ch) 
    read(ch) 
} 

func read(ch <-chan int) { 
    i,ok := <- ch 
    if !ok { 
     fmt.Printf("channel is closed\n") 
     return 
    } 
    fmt.Printf("read %d from channel\n", i) 
} 

Çıktı:

read 2 from channel 
channel is closed 
channel is closed 

Çalıştır "okuma kapalı kanal "on Playground

Muhtemelen kapalı bir kanala yazılması daha düzensizdir, çünkü wri denerseniz, Go panik yapar te kanal kapatıldığında:

//writing to closed channel 

package main 

import (
    "fmt" 
) 

func main() { 
    output := make(chan int, 1) // create channel 
    write(output, 2) 
    close(output) // close channel 
    write(output, 3) 
    write(output, 4) 
} 

// how to write on possibly closed channel 
func write(out chan int, i int) (err error) { 

    defer func() { 
     // recover from panic caused by writing to a closed channel 
     if r := recover(); r != nil { 
      err = fmt.Errorf("%v", r) 
      fmt.Printf("write: error writing %d on channel: %v\n", i, err) 
      return 
     } 

     fmt.Printf("write: wrote %d on channel\n", i) 
    }() 

    out <- i // write on possibly closed channel 

    return err 
} 

Çıktı:

"kapalı kanala yazma"
write: wrote 2 on channel 
write: error writing 3 on channel: send on closed channel 
write: error writing 4 on channel: send on closed channel 

olarak çalıştır bildiğim kadarıyla

Playground üzerine, yazma için daha basit bir deyim yoktur panik yapmadan muhtemelen kapalı bir kanal içine. Neden olmasın? Okuma ve yazma arasındaki bu tür asimetrik davranışların ardındaki sebep nedir? Go Language Spec itibaren

+3

nasıl bilebiliriz ki? Google golang grubuna sor, belki yazarlardan biri sana cevap verecek. Tek bir sebep düşünebilirim. Üretici tarafında bir kanalı kapatmak için iyi bir tasarım. Panik yapmak, uygulamanızı böyle bir şekilde tasarlamanızı zorlaştırır. – creker

+5

Bir kanalı kapatmak, burada daha fazla değer olmayacak bir işarettir. Kapalı bir kanala yazmak, panik yapan bir program hatasıdır. – JimB

cevap

11

: Bir kanal için c

, yerleşik fonksiyon yakın (c) artık değerleri kanalda gönderilecektir kaydeder. C, bir yalnızca alma kanalı ise bir hatadır. Kapalı bir kanala göndermek veya kapamak, çalışma zamanı paniğe neden olur. Nil kanalını kapatmak aynı zamanda çalışma zamanı paniğine neden olur. Yakından arama yaptıktan sonra ve daha önce gönderilen tüm değerler alındıktan sonra, alma işlemleri kanalın tipi için sıfır değerini, engellemeden döndürür. Çok değerli alım işlemi , kanalının kapalı olup olmadığının bir göstergesiyle birlikte alınan bir değeri döndürür.

Kapalı bir kanala yazdıysanız, programınız panik olacaktır. Bunu gerçekten yapmak istiyorsanız, catch this error with recover potansiyelini kullanabilirsiniz, ancak yazdığınız kanalın açık olup olmadığını bilmediğiniz bir durumda olmak genellikle programda bir hatanın işaretidir.

Bazı tırnak:

bir kanalın "yakın" gerçekten kanalda özel değerin sadece bir gönderme yapıyor: İşte

bir motivasyondur. Daha fazla değerin gönderilmeyeceğine söz veren özel bir değerdir. Bir kanalda kapandıktan sonra bir değer göndermeye çalışmak, panik yapacaktır, çünkü gerçekte gönderen değer, garantisinin kapanmasını sağlayacaktır. Kapanış sadece özel bir tür gönderdiğinden, kanal kapatıldıktan sonra da izin verilmez.İşte

başka bir şeydir:

kanal yakın tek kullanım gelmek artık değerler olduğunu okuyucuya sinyal etmektir. Bu sadece tek değer kaynağı olduğunda veya birden fazla kaynak koordine olduğunda anlamlıdır. , çoklu goroutinlerin iletişim kurmadan bir kanalı kapattığı makul bir program değildir. Bu, çoklu goroutinler 'un, gönderilecek daha fazla değer olmadığını bileceğini ima eder - nasıl iletişim kurmuyorlarsa nasıl belirleyebilirler? bir kaynak olarak bir kanal serbest bırakır onu Kapanış

: -

(Ian Lance Taylor)

İşte

başka bir şeydir. Bir kanalı tanımlayıcısını bir çok kez kapatmak veya bir defaya mahsus bellek bir bloğunu birden çok kez kapatmak için bir kanalı daha fazla anlamlandırmaz. Bu tür eylemler kodun kırıldığını gösterir, bu nedenle kapalı bir kanalı kapatan bir paniği tetikler.

(Rob Pike)

-

Kaynak: Go design detail rationale question - channel close