gpt4 book ai didi

go - 为什么用goroutines for循环会导致数据丢失

转载 作者:行者123 更新时间:2023-12-01 22:07:49 26 4
gpt4 key购买 nike

好的,所以我有两个代码。首先是一个简单的for循环,效果很好

package main

import (
"context"
"encoding/json"
"fmt"
"log"
"os"

elasticsearch "github.com/elastic/go-elasticsearch/v7"
"github.com/elastic/go-elasticsearch/v7/esapi"
"github.com/mitchellh/mapstructure"
)

type Esindices struct {
Health string `json:"health"`
Status string `json:"status"`
Index string `json:"index"`
Uuid string `json:"uuid"`
Pri string `json:"pri"`
Rep string `json:"rep"`
DocsCount string `json:"docs.count"`
DocsDeleted string `json:"docs.deleted"`
StoreSize string `json:"store.size"`
PriStoreSize string `json:"pri.store.size"`
}

func main() {

var r []map[string]interface{}

es, err := elasticsearch.NewDefaultClient()
if err != nil {
log.Fatalf("Error creating client: %s", err)
}

req := esapi.CatIndicesRequest{
Format: "json",
Pretty: false,
}

res, err := req.Do(context.Background(), es)
if err != nil {
log.Fatalf("Error getting response: %s", err)
}

defer res.Body.Close()

if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
log.Printf("Error parsing the response body: %s", err)
}

indexSlice := make([]*Esindices, len(r))

for i, element := range r {
result := &Esindices{}
cfg := &mapstructure.DecoderConfig{
Metadata: nil,
Result: &result,
TagName: "json",
}
decoder, _ := mapstructure.NewDecoder(cfg)
decoder.Decode(element)
indexSlice[i] = result
}

thisisjson, err := json.MarshalIndent(indexSlice, "", " ")
if err != nil {
log.Fatal("Can't encode to JSON", err)
}


fmt.Fprintf(os.Stdout, "%s", thisisjson)

大部分内容都是不言自明的,但只是为了澄清一下,我使用的是Elasticsearch客户端和api.cat.indices API,以获取本地Elasticsearch安装中所有索引的列表,然后将它们存储为 map[string]interface{}和然后循环遍历以将其添加到结果结构的一部分。实际上,这很好,但是我要注意性能,尽管我不能提高请求本身的延迟,但是我当然可以提高循环的性能,至少我认为应该可以。

因此,当我尝试以下操作时,我得到的结果很奇怪。
var wg sync.WaitGroup
defer wg.Wait()
for i, element := range r {
wg.Add(1)
go func(i int, element map[string]interface{}) {
defer wg.Done()
result := Esindices{}
cfg := &mapstructure.DecoderConfig{
Metadata: nil,
Result: &result,
TagName: "json",
}
decoder, _ := mapstructure.NewDecoder(cfg)
decoder.Decode(element)
indexSlice[i] = result
}(i, element)
}

具体地说,问题是 slice 中元素的键的某些值是空的。这使我认为代码正在尝试将其添加到 slice 中,但是即使没有完成,它也会通过。

有什么想法吗?

最佳答案

代替defer wg.Wait,在for循环的末尾使用wg.Wait。在for循环完成之后,您正在使用for循环中goroutine构造的数据,并且在使用该数据之前,您不必等待所有goroutine都完成。

当您使用defer wg.Wait时,等待会在函数末尾发生。使用数据的for循环对不完整的数据进行操作,因为goroutine仍在运行。

在for循环的末尾使用wg.Wait时,您首先要等待所有goroutine结束,然后再使用它们生成的数据。

关于go - 为什么用goroutines for循环会导致数据丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60029661/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com