Golang通道阻塞操作

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

Golang channel blocking operations

问题

我正在尝试停止子(或链接的)Go通道,但操作是阻塞的(例如等待网络连接的监听器)。

由于操作是阻塞的,因此在<-quit的情况下,for和case永远不会进入。

如何解决这个问题?

package main

import (
	"fmt"
	"time"
)

func main() {
	quit := make(chan bool)

	fmt.Println("Starting Channel 001")
	go func() {
		for {
			select {
			case <-quit:
				fmt.Println("Channel 001 stopped")
				// 期望结果:hangFunction停止执行循环
				return
			default:
				hangFunction()
				time.Sleep(1 * time.Second)

			}
		}
	}()

	time.Sleep(2 * time.Second)

	fmt.Println("Closing channel 001")
	close(quit)

	time.Sleep(1 * time.Hour)
}

func hangFunction() {
	for {
		fmt.Println("[hangFunction] Looping")
		time.Sleep(1 * time.Second)
	}
}

请注意,我只提供了代码的翻译部分,不包括其他内容。

英文:

I'm trying to stop child (or chained) go channels, but operation is blocking (e.g listener with wait network connection)

Because operation is blocking, for and case never enter in case <-quit

How to solve this ?

package main

import (
	&quot;fmt&quot;
	&quot;time&quot;
)

func main() {
	quit := make(chan bool)

	fmt.Println(&quot;Starting Channel 001&quot;)
	go func() {
		for {
			select {
			case &lt;-quit:
				fmt.Println(&quot;Channel 001 stopped&quot;)
				// Expected result: hangFunction stop execution looping
				return
			default:
				hangFunction()
				time.Sleep(1 * time.Second)

			}
		}
	}()

	time.Sleep(2 * time.Second)

	fmt.Println(&quot;Closing channel 001&quot;)
	close(quit)

	time.Sleep(1 * time.Hour)
}

func hangFunction() {
	for {
		fmt.Println(&quot;[hangFunction] Looping&quot;)
		time.Sleep(1 * time.Second)
	}
}

答案1

得分: 1

你可以在hangFunction()中删除for{}循环,该循环会一直阻塞:

func hangFunction() {
	fmt.Println("[hangFunction] Looping")
	time.Sleep(1 * time.Second)
}

或者你可以像@Adrian在评论中提到的那样,在函数内部监视通道,做如下操作:

func hangFunction(quit chan bool) {
	for {
		select {
		case <-quit:
			return
		default:
			fmt.Println("[hangFunction] Looping")
			time.Sleep(1 * time.Second)
		}
	}
}

这种方法不是很理想,因为你在主函数和函数中都有相同的select{}块。不过它可以工作。

英文:

You can remove the for{} loop in hangFunction() which is blocking forever:

func hangFunction() {
	fmt.Println(&quot;[hangFunction] Looping&quot;)
	time.Sleep(1 * time.Second)
}

Or you can monitor the channel from within the function as @Adrian mentionned in the comments, by doing something like:

func hangFunction(quit chan bool) {
	for {
		select {
		case &lt;-quit:
			return
		default:
			fmt.Println(&quot;[hangFunction] Looping&quot;)
			time.Sleep(1 * time.Second)
		}
	}
}

which is not ideal as you have the same select{} block twice (in your main and in the function). It will work tho.

huangapple
  • 本文由 发表于 2021年10月9日 05:28:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/69501891.html
匿名

发表评论

匿名网友

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

确定