RISEBY
我想出了这种方法,它适用于我的需要:package mainimport ( "errors" "fmt" "strings" "sync" "time")type ProgressTracker struct { Progress int Error error Completed bool Url string}/**This method sleeps for 1 second and sends progress (in %) in each iteration to Progress channelFor .net sites on 3rd iteration fail with errorWhen everything is completed, send a message to Complete channel*/func work(url string, tracker chan ProgressTracker) { var internalTracker = ProgressTracker{ Url: url, } tracker <- internalTracker fmt.Printf("processing url %s\n", url) for i := 1; i <= 5; i++ { if url == "google.com" { time.Sleep(time.Second * 3) } time.Sleep(time.Second) if i == 3 && strings.HasSuffix(url, ".net") { internalTracker.Error = errors.New("error for .net sites") internalTracker.Completed = true tracker <- internalTracker return } progress := 20 * i internalTracker.Progress = progress internalTracker.Completed = false tracker <- internalTracker } internalTracker.Completed = true tracker <- internalTracker}func main() { var urls = []string{"google.com", "youtube.com", "someurl.net"} var tracker = make(chan ProgressTracker, len(urls)) var wg sync.WaitGroup wg.Add(len(urls)) for _, url := range urls { go func(workUrl string) { defer wg.Done() work(workUrl, tracker) }(url) } go func() { wg.Wait() close(tracker) fmt.Printf("After wg wait") }() var completed = 0 for completed < len(urls) { select { case t := <-tracker: if t.Completed { fmt.Printf("Processing for %s is completed!\n", t.Url) completed = completed + 1 } else { fmt.Printf("Processing for %s is in progress: %d\n", t.Url, t.Progress) } if t.Error != nil { fmt.Printf("Url %s has errors %s\n", t.Url, t.Error) } } }}在这里,我ProgressTracker作为通道传递(中的字段ProgressTracker被声明为简单字段,而不是通道)并且在来自工作函数的每个事件上返回正在发生的事情的完整状态(如果进度增加 - 设置新值并将结构返回通道,如果发生错误 - 设置错误并返回结构等)。