想从一个字符切片[]string中打印切片中的每个元素, 且每个打印动作都用一个goroutine完成, 限制goroutine最大数量 为5。
以下是我写的代码, 但不能打印完整, 5个goroutine用完后不会打切片后面的字符了,怎么让goroutine循环使用, 将其切片中所有的字符 打印完? 哪位高手来指点一下。
```go
package main
import (
"fmt"
"time"
)
type Worker struct {
Workcount int
}
func (w *Worker) Run(ch chan string, strs []string) {
for i := 0; i < w.Workcount; i++ {
var s string
if len(strs) > 0 {
s = strs[0]
strs = strs[1:]
}
createWorker(ch, s, i)
}
}
func createWorker(ch chan string, s string, goid int) {
go func(id int) {
worker(id,ch, s)
}(goid)
}
func worker(id int,ch chan string, str string) {
ch <- str
fmt.Printf("goid is %d , string is %s\n", id, str)
}
func main() {
input := []string{"goland", "time", "slice", "reflect", "strings", "regexp", "map", "convert", "google", "complier"}
e := Worker{Workcount: 5}
ch := make(chan string)
e.Run(ch, input)
t := time.After(5 * time.Second)
for {
select {
case re := <-ch:
fmt.Println(re)
case <-t:
fmt.Println("timeout")
return
}
}
}
```
更多评论
改成以下代码后, 可以实现, 但有一个奇怪的问题是select中注释掉time.After和<-t 后就会死锁了, 是什么原因呢?
```go
package main
import (
"fmt"
//"time"
)
type Worker struct {
Workcount int
requestchan chan string
workchan chan string
}
func (w *Worker) Run(strs []string) {
for _, v := range strs {
go func(s string) {
w.requestchan <- s
}(v)
}
for i := 0; i < w.Workcount; i++ {
w.worker(i)
}
//t := time.After(15 * time.Second)
for {
select {
case re := <-w.requestchan:
w.submit(re)
case work := <-w.workchan:
fmt.Println(work)
//case <-t:
// fmt.Println("---timeout--")
// return
}
}
}
func (w *Worker) worker(goid int) {
go func(id int) {
fmt.Printf("goid is %d\n", id)
}(goid)
}
func (w *Worker) submit(s string) {
go func() {
w.workchan <- s
}()
}
func main() {
input := []string{"php", "java", "python", "javascript", "goland", "time", "slice", "reflect", "strings", "regexp", "map", "convert", "google", "complier"}
e := Worker{Workcount: 5, requestchan: make(chan string), workchan: make(chan string)}
e.Run(input)
}
```
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [select]:
main.(*Worker).Run(0xc00000a080, 0xc00003c6a8, 0xe, 0xe)
/home/steven/go/src/mytest/mtest/ch.go:26 +0x18a
main.main()
/home/steven/go/src/mytest/mtest/ch.go:54 +0xf3
exit status 2
#2
因为你的requestchan workchan 都是非缓冲型的同步chan,主goroutines 同步完全阻塞自然就死锁了。
time.After 相当于存在一个 goroutines,等于并非只有一个 主goroutines,不会产生阻塞死锁自然就没问题了
#3