3 回答

TA貢獻1891條經驗 獲得超3個贊
var mu = &sync.RWMutex{}
func openStatusFile() *os.File {
file, err := os.Open("/usr/local/nagios/var/status.dat")
if err != nil {
}
return file
}
func nextStanza() <-chan map[string]string {
myChannel := make(chan map[string]string)
scanner := bufio.NewScanner(openStatusFile())
current := make(map[string]string)
go func() {
for scanner.Scan() {
mainline := scanner.Text()
line := strings.TrimSpace(mainline)
if strings.HasSuffix(line, "{") {
if len(current) != 0 {
myChannel <- current
}
result := strings.SplitN(line, " ", 2)
mu.Lock()
current["type"] = result[0]
mu.Unlock()
} else if strings.Contains(line, "=") {
result := strings.SplitN(line, "=", 2)
key := result[0]
val := result[1]
mu.Lock()
current[key] = val
mu.Unlock()
}
}
close(myChannel)
}()
return myChannel
}
在主函數(shù)中,我創(chuàng)建了嵌套映射以暫時僅保存主機數(shù)據(jù),并且完成后沒有任何抱怨。我遇到的問題是,當我檢查此映射的長度時,我期望看到 104 個主機,但每次運行此測試文件時都會得到不同的結果。
func main() {
hoststatus := nextStanza()
hosts := make(map[string]map[string]string)
// services := make(map[string]map[string]map[string]string)
var host string
// var service string
for obj := range hoststatus {
var hostPlaceHolder string
var typePlaceHolder string
mu.Lock()
hostPlaceHolder = obj["host_name"]
mu.Unlock()
if hostPlaceHolder != "" {
host = hostPlaceHolder
}
mu.Lock()
typePlaceHolder = obj["type"]
mu.Unlock()
if typePlaceHolder == "hoststatus" {
mu.Lock()
hosts[host] = obj
mu.Unlock()
}
}
fmt.Println(len(hosts))
}
第一次運行:
$ go run -race mytest.go
93
第二次運行:
$ go run -race mytest.go
95
第三次運行:
$ go run -race mytest.go
63
你明白了。
我覺得問題與地圖有關,因為如果我只是打印主機而不將它們放入地圖中,我會看到我期望的所有主機。每次運行時地圖尺寸不同的原因是什么?

TA貢獻1744條經驗 獲得超4個贊
我能夠通過在將地圖current發(fā)送到頻道后清空地圖來解決我的問題。
myChannel <- current
current = make(map[string]string)
然后在循環(huán)main()后的函數(shù)中for obj := range hoststatus,我將這些數(shù)據(jù)放入一個單獨的映射中,然后進行處理。
hostStatusMap := make(map[string]string)
for k, v := range obj {
hostStatusMap[k] = v
}
我還能夠刪除分散在代碼中的鎖,現(xiàn)在它在每次運行時返回正確的主機長度。

TA貢獻1805條經驗 獲得超10個贊
您的代碼具有以下競爭條件
func nextStanza() <-chan map[string]string {
myChannel := make(chan map[string]string)
scanner := bufio.NewScanner(openStatusFile())
current := make(map[string]string)
go func() {
for scanner.Scan() {
mainline := scanner.Text()
line := strings.TrimSpace(mainline)
if strings.HasSuffix(line, "{") {
if len(current) != 0 {
myChannel <- current
}
result := strings.SplitN(line, " ", 2)
mu.Lock()
current["type"] = result[0]
mu.Unlock()
} else if strings.Contains(line, "=") {
result := strings.SplitN(line, "=", 2)
key := result[0]
val := result[1]
mu.Lock()
current[key] = val
mu.Unlock()
}
}
close(myChannel)
}()
return myChannel
}
當您在匿名函數(shù)上啟動 goroutine 時,您并沒有為其創(chuàng)建 WaitGroup。這意味著該函數(shù)nextStanza()將啟動 goroutine,而return無需等待匿名 goroutine 終止——從而在父函數(shù)關閉時結束 goroutine。
我建議使用等待組,這樣可以保證匿名函數(shù)終止。
一個簡單的例子說明了正在發(fā)生的事情:
具有競爭條件
import (
"fmt"
"time"
// "sync"
)
func main() {
go func() {
time.Sleep(3 * time.Second)
fmt.Println("hai")
}()
return
}
沒有競爭條件
import (
"fmt"
"time"
"sync"
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
go func() {
time.Sleep(3 * time.Second)
fmt.Println("hai")
wg.Done()
}()
wg.Wait()
return
}
- 3 回答
- 0 關注
- 179 瀏覽
添加回答
舉報