GO程序陷入循环中。

huangapple go评论69阅读模式
英文:

GO program stuck in a loop

问题

// _关闭_一个通道表示不会再向其发送值。这对于向通道的接收方传达完成信息非常有用。

package main

import "fmt"

// 在这个例子中,我们将使用一个jobs通道将工作从main() goroutine传递给工作goroutine。
// 当我们没有更多的工作要给工作goroutine时,我们将close jobs通道。
func main() {
jobs := make(chan int, 5)
done := make(chan bool)

// 这是工作goroutine。它使用`j, more := <-jobs`从`jobs`接收。
// 在这个特殊的2值接收形式中,如果`jobs`已经被`close`并且通道中的所有值都已经被接收,
// `more`值将为`false`。我们使用这个来在我们完成所有工作时通知`done`。

for i := 1; i <= 3; i++ {
    go func() {
        for {
            j, more := <-jobs
            if more {
                fmt.Println("接收到工作", j)
            } else {
                fmt.Println("接收到所有工作")
                done <- true
                return
            }
        }
    }()
}

// 这将通过`jobs`通道向工作goroutine发送3个工作,然后关闭它。
j := 0
for {
    j++
    jobs <- j
    fmt.Println("发送工作", j)
}
close(jobs)
fmt.Println("发送所有工作")

// 我们使用之前看到的[synchronization](channel-synchronization)方法等待工作goroutine。
<-done

}

https://play.golang.org/p/x28R_g8ftS

我尝试的是从分页的URL端点获取所有响应。jobs是一个存储页码的通道。我在if more{}中有一个检查空响应的函数,我有

done <- true
return

我以为这会关闭goroutine。
但是,页面生成器for{j++; jobs <- j}导致它陷入循环。有什么办法可以解决这个问题吗?

英文:
// _Closing_ a channel indicates that no more values
// will be sent on it. This can be useful to communicate
// completion to the channel&#39;s receivers.

package main

import &quot;fmt&quot;

// In this example we&#39;ll use a `jobs` channel to
// communicate work to be done from the `main()` goroutine
// to a worker goroutine. When we have no more jobs for
// the worker we&#39;ll `close` the `jobs` channel.
func main() {
	jobs := make(chan int, 5)
	done := make(chan bool)

	// Here&#39;s the worker goroutine. It repeatedly receives
	// from `jobs` with `j, more := &lt;-jobs`. In this
	// special 2-value form of receive, the `more` value
	// will be `false` if `jobs` has been `close`d and all
	// values in the channel have already been received.
	// We use this to notify on `done` when we&#39;ve worked
	// all our jobs.

	for i := 1; i &lt;= 3; i++ {
		go func() {
			for {
				j, more := &lt;-jobs
				if more {
					fmt.Println(&quot;received job&quot;, j)
				} else {
					fmt.Println(&quot;received all jobs&quot;)
					done &lt;- true
					return
				}
			}
		}()
	}

	// This sends 3 jobs to the worker over the `jobs`
	// channel, then closes it.
	j := 0
	for {
		j++
		jobs &lt;- j
		fmt.Println(&quot;sent job&quot;, j)
	}
	close(jobs)
	fmt.Println(&quot;sent all jobs&quot;)

	// We await the worker using the
	// [synchronization](channel-synchronization) approach
	// we saw earlier.
	&lt;-done
}

https://play.golang.org/p/x28R_g8ftS

What I'm trying to do is get all the responses from a paginated url endpoint. jobs is a channel storing the page number. I have a function in if more{} checking for empty reponse and I have

done &lt;- true
return

I thought this would close the go routine.
But, the page generator for{j++; jobs &lt;- j} is causing it to get stuck in a loop. Any idea how this can be resolved?

答案1

得分: 2

根据定义,没有条件的for循环是一个无限循环。除非你加入一些逻辑来打破这个无限循环,否则你将永远无法跳出它。

根据你的注释,你想发送3个作业。你应该相应地修改你的for循环:

for j := 0; j < 3; j++ {
  jobs <- j
  fmt.Println("发送作业", j)
}
英文:

By definition a for loop without conditions is an infinite loop. Unless you put some logic to break this infinite loop, you'll never get out of it.

In your playground your comment implies that you want to send 3 jobs. You should change your for loop accordingly:

for j := 0; j &lt; 3; j++ {
  jobs &lt;- j
  fmt.Println(&quot;sent job&quot;, j)
}

答案2

得分: 1

这是一个简化版本的工作程序。它对于生产级别的流量来说并不是很有用,但可以作为一个简单的示例,有很多类似的程序。

package main

import (
	"log"
	"sync"
)

type worker struct {
	jobs chan int
	wg   *sync.WaitGroup
}

func main() {
	w := worker{
		jobs: make(chan int, 5), // 我只想同时处理5个任务
		wg:   new(sync.WaitGroup),
	}

	for i := 0; i < 3; i++ {
		w.wg.Add(1)
		go func(i int) {
			defer w.wg.Done()
			w.jobs <- i
		}(i)

	}

	// 在后台等待,以便我可以转到第34行并开始处理我的任务队列
	go func() {
		w.wg.Wait()
		close(w.jobs)
	}()

	for job := range w.jobs {
		log.Println("收到任务,我应该对其进行处理", job)
	}

}

希望这个翻译对你有帮助!

英文:

This is a simplified version of a worker.. Its not very useful for production level traffic, but should serve as a simple example, there are tons of them GO程序陷入循环中。

package main

import (
	&quot;log&quot;
	&quot;sync&quot;
)

type worker struct {
	jobs chan int
	wg   *sync.WaitGroup
}

func main() {
	w := worker{
		jobs: make(chan int, 5), // I only want to work on 5 jobs at any given time
		wg:   new(sync.WaitGroup),
	}

	for i := 0; i &lt; 3; i++ {
		w.wg.Add(1)
		go func(i int) {
			defer w.wg.Done()
			w.jobs &lt;- i
		}(i)

	}

	// wait in the background so that i can move to line 34 and start consuming my job queue
	go func() {
		w.wg.Wait()
		close(w.jobs)
	}()

	for job := range w.jobs {
		log.Println(&quot;Got job, I should do something with it&quot;, job)
	}

}

答案3

得分: 0

这是我一直在寻找的内容。我有一个在无限循环中的数字生成器。程序在某个条件下退出,例如在这个示例中,是在 j 值上,但也可以是其他条件。

package main

import "fmt"

func jobs(job chan int) {
    i := 1
    for {
        job <- i
        i++
    }
}

func main() {
    jobsChan := make(chan int, 5)

    done := false
    j := 0

    go jobs(jobsChan)
    for !done {
        j = <-jobsChan
        if j < 20 {
            fmt.Printf("job %d\n", j)
        } else {
            done = true
        }
    }
}

链接:https://play.golang.org/p/Ud4etTjrmx

英文:

This was I was looking for. I have a number generator in an infinite while loop. And the program exits on some condition, in this example, it is on the j value, but it can also be something else.

https://play.golang.org/p/Ud4etTjrmx

package main

import &quot;fmt&quot;



func jobs(job chan int) {
	i := 1
	for {
		job &lt;- i
		i++
	}
}

func main() {
	jobsChan := make(chan int, 5)


	done := false
	j := 0

	go jobs(jobsChan)
	for !done {
		j = &lt;-jobsChan
		if j &lt; 20 {
			fmt.Printf(&quot;job %d\n&quot;, j)
		} else {
			done = true
		}
	}
}

huangapple
  • 本文由 发表于 2017年9月13日 08:42:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/46187181.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定