go程序入口必须是package main中的func main(),参数和返回值均为空;多main包需分别构建;main结束进程立即退出,不等待goroutine或defer中的异步操作。

main函数必须在main包里,否则编译失败
Go 程序启动时只认 package main 里的 func main()。哪怕你把 main 函数写得再标准,只要它不在 main 包下,go build 就会报错:no Go files in current directory 或更隐晦的 cannot find package "main" —— 实际是找不到入口,不是路径问题。
常见错误现象:
- 把
main.go放进子目录(如cmd/myapp/main.go),但没用go run cmd/myapp,而是直接go run main.go,此时当前目录没main包,Go 会去查文件所在包名,发现是myapp就拒绝执行 - 误写成
package mainn或package Main(大小写敏感) - 同一目录下混了
package main和package utils的 .go 文件,go build直接报错:“cannot mix package main and package utils”
main函数签名不能改,参数和返回值都必须为空
func main() 是硬性约定,不是普通函数。加参数、加返回值、改名字,都会让编译器拒绝:
- 写成
func main(args []string)→ 报错:func main must have no arguments and no return values - 写成
func Main()(首字母大写)→ 不报错但不被识别为入口,程序静默退出(实际根本没运行) - 写成
func main() int→ 同样触发上面那条错误信息
如果真需要处理命令行参数,请用 os.Args 或 flag 包,而不是改 main 签名。
立即学习“go语言免费学习笔记(深入)”;
多个main包不能共存于一个模块构建中
一个 Go module 可以有多个 main 包,比如 cmd/a/main.go 和 cmd/b/main.go,但你不能用一条 go build 命令同时生成两个可执行文件。
-
go build ./...会失败,提示 “multiple main packages” - 正确做法是明确指定路径:
go build ./cmd/a和go build ./cmd/b分开执行 - 如果想一键构建多个,得靠 shell 脚本或 Makefile,Go 原生命令不支持
这跟其他语言“多个 main 类”的逻辑不同——Go 认为每个可执行文件对应一个独立的 main 包实例,不是多入口。
main函数结束 = 进程退出,defer 和 goroutine 容易被截断
main 函数返回后,进程立刻终止,不会等后台 goroutine 或未执行完的 defer。
- 写
go func() { time.Sleep(2 * time.Second); fmt.Println("done") }()在main末尾?大概率看不到输出 -
defer fmt.Println("cleanup")能执行,但若 defer 里启了 goroutine,它也可能被杀掉 - 真正可靠的退出方式是显式同步:用
sync.WaitGroup、context或os.Interrupt信号控制
这个行为不是 bug,是设计使然。Go 不保证 main 之外的并发生命周期,别指望它自动兜底。










