Go 中 Goroutine 未执行的常见原因及正确同步方法
技术百科
花韻仙語
发布时间:2026-01-17
浏览: 次 当 main 函数返回时,go 程序立即退出,不会等待其他 goroutine 完成;因此若未显式同步,含 time.sleep 的代码可能因 main 提前结束而无法输出结果。
在 Go 中,程序生命周期由 main 函数严格控制:main() 函数执行完毕(即 main 函数体最后一行代码执行后),整个程序立即终止——无论其他 goroutine 是否仍在运行、是否已开始执行或是否即将打印日志。这正是你观察到“添加 time.Sleep(time.Second) 后反而不输出”的根本原因。
表面上看,time.Sleep 延迟了 c
✅ 正确做法:使用通道实现 goroutine 同步
最符合 Go 风格的解决方案是引入一个 done 通道,让 main 主动等待工作 goroutine 完成关键操作(如打印)后再退出:
package main
import (
"fmt"
"time"
)
func my_func(c, done chan int) {
val := <-c
fmt.Println(val) // 关键逻辑执行完成
done <- 1 // 通知 main:我已就绪
}
func main() {
c := make(chan int)
done := make(chan int) // 无缓冲通道,保证同步语义
go my_func(c, done)
time.Sleep(time.Second) // 模拟延迟(非必需,仅用于演示场景)
c <- 3
<-done // 阻塞等待 my_func 发送信号 → 确保打印已完成
}? 关键点解析:done 是无缓冲通道,
⚠️ 注意事项与最佳实践
- ❌ 避免用 time.Sleep 作为 goroutine 同步手段:它不可靠、难以维护,且在高负载或不同环境中行为不一致;
- ✅ 优先使用通道(channel)、sync.WaitG
roup 或 context 进行显式同步;
- ? 若 goroutine 仅需单次通知,无缓冲通道简洁高效;若需多次通知或计数,sync.WaitGroup 更合适;
- ? 在真实项目中,还应考虑超时控制(如 select + time.After),防止死锁:
select {
case <-done:
fmt.Println("goroutine completed successfully")
case <-time.After(2 * time.Second):
fmt.Println("timeout: goroutine did not finish in time")
}总之,Go 的并发模型强调明确的通信与同步,而非隐式的执行时序依赖。理解 main 的生命周期边界,并主动设计同步机制,是编写健壮并发程序的第一课。
# ai
# 它不
# 而不
# 仅需
# 而非
# app
# go
# 并发
# 同步机制
# 死锁
# 事件
# channel
# 根本原因
# select
# 上看
# 我已
# 还应
# 严格控制
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11怎么关闭边缘滑动手势_Windows11
- Python并发安全问题_资源竞争说明【指导】
- Windows10系统怎么查看CPU核心数_Win
- Win11如何关闭小娜Cortana Win11禁
- Python网页解析流程_html结构说明【指导】
- Linux如何安装Golang环境_Linux下G
- Win11怎么连接投影仪_Win11多显示器投屏设
- Win11怎么检查TPM2.0模块_Windows
- Windows Defender扫描失败怎么办_安
- 如何使用Golang进行HTTP服务性能测试_测量
- c# await 一个已经完成的Task会发生什么
- Win11怎么开启远程桌面连接_Windows11
- Win11怎么关闭搜索历史_Win11清除任务栏搜
- Python函数缓存机制_lru_cache解析【
- 如何在 Django 中修改用户密码后保持会话不丢
- 怎么将XML数据可视化 D3.js加载XML
- Python对象比较与排序_魔术方法解析【教程】
- LINUX怎么进行文本内容搜索_Linux gre
- 如何在Golang中处理通道发送接收错误_防止阻塞
- Windows资源管理器总是卡顿或重启怎么办?(修
- 如何在 PHP 单元测试中正确模拟带方法的图像处理
- Win11怎么开启专注模式_Windows11时钟
- Win11怎么设置右键刷新选项_Windows11
- 如何在Mac上搭建Golang开发环境_使用Hom
- Win10怎么设置开机密码_Windows10账户
- Win10电脑怎么设置IP地址_Windows10
- Win11怎么设置按流量计费_Win11限制后台流
- c++中的CRTP是什么 c++奇异递归模板模式【
- 如何使用Golang读取日志文件_Golang b
- Win10怎么卸载迅雷_Win10彻底卸载迅雷方法
- C#如何使用XPathNavigator高效查询X
- Win10怎样清理C盘阿里旺旺缓存_Win10清理
- 手机php怎么转mp4_手机端php文件转mp4a
- Python随机数生成_random模块说明【指导
- Windows如何查看和管理已安装的字体?(字体文
- Win11怎么关闭任务栏小图标_Windows11
- Windows怎样关闭锁屏广告_Windows关闭
- c++的位运算怎么用 与、或、异或、移位操作详解【
- C++中的Pimpl idiom是什么,有什么好处
- Windows10如何更改鼠标图标_Win10鼠标
- Win11怎么设置ip地址_Windows 11手
- php修改数据怎么批量改状态_批量更新status
- 如何使用Golang开发基础文件下载功能_Gola
- 如何在Golang中处理URL参数_Golang
- c++如何判断文件是否存在_c++ filesys
- 如何使用Golang实现路由参数绑定_使用Mux和
- c++输入输出流 c++ cin与cout格式化输
- php打包exe后无法写入文件_权限问题解决方法【
- 如何在 Laravel 中通过嵌套关联关系进行 o
- 零基础学会Python自动化办公_高效处理Exce


QQ客服