Golang Go语言中如何打印出“End. [sender]”
大家好,这是我的代码:
func main () {
// synChan := make(chan struct{}, 1)
intChan := make(chan int, 1)
ticker := time.NewTicker(time.Second)
go func() {
for range ticker.C {
select {
case intChan <- 1:
case intChan <- 2:
case intChan <- 3:
}
}
// synChan<- struct{}{}
fmt.Println("End [SEND]")
}()
var sum int
for e := range intChan {
fmt.Printf("接收到 %d\n", e)
sum += e
if sum > 3 {
fmt.Println(sum)
break
}
}
fmt.Println("End [REC]")
// <-synChan
}
这是《 GO 并发编程》里讲通道的一个题目,但是我试了几个方法之后会成死锁,请问大家如何打印出这个 fmt.Println("End [SEND]")。这里为什么不能打印出来?我想过是 main 函数退出了,所以试着使用通道阻塞,但直接会出死锁。。。
Golang Go语言中如何打印出“End. [sender]”
更多关于Golang Go语言中如何打印出“End. [sender]”的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我蛮帮你问了大模型,你试试看:
这段 Go 代码的主要问题是,它在等待一个信号来表明发送 goroutine 已经结束,但是这个信号从未被发送。当sum
大于 3 时,接收循环会中断,但是发送 goroutine 会因为intChan
的缓冲区已满而阻塞,导致无法到达打印"End [SEND]"
的代码行。
要解决这个问题,你需要确保发送 goroutine 有机会发送完成信号。在这个场景中,你可以通过关闭intChan
来实现,因为关闭一个通道会导致所有接收者收到一个零值,并且随后的接收都会立即返回零值,而不会阻塞。因为intChan
是一个 int 类型的通道,接收者会得到一个0
。
以下是修正后的代码,它确保了打印出"End [SEND]"
:go<br>package main<br><br>import (<br> "fmt"<br> "time"<br>)<br><br>func main() {<br> intChan := make(chan int, 1)<br> ticker := time.NewTicker(time.Second)<br> done := make(chan struct{}) // 添加一个完成通道<br><br> go func() {<br> for range ticker.C {<br> select {<br> case intChan <- 1:<br> case intChan <- 2:<br> case intChan <- 3:<br> }<br> }<br> ticker.Stop() // 停止 ticker<br> close(intChan) // 关闭 intChan<br> fmt.Println("End [SEND]")<br> close(done) // 发送完成信号<br> }()<br><br> var sum int<br><br> for e := range intChan {<br> fmt.Printf("接收到 %d\n", e)<br> sum += e<br> if sum > 3 {<br> fmt.Println(sum)<br> break<br> }<br> }<br><br> fmt.Println("End [REC]")<br><br> <-done // 等待发送 goroutine 完成<br>}<br>
这里做了以下改动:
1. 添加了一个done
通道,用来接收发送 goroutine 完成的信号。
2. ticker.Stop()
被调用来停止 ticker ,避免资源泄露。
3. 在发送循环结束后关闭intChan
通道。
4. 打印"End [SEND]"
后,关闭done
通道来发送一个完成信号。
5. 在主函数的最后,添加<-done
来等待发送 goroutine 完成。
现在程序会等待发送 goroutine 结束后,才结束main
函数,确保"End [SEND]"
被打印出来。请注意,这个版本的代码假设发送 goroutine 总是会结束,否则可能会导致死锁。在实际编程中,你可能需要添加超时或其他机制来处理这种情况。
更多关于Golang Go语言中如何打印出“End. [sender]”的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
#1 这个 ai 的答案你试过没有,这里是禁止搬运 ai 回答的,
不行,死锁了
time.NewTicker 是创建了一个周期定时器,下面没有调用 ticker.Stop()来终止定时器,所以 for range ticker.C 回一直循环不会退出
你这个不叫死锁好吧,你要在适当的时候调用 ticker.Stop()让这个 Ticker 停下来,让 channel 被 close
你接收完数据了,不向发送方发送结束命令,它还在发数据呢
ticker.Stop() 停止计时器后只是不再发送数据,但是 channel 并没有被关闭
https://pkg.go.dev/time#Ticker.Stop<br>func main() {<br> intChan := make(chan int, 1)<br> ticker := time.NewTicker(time.Second)<br> end := make(chan int)<br> go func() {<br> loop:<br> for range ticker.C {<br> select {<br> case intChan <- 1:<br> case intChan <- 2:<br> case intChan <- 3:<br> case <-end:<br> fmt.Println("End [SEND]")<br> ticker.Stop()<br> break loop<br> }<br> }<br> }()<br><br> var sum int<br><br> for e := range intChan {<br> fmt.Printf("接收到 %d\n", e)<br> sum += e<br> if sum > 3 {<br> fmt.Println(sum)<br> end <- 1<br> break<br> }<br> }<br> fmt.Println("End [REC]")<br>}<br>
soga ,我懂了,谢谢大佬
抱歉抱歉
在Go语言中,打印输出到控制台通常使用标准库中的fmt
包。要打印出字符串“End. [sender]”,你可以使用fmt.Printf
函数来格式化输出,或者使用fmt.Sprintf
先生成字符串再打印。这里,[sender]
部分需要替换为具体的发送者信息。假设sender
是一个变量,以下是两种方法的示例:
方法一:使用fmt.Printf
直接打印
package main
import (
"fmt"
)
func main() {
sender := "Alice" // 假设发送者是Alice
fmt.Printf("End. [%s]\n", sender)
}
方法二:使用fmt.Sprintf
生成字符串后打印
package main
import (
"fmt"
)
func main() {
sender := "Bob" // 假设发送者是Bob
message := fmt.Sprintf("End. [%s]", sender)
fmt.Println(message)
}
在这两个例子中,%s
是一个占位符,用于表示一个字符串。fmt.Printf
和fmt.Sprintf
会将sender
变量的值替换到%s
的位置。fmt.Printf
直接输出到标准输出,而fmt.Sprintf
返回一个格式化后的字符串,你可以将其赋值给变量或进一步处理。
根据你的需求选择合适的方法即可。如果你的sender
变量已经存在,并且你需要动态地构建和打印这条消息,这两种方法都非常有效。