2013-11-21 2 views
1

http://play.golang.org/p/uRHG-Th_2PGolang: некоторые вопросы на канале

я с трудом понять концепцию канала

package main 

import (
    "fmt" 
) 

func Fibonacci(limit int, chnvar chan int) { 
    x, y := 0, 1 
    for i := 0; i < limit; i++ { 
    chnvar <- x 
    x, y = y, x+y 
    } 
    close(chnvar) 

    v, ok := <-chnvar 
    fmt.Println(v, ok) 
} 


func main() { 
    chn := make(chan int, 10) 
    go Fibonacci(cap(chn), chn) 
    for elem := range chn { 
    fmt.Printf("%v ", elem) 
    } 
} 
//1 1 2 3 5 8 13 21 34 

1) Как получить ложное значение от линии

v, ok := <-chnvar 

Он говорит false, если больше нет значений. , а также false, если канал закрыт. Но в этом случае канал закрыт, но (?) Все равно получает истинное значение.

И если я выйду за закрытие, это паника.

Как и почему он возвращается сюда?

2) Линия

go Fibonacci(cap(chn), chn) 

также работает без goroutine. В чем разница? Просто вопрос производительности.

Заранее спасибо

ответ

1
  1. Fibonacci Ваша функция наполнители 10 значений в канал (который имеет буфер 10 значений), а затем закрывает его. Предполагая, что инструкция v, ok <- chnvar выполняется до того, как главный горут все считывает из канала (очень вероятно, но не гарантируется), будет значение для чтения, поэтому значение ok будет истинным.

    Если вы удалите вызов close, цикл for в главном goroutine, в конечном счете, освободит буфер канала и блокирует ожидающие большего количества данных. Поскольку нет другого горутинга, который будет писать на канал, среда выполнения определяет это как тупик.

  2. Ваша программа-образец работает с Fibonacci, вызываемым напрямую (не как goroutine), потому что канал, который он пишет, буферизуется, и он никогда не переполняет буфер. Поэтому он может завершиться без блокировки и позволяет исполнению продолжить работу с остальной функцией main.

    Если канал не был буферизирован или вы написали больше значений, чем помещались в буфер, то Fibonacci блокировал бы ожидание какой-либо другой goroutine для чтения чего-либо из канала.

0

1)

В Go спецификации состояния для канала операций приема (курсив мой):

х, OK: = < -ch

Значение ок истинно, если полученное значение было доставлено успешной передачей на канал или false, если это нулевое значение, сгенерированное, потому что канал закрыт и пустой.

То есть, поскольку буферный канал не пуст, и вы успешно получили значение (0), будет истинно ok. Вы не получите false до тех пор, пока канал не будет опустошен.

2)

Запустив Fibonacci(cap(chn), chn) в его собственной рутиной Go, главный может начать прием и обработка (распечатка) из значения в то время как функция Фибоначчи будет продолжать подавать новые значения в канале.
В вашем случае это, вероятно, никогда не произойдет, так как функция заполнит буфер и завершит работу до того, как main получит шанс обработать что-либо.

Если он не будет работать в процедуре Go, Fibonacci сначала должен будет произвести все значения, прежде чем они смогут быть обработаны далее по основному.

Смежные вопросы