下面的代码与硬编码的JSON数据一起正常工作,但是当我从文件中读取JSON数据时不起作用。我得到fatal error: all goroutines are asleep - deadlock
使用时的错误sync.WaitGroup
。
硬编码JSON数据的工作示例:
package main
import (
"bytes"
"fmt"
"os/exec"
"time"
)
func connect(host string) {
cmd := exec.Command("ssh", host, "uptime")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
fmt.Println(err)
}
fmt.Printf("%s: %q\n", host, out.String())
time.Sleep(time.Second * 2)
fmt.Printf("%s: DONE\n", host)
}
func listener(c chan string) {
for {
host := <-c
go connect(host)
}
}
func main() {
hosts := [2]string{"user1@111.79.154.111", "user2@111.79.190.222"}
var c chan string = make(chan string)
go listener(c)
for i := 0; i < len(hosts); i++ {
c <- hosts[i]
}
var input string
fmt.Scanln(&input)
}
输出:
user@user-VirtualBox:~/go$ go run channel.go
user1@111.79.154.111: " 09:46:40 up 86 days, 18:16, 0 users, load average: 5"
user2@111.79.190.222: " 09:46:40 up 86 days, 17:27, 1 user, load average: 9"
user1@111.79.154.111: DONE
user2@111.79.190.222: DONE
不起作用-读取JSON数据文件的示例:
package main
import (
"bytes"
"fmt"
"os/exec"
"time"
"encoding/json"
"os"
"sync"
)
func connect(host string) {
cmd := exec.Command("ssh", host, "uptime")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
fmt.Println(err)
}
fmt.Printf("%s: %q\n", host, out.String())
time.Sleep(time.Second * 2)
fmt.Printf("%s: DONE\n", host)
}
func listener(c chan string) {
for {
host := <-c
go connect(host)
}
}
type Content struct {
Username string `json:"username"`
Ip string `json:"ip"`
}
func main() {
var wg sync.WaitGroup
var source []Content
var hosts []string
data := json.NewDecoder(os.Stdin)
data.Decode(&source)
for _, value := range source {
hosts = append(hosts, value.Username + "@" + value.Ip)
}
var c chan string = make(chan string)
go listener(c)
for i := 0; i < len(hosts); i++ {
wg.Add(1)
c <- hosts[i]
defer wg.Done()
}
var input string
fmt.Scanln(&input)
wg.Wait()
}
输出值
user@user-VirtualBox:~/go$ go run deploy.go < hosts.txt
user1@111.79.154.111: " 09:46:40 up 86 days, 18:16, 0 users, load average: 5"
user2@111.79.190.222: " 09:46:40 up 86 days, 17:27, 1 user, load average: 9"
user1@111.79.154.111 : DONE
user2@111.79.190.222: DONE
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc210000068)
/usr/lib/go/src/pkg/runtime/sema.goc:199 +0x30
sync.(*WaitGroup).Wait(0xc210047020)
/usr/lib/go/src/pkg/sync/waitgroup.go:127 +0x14b
main.main()
/home/user/go/deploy.go:64 +0x45a
goroutine 3 [chan receive]:
main.listener(0xc210038060)
/home/user/go/deploy.go:28 +0x30
created by main.main
/home/user/go/deploy.go:53 +0x30b
exit status 2
user@user-VirtualBox:~/go$
主机
[
{
"username":"user1",
"ip":"111.79.154.111"
},
{
"username":"user2",
"ip":"111.79.190.222"
}
]
当主功能结束时,Go程序结束。
从语言规范
程序执行首先初始化主程序包,然后调用函数main。当该函数调用返回时,程序退出。它不等待其他(非主)goroutine完成。
因此,您需要等待goroutine完成。常见的解决方案是使用sync.WaitGroup对象。
最简单的同步goroutine的代码:
package main
import "fmt"
import "sync"
var wg sync.WaitGroup // 1
func routine() {
defer wg.Done() // 3
fmt.Println("routine finished")
}
func main() {
wg.Add(1) // 2
go routine() // *
wg.Wait() // 4
fmt.Println("main finished")
}
并用于同步多个goroutine
package main
import "fmt"
import "sync"
var wg sync.WaitGroup // 1
func routine(i int) {
defer wg.Done() // 3
fmt.Printf("routine %v finished\n", i)
}
func main() {
for i := 0; i < 10; i++ {
wg.Add(1) // 2
go routine(i) // *
}
wg.Wait() // 4
fmt.Println("main finished")
}
WaitGroup按执行顺序使用。
*实际参数在开始新的鱼肉素之前要进行评估。因此,需要在对它们进行显式评估之前,wg.Add(1)
使可能出现恐慌的代码不会留下增加的计数器。
用
param := f(x)
wg.Add(1)
go g(param)
代替
wg.Add(1)
go g(f(x))
问题内容: 我想编写三个同时发送整数的并发go例程。现在,我的代码已正确编译,但是在第一次执行后,出现错误“所有goroutine都处于睡眠状态- 死锁!”。我试图找到错误,但是在代码逻辑中找不到任何错误。有人可以帮助我在我的代码中查找错误。我的代码如下。提前致谢。 谁能告诉我为什么我将Routine2和Routine3声明为go例程,为什么输出为[no output]。我是GO语言的新手,据我从
问题内容: 给出以下简单的Go程序 我想知道是否有人可以启发我 谢谢 问题答案: 由于您从不关闭通道,因此范围循环将永远不会结束。 您不能在同一频道上发送结果。一种解决方案是使用其他解决方案。 您的程序可以这样修改:
问题内容: 我正在尝试剥离一组goroutine,然后等待它们全部完成。 但是,当我运行此代码时,出现以下错误: 我很困惑,因为我写的几乎与文档示例所演示的完全一样。 问题答案: 您需要将指针传递给WaitGroup,而不是WaitGroup对象。当您传递实际的WaitGroup时,Go会生成该值的副本,然后调用该副本。结果是原始的WaitGroup将具有10个Add,而没有Done,并且Wait
问题内容: 对于我的要求之一,我必须创建N个工作程序例程,该例程将由一个监视程序监视。所有工作程序完成后,监视程序必须结束。我的代码以死锁结尾,请帮忙。 问题答案: 您的monitorWorker永不死。当所有工作人员完成时,它将继续等待cs。这将导致死锁,因为其他任何东西都不会继续发送给CS,因此wg永远不会达到0。一种可能的解决方法是,当所有工作程序完成时,让监视器关闭通道。如果for循环在m
问题内容: 在进行工作之前,我一直遵循一种检查通道中是否有东西的模式: 这是基于这部视频的。这是我的完整代码: 如果您尝试运行它,则在打印将要中断的消息之前,我们最终将陷入僵局。自上次以来,当chan中没有其他内容时,tbh才有意义,因此我们试图拉出该值,因此出现此错误。但是这样的模式是不可行的。我如何使此代码起作用以及为什么会出现此死锁错误(大概此模式应该起作用?)。 问题答案: 鉴于您在一个频
问题内容: 例如,有没有一种我可以执行的方法 然后在需要时“唤醒”睡眠的goroutine? 我看到里面有一个,但是我无法调用它。有什么想法吗? 问题答案: 没有办法中断,但是,您可以使用和语句来获取所需的功能。 一个简单的例子来展示基本思想: http://play.golang.org/p/7uKfItZbKG 在此示例中,我们生成了一个信令goroutine来告知main停止暂停。主要是在两