我是 goroutines、channels 之类的新手,如果这看起来微不足道,我深表歉意。
我写了下面的代码:
for _, h := range hosts {
go func() {
httpClient := cleanhttp.DefaultPooledClient()
// format the URL with the passed host and por
url := fmt.Sprintf("https://%s:%v", h.Name, h.Port)
// create a vault client
client, err := api.NewClient(&api.Config{Address: url, HttpClient: httpClient})
if err != nil {
panic(err)
}
// get the current status
status := v.VaultStatus(client)
// send the status to a channel
s <- strconv.FormatBool(status.Ready)
}()
// assign the value of channel to a var
cs := <-s
// print it
fmt.Printf("Host: %s Status: %s\n", h.Name, cs)
}
},
这个想法很简单,它需要一个主机列表,然后使用 Golang Vault API 去确定当前状态。我很高兴它有效。
我想做的是确保这些操作并行进行。当我运行以下代码时,我得到如下结果:
host: Host1: status: true
host: Host2: status: false
host: Host3: status: true
host: Host4: status: true
这里的问题是这些主机总是以相同的顺序返回。我认为 goroutines 根本不是并行执行的,因为它们似乎一个接一个地运行,然后每次都以相同的顺序打印。
代码是否按照我认为应该的方式运行?我如何知道这个 goroutine 是并行运行的?
最佳答案
您一次只运行一个 goroutine,因为主 goroutine 在继续循环的下一次迭代之前在 channel 上等待。相反,您应该在所有 goroutine 启动后等待 for 循环外的 channel 上的结果。顺便说一句,您还需要在 channel 上发送一些标识主机的内容。
顺便说一下,你的 goroutine 函数有一个潜在的问题。您正在使用变量 h
,每次循环都会由主 goroutine 更改,因此您真的不知道在其他 goroutine 中得到了什么(假设您小心我上面提到的问题,以便 goroutines 并行运行)。您不应直接引用该变量,而应将其作为参数传递给 goroutine 函数(或者您可以在 for 循环内创建一个不同的变量并为其分配 h
的值并在函数)。
尝试这样做:
var wg sync.WaitGroup
for _, h := range hosts {
h := h // create local copy of loop var
wg.Add(1)
go func() {
defer wg.Done()
httpClient := cleanhttp.DefaultPooledClient()
// format the URL with the passed host and por
url := fmt.Sprintf("https://%s:%v", h.Name, h.Port)
// create a vault client
client, err := api.NewClient(&api.Config{Address: url, HttpClient: httpClient})
if err != nil {
panic(err)
}
// get the current status
status := v.VaultStatus(client)
// print it
fmt.Printf("Host: %s Status: %v\n", h.Name, status.Ready)
}()
}
wg.Wait()
关于Goroutine并行执行确认,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42753067/