Перейти Код ошибки языка программирования - PullRequest
0 голосов
/ 22 ноября 2011

Я пытаюсь написать простой код в GO, в котором две подпрограммы go (Send и Receive) отправляют друг другу целые числа.Я даю код ниже.Кто-нибудь может мне помочь, почему вывод этой программы [нет вывода].Есть ли какая-нибудь глупая ошибка (извините, я новичок в GO)?

package main

func Send (in1 <-chan int, out1 chan<- int) {

                i := 2 
        out1 <- i 
    print(i, "\n")
}

func Receive (in <-chan int, out chan<- int) {

        i := <-in 
        print(i, "\n")
        out <- i 
}


func main() {

       for i := 0; i < 10; i++ {
        ch1 := make(chan int)
        ch := make(chan int) 
            go Send (ch1 , ch)
        go Receive (ch , ch1)
        ch = ch1
        ch1 = ch
        }

}

Ответы [ 2 ]

2 голосов
/ 22 ноября 2011

Исправление Дэвида Грейсона работает, но объяснение, почему 9 не всегда принимается, не вписывается в комментарий!

Когда отправляющая программа отправляет значение в канал, оно блокируется до тех пор, пока принимающая программа не получит его. В этот момент он разблокирован. Планировщик go может вернуться из main почти сразу, прежде чем он даст принимающей программе возможность напечатать что-нибудь. Если вы установите для GOMAXPROCS значение больше 1, это случается реже, поскольку принимающая программа не будет блокироваться, пока активна основная программа.

Если вы хотите остановить возврат main, пока не завершены все процедуры, вы можете вернуть канал с Receive(), например:

package main

import "fmt"

func Send(ch chan<- int) {
    for i := 0; i < 10; i++ {
        fmt.Println(i, " sending")
        ch <- i
    }
    close(ch)
}

func Receive(ch <-chan int) (<-chan bool) {
    done := make(chan bool)
    go func() {
        for {
            i, ok := <-ch
            if !ok {
                break
            }
            fmt.Println(i, " received")
        }
        done <- true
    }()
    return done
}

func main() {
    ch := make(chan int)
    d := Receive(ch)
    Send(ch)
    _ = <-d
}

Что касается того, почему ваш вывод был пустым в исходном примере: вы делаете две процедуры, и, таким образом, main полностью разблокирована, поэтому она просто возвращается и программа завершается! Я тоже определенно допустил эту ошибку, но среда выполнения соединяется только с основной программой, а не со ВСЕМИ, как вы, возможно, ожидаете.

2 голосов
/ 22 ноября 2011

Как насчет этого:

package main

func Send (ch chan<- int) {
    for i := 0; i < 10; i++ {
      print(i, " sending\n")
      ch <- i
    }
}

func Receive (ch <-chan int) {
    for i := 0; i < 10; i++ {
        print(<-ch, " received\n")
    }
}

func main() {
   ch := make(chan int)
   go Receive(ch)
   Send(ch)
}

Вывод этого при запуске на golang.org:

0 sending
0 received
1 sending
2 sending
1 received
2 received
3 sending
4 sending
3 received
4 received
5 sending
6 sending
5 received
6 received
7 sending
8 sending
7 received
8 received
9 sending

Я не уверен, почему 9 не был получен. Должен быть какой-то способ усыпить основной поток, пока процедура получения не будет завершена. Кроме того, нелегко, что и получатель, и отправитель знают, что собираются отправить 10 номеров. Одна из программ должна быть отключена, когда другая закончит свою работу. Я не уверен, как это сделать.

EDIT1:

Вот реализация с двумя каналами, и подпрограммы go отправляют целые числа туда и обратно между собой. Один из них обозначен как ответчик, который отправляет только int после получения int. Ответчик просто добавляет два к полученному ему int, а затем отправляет его обратно.

package main

func Commander(commands chan int, responses chan int) {
    for i := 0; i < 10; i++ {
      print(i, " command\n")
      commands <- i
      print(<-responses, " response\n");
    }
    close(commands)
}

func Responder(commands chan int, responses chan int) {
    for {
        x, open := <-commands
        if !open {
            return;
        }
        responses <- x + 2
    }
}

func main() {
   commands := make(chan int)
   responses := make(chan int)
   go Commander(commands, responses)
   Responder(commands, responses)
}

Вывод, когда я запускаю его на golang.org:

0 command
2 response
1 command
3 response
2 command
4 response
3 command
5 response
4 command
6 response
5 command
7 response
6 command
8 response
7 command
9 response
8 command
10 response
9 command
11 response
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...