О поведении го рутина в го рутина - PullRequest
0 голосов
/ 08 октября 2019

Я новичок в golang и изучаю goroutine.
Я написал простой код, который специально делит число, используя goroutine.
Прежде всего, я даю базовое число и продолжаю делить его доон не делится
Но я изменяю go split(n) на split(n), он не работает следующим образом, и поэтому?

■ исходный код

package main

import (
    "flag"
    "fmt"
    "log"
    "net/http"
    "os"
    "strconv"
)

var next = make(chan int)
var quit = make(chan int)

func divide(n int) {
    defer func(){ quit <- 1 }()

    fmt.Println("[divide] n = " + strconv.Itoa(n))

    r := n % 2
    if r == 0 {
        next <- n / 2
    }
}

func execute() {

    fmt.Println("[execute] start")
    count := 0
    end   := false
    for !end {
        select {
        case n := <- next:
            count++
            fmt.Println("[execute] n = " + strconv.Itoa(n) + ", count = " + strconv.Itoa(count))
            go divide(n)
        case _ = <- quit:
            count--
            fmt.Println("[execute] end. count = " + strconv.Itoa(count))
            if count <= 0 {
                end = true
            }
        }
    }
    fmt.Println("complete")
    os.Exit(0)
}

func main() {

    base := flag.Int("n", 1, "Input the number")
    flag.Parse()

    if *base <= 0 {
        fmt.Println("please more than 1")
        os.Exit(0)
    }

    go execute()
    next <- *base

    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatal("ListenAndSearver:", err)
    }
}

■результат (работает нормально)

$ go run main.go -n 6
[execute] start
[execute] n = 6, count = 1
[divide] n = 6
[execute] n = 3, count = 2
[execute] end. count = 1
[divide] n = 3
[execute] end. count = 0
complete

■ результат (не работает)

$ go run main.go -n 6
[execute] start
[execute] n = 6, count = 1
[divide] n = 6

1 Ответ

1 голос
/ 08 октября 2019

Без go divide() внутри execute:

  • execute () читает из канала next, вызовы divide
  • split () ожидает записи в next
  • execute () по-прежнему ожидает возврата div (), поэтому программа теперь заблокирована.

с go divide() внутри execute:

  • execute () читает из канала next, запускает divide в новой процедуре, продолжает ждать
  • split () записывает в next
  • execute () читает из next,запускает другую процедуру и т. д.

Обратите внимание, что как только divide записывает в next, он продолжает записывать в quit, поэтому вы можете получить несколько сообщений о выходе до того, как все будет сделано.

...