
go 程序在 `main` 函数返回后立即终止,若未同步等待 goroutine 完成,其内部逻辑(如 `fmt.println`)可能被直接丢弃,导致看似“无输出”。
在 Go 中,启动 goroutine 是非阻塞的——它只是将函数提交到调度器队列,但不会自动等待执行完成。你提供的代码中存在两个关键问题:
- main 函数过早退出:go h.Myprint("need to go") 启动了一个 goroutine,而 main() 随即结束,整个进程终止,导致该 goroutine 甚至来不及被调度执行;
- 嵌套 goroutine 缺乏同步机制:Myprint 方法内部又启动了一层 goroutine(go func() { fmt.Println(...) }()),但既无等待逻辑,也无任何信号通知外部其已完成。
✅ 正确做法是使用同步原语(如 sync.WaitGroup)显式等待 goroutine 完成。以下是修复后的完整示例:
package main
import (
"fmt"
"sync"
"time" // 仅用于演示,实际应避免 sleep 替代同步
)
type Hello struct {
a int
}
func (h *Hello) Myprint(value string, wg *sync.WaitGroup) {
defer wg.Done() // 标记此 goroutine 完成
fmt.Println(value)
}
func main() {
h := &Hello{100}
var wg sync.WaitGroup
wg.Add(1)
go h.Myprint("need to go", &wg)
wg.Wait() // 阻塞直到所有 Add 的 goroutine 调用 Done()
}? 注意事项:
- ❌ 不要用 time.Sleep() 代替 WaitGroup —— 它不可靠(时间过短会失败,过长则低效),且违背 Go 并发设计哲学;
- ✅ WaitGroup 是最常用、最推荐的轻量级同步方式,适用于已知 goroutine 数量的场景;
- ⚠️ 若需传递结果或错误,应结合 channel 使用;若涉及共享状态修改,请额外注意数据竞争,必要时加 sync.Mutex;
- ? 可通过 go run -race main.go 启用竞态检测器,提前发现潜在并发 bug。
总结:Go 的并发不是“自动等待”,而是“自主调度 + 显式同步”。理解 main 的生命周期与 goroutine 的协作关系,是写出可靠并发程序的第一步。










