Перейти подпрограммы не выполняются

Ниже приведен код, который вызывает у меня проблему. Чего я хочу добиться, так это создавать эти параллельные таблицы. После того, как все таблицы созданы, я хочу выйти из функций.

func someFunction(){
    ....
    gos := 5
    proc := make(chan bool, gos)
    allDone := make(chan bool)

    for i:=0; i<gos; i++ {
        go func() {
            for j:=i; j<len(tables); j+=gos {
                r, err := db.Exec(tables[j])

                fmt.Println(r)

                if err != nil {
                    methods.CheckErr(err, err.Error())
                }
            }
            proc <- true
        }()
    }

    go func() {
        for i:=0; i<gos; i++{
            <-proc
        }
        allDone <- true
    }()

    for {
        select {
        case <-allDone:
            return
        }
    }   
}

Я создаю два канала 1, чтобы отслеживать количество созданных таблиц (proc) и другие (allDone), чтобы увидеть, все ли сделано.

Когда я запускаю этот код, тогда процедура go для создания таблицы начинает выполнение, но до ее завершения некоторая функция завершается.

Однако нет проблем, если запустить код последовательно

В чем заключается ошибка в моем шаблоне дизайна, а также как я могу ее исправить.

1 ответ

Решение

Обычный образец того, что вы пытаетесь достичь, использует WaitGroup,

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

Попробуйте передать итератор в качестве параметра в программу, чтобы вы каждый раз получали новую копию.

func someFunction(){
    ....
    gos := 5
    var wg sync.WaitGroup
    wg.Add(gos)

    for i:=0; i< gos; i++ {
        go func(n int) {
            defer wg.Done()
            for j:=n; j<len(tables); j+=gos {
                r, err := db.Exec(tables[j])

                fmt.Println(r)

                if err != nil {
                    methods.CheckErr(err, err.Error())
                }
            }
        }(i)
    }
    wg.Wait();     
}

Я не уверен, что вы пытаетесь достичь здесь, каждая процедура делает db.Exec на всех таблицах выше той, с которой он начинался, поэтому первая обрабатывает все таблицы, вторая - все, кроме первой и так далее. Это то, что вы хотели?

Другие вопросы по тегам