猿问

从文件中解析数据时大小不同的地图的地图

我正在为 Nagios 构建一个 API 。我开始重新创建读取 status.dat 文件并将数据存储在多个对象中的代码,然后使用这些对象创建在 core.py 文件中找到的主机、服务、信息字典。

下面是我的 Go 版本的 python 代码,它似乎按预期工作。它仍处于早期阶段,因此我对任何编码不当做法表示歉意。


翻阅古今
浏览 141回答 3
3回答

万千封印

var mu = &sync.RWMutex{}func openStatusFile() *os.File {&nbsp; &nbsp; file, err := os.Open("/usr/local/nagios/var/status.dat")&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; }&nbsp; &nbsp; return file}func nextStanza() <-chan map[string]string {&nbsp; &nbsp; myChannel := make(chan map[string]string)&nbsp; &nbsp; scanner := bufio.NewScanner(openStatusFile())&nbsp; &nbsp; current := make(map[string]string)&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; for scanner.Scan() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mainline := scanner.Text()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; line := strings.TrimSpace(mainline)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if strings.HasSuffix(line, "{") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if len(current) != 0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; myChannel <- current&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result := strings.SplitN(line, " ", 2)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mu.Lock()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; current["type"] = result[0]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mu.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if strings.Contains(line, "=") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result := strings.SplitN(line, "=", 2)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key := result[0]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val := result[1]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mu.Lock()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; current[key] = val&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mu.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; close(myChannel)&nbsp; &nbsp; }()&nbsp; &nbsp; return myChannel}在主函数中,我创建了嵌套映射以暂时仅保存主机数据,并且完成后没有任何抱怨。我遇到的问题是,当我检查此映射的长度时,我期望看到 104 个主机,但每次运行此测试文件时都会得到不同的结果。func main() {&nbsp; &nbsp; hoststatus := nextStanza()&nbsp; &nbsp; hosts := make(map[string]map[string]string)&nbsp; &nbsp; // services := make(map[string]map[string]map[string]string)&nbsp; &nbsp; var host string&nbsp; &nbsp; // var service string&nbsp; &nbsp; for obj := range hoststatus {&nbsp; &nbsp; &nbsp; &nbsp; var hostPlaceHolder string&nbsp; &nbsp; &nbsp; &nbsp; var typePlaceHolder string&nbsp; &nbsp; &nbsp; &nbsp; mu.Lock()&nbsp; &nbsp; &nbsp; &nbsp; hostPlaceHolder = obj["host_name"]&nbsp; &nbsp; &nbsp; &nbsp; mu.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; if hostPlaceHolder != "" {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; host = hostPlaceHolder&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; mu.Lock()&nbsp; &nbsp; &nbsp; &nbsp; typePlaceHolder = obj["type"]&nbsp; &nbsp; &nbsp; &nbsp; mu.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; if typePlaceHolder == "hoststatus" {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mu.Lock()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hosts[host] = obj&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mu.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println(len(hosts))}第一次运行:$ go run -race mytest.go93第二次运行:$ go run -race mytest.go95第三次运行:$ go run -race mytest.go63你明白了。我觉得问题与地图有关,因为如果我只是打印主机而不将它们放入地图中,我会看到我期望的所有主机。每次运行时地图尺寸不同的原因是什么?

慕无忌1623718

我能够通过在将地图current发送到频道后清空地图来解决我的问题。myChannel <- currentcurrent = make(map[string]string)然后在循环main()后的函数中for obj := range hoststatus,我将这些数据放入一个单独的映射中,然后进行处理。hostStatusMap := make(map[string]string)&nbsp; &nbsp; for k, v := range obj {&nbsp; &nbsp; &nbsp; &nbsp; hostStatusMap[k] = v&nbsp; &nbsp; }我还能够删除分散在代码中的锁,现在它在每次运行时返回正确的主机长度。

holdtom

您的代码具有以下竞争条件func nextStanza() <-chan map[string]string {&nbsp; &nbsp; myChannel := make(chan map[string]string)&nbsp; &nbsp; scanner := bufio.NewScanner(openStatusFile())&nbsp; &nbsp; current := make(map[string]string)&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; for scanner.Scan() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mainline := scanner.Text()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; line := strings.TrimSpace(mainline)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if strings.HasSuffix(line, "{") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if len(current) != 0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; myChannel <- current&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result := strings.SplitN(line, " ", 2)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mu.Lock()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; current["type"] = result[0]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mu.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if strings.Contains(line, "=") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result := strings.SplitN(line, "=", 2)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key := result[0]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; val := result[1]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mu.Lock()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; current[key] = val&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mu.Unlock()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; close(myChannel)&nbsp; &nbsp; }()&nbsp; &nbsp; return myChannel}当您在匿名函数上启动 goroutine 时,您并没有为其创建 WaitGroup。这意味着该函数nextStanza()将启动 goroutine,而return无需等待匿名 goroutine 终止——从而在父函数关闭时结束 goroutine。我建议使用等待组,这样可以保证匿名函数终止。一个简单的例子说明了正在发生的事情:具有竞争条件import (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "time"&nbsp; &nbsp; // "sync"&nbsp; &nbsp; )func main() {&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(3 * time.Second)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("hai")&nbsp; &nbsp; }()&nbsp; &nbsp; return}没有竞争条件import (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "time"&nbsp; &nbsp; "sync"&nbsp; &nbsp; )func main() {&nbsp; &nbsp; var wg sync.WaitGroup&nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; time.Sleep(3 * time.Second)&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("hai")&nbsp; &nbsp; &nbsp; &nbsp; wg.Done()&nbsp; &nbsp; }()&nbsp; &nbsp; wg.Wait()&nbsp; &nbsp; return}
随时随地看视频慕课网APP

相关分类

Go
我要回答