下面的代码适用于硬编码的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)
}
Run Code Online (Sandbox Code Playgroud)
OUTPUT:
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
Run Code Online (Sandbox Code Playgroud)
不工作 - 阅读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()
}
Run Code Online (Sandbox Code Playgroud)
OUTPUT
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$
Run Code Online (Sandbox Code Playgroud)
HOSTS.TXT
[
{
"username":"user1",
"ip":"111.79.154.111"
},
{
"username":"user2",
"ip":"111.79.190.222"
}
]
Run Code Online (Sandbox Code Playgroud)
Grz*_*Żur 44
当主函数结束时,Go程序结束.
从语言规范
程序执行从初始化主包然后调用main函数开始.当该函数调用返回时,程序退出.它不等待其他(非主要)goroutines完成.
因此,您需要等待您的goroutines完成.对此的常见解决方案是使用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")
}
Run Code Online (Sandbox Code Playgroud)
并用于同步多个goroutines
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")
}
Run Code Online (Sandbox Code Playgroud)
WaitGroup按执行顺序使用.
*在开始新的gouroutine之前评估实际参数.因此,需要明确地对它们进行评估,wg.Add(1)以便可能恐慌的代码不会留下增加的计数器.
使用
param := f(x)
wg.Add(1)
go g(param)
Run Code Online (Sandbox Code Playgroud)
代替
wg.Add(1)
go g(f(x))
Run Code Online (Sandbox Code Playgroud)
小智 5
感谢 Grzegorz \xc5\xbbur 提供的非常详细的解释。\n我想指出的是,通常需要线程化的 func 不会在 中main(),所以我们会有这样的东西:
package main\n\nimport (\n "bufio"\n "fmt"\n "io"\n "io/ioutil"\n "math/rand"\n "os"\n "reflect"\n "regexp"\n "strings"\n "sync"\n "time"\n)\n\nvar wg sync.WaitGroup // VERY IMP to declare this globally, other wise one //would hit "fatal error: all goroutines are asleep - deadlock!"\n\nfunc doSomething(arg1 arg1Type) {\n // cured cancer\n}\n\nfunc main() {\n r := rand.New(rand.NewSource(time.Now().UnixNano()))\n randTime := r.Intn(10)\n wg.Add(1) \n go doSomething(randTime)\n wg.Wait()\n fmt.Println("Waiting for all threads to finish")\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我想指出的是,全局声明wg对于所有线程在之前完成非常重要main()
| 归档时间: |
|
| 查看次数: |
27611 次 |
| 最近记录: |