Go例程的Golang订单输出

时间:2017-06-10 16:15:29

标签: go

我有16个返回输出的例程,通常是结构。

struct output{
index int,
description string,
}

现在所有这16个例程并行运行,并且所有go例程的总预期输出结构预计为100万。我已经使用了go lang的基本排序,这样做是非常昂贵的,有些人可以帮助我根据索引对输出进行排序,我需要编写"描述"根据索引的顺序将字段放到文件上。

例如, 如果一个go例程给出输出为{2,"你好"},{9,"嘿"},{4," Hola"},我的输出文件应该包含 你好 你好 哎

所有这些go例程并行运行,我无法控制执行顺序,因此我将索引传递给最终命令输出。

2 个答案:

答案 0 :(得分:2)

在得到答案之前要考虑的一件事是你的示例代码无法编译。要在Go中定义结构类型,您需要将语法更改为

type output struct {
    index       int
    description string
}

就问题的潜在解决方案而言 - 如果您已经可靠地拥有唯一索引以及结果集的预期计数 - 您根本不需要进行任何排序。而是通过通道同步go例程,并将输出插入相应索引的已分配切片中。然后,您可以遍历该切片以将内容写入文件。例如:

ch := make(chan output) //each go routine will write to this channel
wg := new(sync.WaitGroup) //wait group to sync all go routines

//execute 16 goroutines 
for i := 0; i < 16; i++ {
    wg.Add(1)
    go worker(ch, wg) //this is expecting each worker func to call wg.Done() when completing its portion of work
}

//create a "quit" channel that will be used to signal to the select statement below that your go routines are all done
quit := make(chan bool)
go func() {
    wg.Wait()
    quit <- true
}()

//initialize a slice with length and capacity to 1mil, the expected result size mentioned in your question
sorted := make([]string, 1000000, 1000000)

//use the for loop, select pattern to sync the results from your 16 go routines and insert them into the sorted slice
for {
    select {
        case output := <-ch:
            //this is not robust - check notes below example
            sorted[output.index] = output.description
        case <-quit:
            //implement a function you could pass the sorted slice to that will write the results
            // Ex:  writeToFile(sorted)
            return
    }
}

关于此解决方案的几点说明:它取决于您知道预期结果集的大小。如果您不知道结果集的大小是什么 - 在select语句中,您需要检查从ch读取的索引是否超过sorted切片的长度并在之前分配额外的空间插入我们的程序将因出界错误而崩溃

答案 1 :(得分:0)

您可以使用 Ordered-concurrently 模块合并您的输入,然后按顺序打印它们。

https://github.com/tejzpr/ordered-concurrently

示例 - https://play.golang.org/p/hkcIuRHj63h

package main

import (
    concurrently "github.com/tejzpr/ordered-concurrently/v2"
    "log"
    "math/rand"
    "time"
)

type loadWorker int

// The work that needs to be performed
// The input type should implement the WorkFunction interface
func (w loadWorker) Run() interface{} {
    time.Sleep(time.Millisecond * time.Duration(rand.Intn(10)))
    return w
}

func main() {
    max := 10
    inputChan := make(chan concurrently.WorkFunction)
    output := concurrently.Process(inputChan, &concurrently.Options{PoolSize: 10, OutChannelBuffer: 10})
    go func() {
        for work := 0; work < max; work++ {
            inputChan <- loadWorker(work)
        }
        close(inputChan)
    }()
    for out := range output {
        log.Println(out.Value)
    }
}

免责声明:我是模块创建者