net.listen("unix") 是两个独立 go 进程间 ipc 的最常用、最可靠方式,支持跨语言、高性能、带连接管理与超时,需注意 socket 路径权限、旧文件清理、读写 deadline 设置及路径长度限制。
net.listen("unix") 是两个 go 进程间建立 ipc 的最常用、最可靠方式。go 没有“打开 ipc”这种抽象操作,必须明确选择底层机制:unix domain socket(推荐)、os.pipe(仅限父子进程)、或共享内存(需 syscall.mmap + 同步原语)。别指望像 shell 那样写 cmd1 | cmd2 就自动 ipc。
用 net.Listen("unix") 建立跨进程通信
这是生产环境首选,支持任意两个独立 Go 进程(甚至跨语言),性能接近内存拷贝,且天然支持连接管理与超时。
- 服务端必须先创建 socket 文件路径的父目录,并设可写权限:
os.MkdirAll(filepath.Dir(sockPath), 0755) - 监听后立即清理旧 socket 文件:
os.Remove(sockPath)(忽略os.IsNotExist错误) - 务必对每个
net.Conn设置读写 deadline:conn.SetReadDeadline(time.Now().Add(5 * time.Second)),否则客户端异常退出会导致服务端永久阻塞 - socket 路径长度不能超过
UNIX_PATH_MAX(通常 108 字节),建议控制在 64 字以内,如/tmp/myapp.sock - 客户端 connect 失败若报
connect: connection refused,大概率是服务端还没完成Listen或Accept,不要直接 panic,应加重试逻辑
os.Pipe 只适用于父子进程,且极易卡死
它返回一对 *os.File,本质是内核 pipe fd,但只在 fork 后的父子进程间有效。不是通用 IPC,更不是 channel。
- 父进程调用
os.Pipe()后,fork前必须关闭子进程不需要的句柄:子进程关readEnd,父进程关writeEnd;漏关一个写端,读端就永远等不到 EOF - 用
exec.Command启子进程时,优先走cmd.StdoutPipe(),它内部已帮你隔离 fd;别自己手动传os.Pipe的文件描述符 - 多级管道(如
ls | grep | awk)几乎没人手撸 —— 直接用exec.Command("sh", "-c", `ls | grep go`),省事且健壮 - 子进程退出后,父进程必须调
cmd.Wait()获取*exec.ExitError,靠这个判断是否异常终止,不能只看err != nil
别把 channel 当 IPC,也别把 sync.Mutex 跨进程用
channel 是 goroutine 间通信,生命周期绑定于当前进程;sync.Mutex 是线程级同步原语,两个进程的地址空间完全隔离,互不感知。
- 协程链式处理(gen → filter → print)中,
close(ch)必须由**最后一个发送方**执行,且只能 close 一次;接收方绝不能 close,否则下游for range ch会死锁 - 想让多个进程共享一块内存?得用
syscall.MemfdCreate+syscall.Mmap,再配 POSIX 信号量(sem_open)或原子操作(atomic.CompareAndSwapUint32)做同步 —— Go 标准库不封装这些,要 cgo 或 x/sys/unix - 把
sync.Mutex放进 mmap 区域?会 panic。它的字段含 runtime 内部指针,跨进程无效
Unix domain socket 的难点不在 listen 或 dial,而在连接生命周期管理:客户端断连不通知、服务端未设 deadline、路径权限错位、旧 socket 文件残留 —— 这些才是线上 IPC 故障的真正来源。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











