co un() 必须在php脚本最外层且仅调用一次,是协程调度器唯一入口;它初始化事件循环并接管主线程,内部需完成全部协程逻辑,外部代码在其后执行;cli必须显式调用,web服务中已隐式存在,且co::set()须在其回调开头、首个go()前调用。

Co un() 必须在顶层调用,不能嵌套或重复执行
Co
un() 是协程调度器的唯一入口,它会初始化事件循环并接管当前线程控制权。一旦执行,就进入协程上下文,后续所有协程操作(如 go()、co::sleep())都必须在这个环境中进行。
常见错误是把它写在某个函数内部、或者在已处于协程中再次调用 —— 这会导致 Fatal error: Uncaught SwooleException: Co
un() can only be called once 或直接崩溃。
- ✅ 正确位置:PHP 脚本最外层(非函数、非类方法、非其他协程回调内)
- ❌ 错误位置:
go()回调里、Co un()已运行后的任意位置、HTTP 服务器的 handle 回调中(除非你明确要再启一个独立调度器,但通常不需要) - ⚠️ 注意:Swoole 的 HTTP/WS 服务器启动后,每个请求回调默认已在协程上下文中,此时再调用
Co un()属于冗余且非法
Co un() 内必须完成全部协程逻辑,外部代码不等待它
Co
un() 是阻塞调用,但它只阻塞到其内部所有协程(包括 go() 创建的)全部结束。而它本身所在的主线程,不会“等”它 —— 实际上,Co
un() 就是主线程的主流程。
典型误区是以为可以在 Co
un() 外继续写业务逻辑,比如:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
Co
un(function () {
go(function () { echo "hello"; });
});
echo "world"; // 这行会在所有协程结束后才执行,不是“并发”
- ✅ 正确理解:
Co un()是整个协程程序的生命周期边界,所有需要并发/异步执行的代码,都应放在它的回调里 - ❌ 错误认知:把它当“后台线程启动器”,认为外面的代码能和它并行跑 —— PHP 主线程只有一个,
Co un()启动后,主线程就归它管了 - ? 补充:如果你真需要“启动协程后立刻返回做别的事”,那应该用
go()(它自动处理环境),而不是Co un()
CLI 场景下 Co un() 是必需的,Web 服务中往往隐式存在
在命令行脚本(CLI)中,没有框架或服务器帮你初始化协程环境,Co
un() 是显式开启协程的唯一方式。但在 Swoole HTTP/WS 服务器中,$server->start() 内部已自动创建协程容器,每个请求回调天然运行在协程中。
- ✅ CLI 脚本必须写:
Co un(function () { /* your go() calls here */ }); - ✅ Web 服务中一般不用写:
$server->handle('/', function ($req, $res) { go(...); });—— 此时go()可直接用 - ⚠️ 混淆点:有人在 Web 服务里又套一层
Co un(),结果报Co::set() must be called in coroutine或调度异常 —— 因为已经身处协程中,再进一次Co un()会破坏上下文
Co un() 前不能调 Co::set(),但必须在第一个 go() 前调
Co::set() 设置协程钩子(如 SWOOLE_HOOK_TCP)必须在协程上下文中生效,但它又不能在 Co
un() 外调用 —— 所以唯一合法位置,就是 Co
un() 的回调函数开头、任何 go() 之前。
- ✅ 正确顺序:
Co un(function () { Co::set(['hook_flags' => SWOOLE_HOOK_ALL]); go(...); go(...); }); - ❌ 错误顺序1:文件顶部就写
Co::set()→ 报Invalid argument: Co::set() must be called in coroutine - ❌ 错误顺序2:把
Co::set()放在某个go()回调里 → 只对该协程生效,其他协程没被 Hook,导致file_get_contents()等仍为同步阻塞
这个时机差之毫厘,就会让协程“看起来在跑”,实则 I/O 还是同步卡死 —— 是线上性能问题最隐蔽的来源之一。










