golang错误:致命错误:所有goroutines都处于睡眠状态

时间:2017-09-23 14:57:51

标签: go

我想在Go中开发一个简单的电子邮件发件人,但我遇到了一些问题,这是我的实际代码:

package main


import (
    "flag"
    "sync"
    "fmt"
)

var logLevel = 0

func sendEmail(try combo){
        fmt.Printf("test send %s %s %s\n", try.to, try.from, try.subject)
}

// where we actually do the work
func work(toSend chan combo, wg *sync.WaitGroup) {
    for send := range toSend {
        sendEmail(send)
    }

    // let the main thread know we're done
    wg.Done()
}

// the basic unit that we pass around
type combo struct {
    to       string
    from     string
    subject  string
    header   string
    body     string
    success bool
}


func main() {

    //defaults variables
    emailsList, smtpList        := "", ""  
    typeConnect, ConnFileName  := "", ""
    delimStart, delimEnd       := "_STARTSUB_", "_ENDSUB_"
    threads, bcc := 5,  1
    skip := 0
    logFile := ""

    // Args parse
    flag.StringVar(&emailsList, "e", "", "load email list (required)") 
    flag.StringVar(&smtpList, "s", "", "load smtp list - (required)")
    flag.IntVar(&bcc, "b", 1, "number of emails sent per connection")
    flag.IntVar(&threads,"t", 2, "run `N` attempts in parallel threads")
    flag.StringVar(&typeConnect, "c", "","direct - send emails directly through smtp\n"+"\tsocks - send emails through smtp via socks5 [requires -f argument]\n"+"\thosts - send emails through smtp via server's ip addresses [requires -f argument]\n")
    flag.StringVar(&ConnFileName, "f", "", "if sending via socks the list should contain socks5 proxies in the following formats\n"+"\tip:port\n"+"\tip:port:user:pass\n")
    flag.StringVar(&delimStart, "q", "_STARTSUB_", "start delimiter for subject.")
    flag.StringVar(&delimEnd, "w", "_ENDSUB_", "end delimiter for subject.")
    flag.IntVar(&skip, "l", 0, "skip first `n` lines of input")
    flag.StringVar(&logFile, "debug", "", "write debug output to `file`")
    flag.IntVar(&logLevel, "d", 0, "set debug `level`")

    flag.Parse()

    var wg sync.WaitGroup // keep track of the workers
    toSend := make(chan combo) // to the workers

    // initialize n workers
    wg.Add(int(threads))
    for i := 0; i < int(threads); i++ {
        go work(toSend, &wg)
    }

    for email := range StreamLines("EMAILS", emailsList, skip) {

        from := "info@testfrom.com"
        subject := "test subject"
        header := "test header"
        body   := "test boady"

        try := combo{email,from, subject, header, body, false}
        toSend <- try
    }

    wg.Wait()
    close(toSend)

    fmt.Println("Send emails Done!")
}

我尝试使用频道向golang中的工作人员发送电子邮件,并返回此错误:

F:\dev\GoLang\gitlab\EasySend>go run main.go usage.go utils.go  -e emails.txt
test send test@gmail.com info@testfrom.com test subject
test send test@gmail.com info@testfrom.com test subject
test send test@gmail.com info@testfrom.com test subject
test send test@gmail.com info@testfrom.com test subject
test send test@gmail.com info@testfrom.com test subject
test send test@gmail.com info@testfrom.com test subject
test send test@gmail.com info@testfrom.com test subject
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc04204c0fc)
        C:/Go/src/runtime/sema.go:56 +0x40
sync.(*WaitGroup).Wait(0xc04204c0f0)
        C:/Go/src/sync/waitgroup.go:131 +0x79
main.main()
        F:/dev/GoLang/gitlab/EasySend/main.go:90 +0x7af

goroutine 18 [chan receive]:
main.work(0xc04203e0c0, 0xc04204c0f0)
        F:/dev/GoLang/gitlab/EasySend/main.go:19 +0x110
created by main.main
        F:/dev/GoLang/gitlab/EasySend/main.go:76 +0x5db

goroutine 19 [chan receive]:
main.work(0xc04203e0c0, 0xc04204c0f0)
        F:/dev/GoLang/gitlab/EasySend/main.go:19 +0x110
created by main.main
        F:/dev/GoLang/gitlab/EasySend/main.go:76 +0x5db
exit status 2

我想知道我哪里错了?方式返回此错误

  

“致命错误:所有goroutine都睡着了 - 死锁!”

1 个答案:

答案 0 :(得分:1)

程序死锁,因为main正在等待goroutines完成,并且goroutines正在等待通道上的工作。要解决此问题,请在主

中交换这些行的顺序
wg.Wait()
close(toSend)

close(toSend)
wg.Wait()

当频道关闭时,工作人员退出频道上的for循环,工作人员调用wg.Done()。