Я придумал простой пример, который вставляет 10 миллионов записей в mongodb. Я начал работать, последовательно работая. Затем я посмотрел, как делать параллелизм, и нашел гортанов. Это похоже на то, что я хочу, но это не так, как я ожидал. Я реализовал WaitGroup, чтобы заблокировать запуск программы до того, как все goroutines были завершены, но у меня все еще есть проблема.Как работают гортины, и они умирают, когда заканчивается главный процесс?
Итак, я начну с того, что происходит, затем покажите код. Когда я запускаю код без goroutine, все 10 миллионов записей вставляются в mongodb в порядке. Однако, когда я добавляю горутин, вводится некоторая неопределенная сумма. Обычно около 8500 дают или берут пару сотен. Я проверил журнал mongodb, чтобы узнать, есть ли у него проблемы, и ничего не появляется. Поэтому я не уверен, что это возможно, просто не регистрируется. В любом случае, вот код:
(Боковое примечание: я делаю по 1 записи за раз, но я разделил ее на метод, чтобы я мог тестировать несколько записей за раз в будущем .. just haven «т придумали, как это сделать с MongoDB еще.)
package main
import (
"fmt"
"labix.org/v2/mgo"
"strconv"
"time"
"sync"
)
// structs
type Reading struct {
Id string
Name string
}
var waitGroup sync.WaitGroup
// methods
func main() {
// Setup timer
startTime := time.Now()
// Setup collection
collection := getCollection("test", "readings")
fmt.Println("collection complete: " + strconv.FormatFloat(time.Since(startTime).Seconds(), 'f', 2, 64))
// Setup readings
readings := prepareReadings()
fmt.Println("readings prepared: " + strconv.FormatFloat(time.Since(startTime).Seconds(), 'f', 2, 64))
// Insert readings
for i := 1; i <= 1000000; i++ {
waitGroup.Add(1)
go insertReadings(collection, readings)
// fmt.Print(".")
if i % 1000 == 0 {
fmt.Println("1000 readings queued for insert: " + strconv.FormatFloat(time.Since(startTime).Seconds(), 'f', 2, 64))
}
}
waitGroup.Wait()
fmt.Println("all readings inserted: " + strconv.FormatFloat(time.Since(startTime).Seconds(), 'f', 2, 64))
}
func getCollection(databaseName string, tableName string) *mgo.Collection {
session, err := mgo.Dial("localhost")
if err != nil {
// panic(err)
fmt.Println("error getCollection:", err)
}
// defer session.Close()
// Optional. Switch the session to a monotonic behavior.
// session.SetMode(mgo.Monotonic, true)
collection := session.DB(databaseName).C(tableName)
return collection
}
func insertReadings(collection *mgo.Collection, readings []Reading) {
err := collection.Insert(readings)
if err != nil {
// panic(err)
fmt.Println("error insertReadings:", err)
}
waitGroup.Done()
}
func prepareReadings() []Reading {
var readings []Reading
for i := 1; i <= 1; i++ {
readings = append(readings, Reading{Name: "Thing"})
}
return readings
}
Я вижу, что код, который вы опубликовали, имеет goroutines. Не могли бы вы также опубликовать код, который работает, чтобы мы могли точно видеть, что вы изменили? Или еще лучше, добавьте комментарии рядом с строками, которые вы изменили. Всегда полезно иметь рабочий пример и сравнивать его с нерабочим примером при отладке. Информация о том, что сработало для вас, важна для понимания этого. –