简体   繁体   English

如何让 goroutine 与匿名函数一起工作,在循环中返回值

[英]How to make goroutines work with anonymous functions returning value in a loop

I am working on a custom script to fetch data from RackSpace cloudfiles container and make a list of all the files in a given container (container has around 100 million files) and I have been working on parallelizing the code and currently stuck.我正在编写一个自定义脚本来从 RackSpace cloudfiles 容器中获取数据并列出给定容器中的所有文件(容器有大约 1 亿个文件),我一直致力于并行化代码,但目前卡住了。


// function to read data from channel and display
// currently just displaying, but there will be allot of processing done on this data
func extractObjectItemsFromList(objListChan <-chan []string) {
    fmt.Println("ExtractObjectItemsFromList")
    for _, c := range <-objListChan {
        fmt.Println(urlPrefix, c, "\t", count)
    }
}


func main()

// fetching data using flags
ao := gophercloud.AuthOptions{
    Username: *userName,
    APIKey:   *apiKey,
}

provider, err := rackspace.AuthenticatedClient(ao)
client, err := rackspace.NewObjectStorageV1(provider,gophercloud.EndpointOpts{
    Region: *region,
})
if err != nil {
    logFatal(err)
}

// We have the option of filtering objects by their attributes
opts := &objects.ListOpts{
    Full:   true,
    Prefix: *prefix,
}

var objectListChan = make(chan []string)
go extractObjectItemsFromList(objectListChan)

// Retrieve a pager (i.e. a paginated collection)
pager := objects.List(client, *containerName, opts)


// Not working
// By default EachPage contains 10000 records
// Define an anonymous function to be executed on each page's iteration
lerr := pager.EachPage(func(page pagination.Page) (bool, error) {       // Get a slice of objects.Object structs
    objectList, err := objects.ExtractNames(page)
    if err != nil {
        logFatal(err)
    }
    for _, o := range objectList {
        _ = o
    }
    objectListChan <- objectList
    return true, nil
})
if lerr != nil {
    logFatal(lerr)
}
//---------------------------------------------------
//       below code is working
//---------------------------------------------------

// working, but only works inside the loop, this keeps on fetching new pages and showing new records, 10000 per page
// By default EachPage contains 10000 records
// Define an anonymous function to be executed on each page's iteration
lerr := pager.EachPage(func(page pagination.Page) (bool, error) {       // Get a slice of objects.Object structs
    objectList, err := objects.ExtractNames(page)
    if err != nil {
        logFatal(err)
    }
    for _, o := range objectList {
        fmt.Println(o)
    }
    return true, nil
})
if lerr != nil {
    logFatal(lerr)
}

The first 10000 records are displayed but then it stuck and nothing happens.显示前 10000 条记录,但随后卡住了,什么也没有发生。 If I do not use channel and just run the plain loop it works perfectly fine, which kills the purpose of parallelizing.如果我不使用 channel 而只是运行普通循环,它就可以正常工作,这会破坏并行化的目的。

for _, c := range <-objListChan {
    fmt.Println(urlPrefix, c, "\t", count)
}

Your async worker pops one list from the channel, iterates it and exits.您的异步工作者从频道中弹出一个列表,对其进行迭代并退出。 You need to have two loops: one reading the channel ( range objListChan ), the other - reading the (just retrieved) object list.您需要有两个循环:一个读取通道( range objListChan ),另一个 - 读取(刚刚检索到的)对象列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM