PHP到Go的过渡本质是执行模型、错误处理、依赖管理及工程习惯的全面切换,需重视显式错误检查、并发安全、手动依赖管理和上下文控制等“PHP默认有而Go必须显式做”的事。
php 到 golang 不是语法替换,而是执行模型、错误处理、依赖管理、甚至工程习惯的切换。你写完第一个 main.go 并跑通 http.HandleFunc,不等于过渡完成;真正卡住人的,是那些“PHP 里默认有,Go 里必须显式做”的事。
别直接重写旧项目,先写一个能跑通的 CLI 工具
很多人一上来就想把 laravel 接口迁成 gin,结果卡在中间件链、session、orm 映射上,两周没出可运行代码。实际更高效的做法是:用 go 写一个和现有 php 项目协同的小工具,比如:
- 读取 PHP 生成的
config.php(用go-php或手动解析)并转成 JSON 配置文件 - 批量重命名上传目录里的文件,按 PHP 里约定的规则加时间戳前缀
- 调用 PHP 写的老接口(
curl或exec.Command),但用 Go 做超时控制、重试、日志结构化
这类任务不涉及路由、模板、数据库抽象层,能快速验证你对 os、io、encoding/json、net/http 的掌握程度,也避免陷入“怎么模拟 $_SESSION”这种伪需求。
变量声明和错误处理不能省略
PHP 的 $data = get_user(); 在 Go 里不是简单改成 data := get_user() —— 如果 get_user() 返回 (User, error),你必须立刻检查 error。Go 不允许忽略返回值,尤其错误。
常见错误现象:panic: runtime error: invalid memory address or nil pointer dereference,往往是因为你写了 user.Name 却没检查 user 是否为 nil,而 PHP 的 $user->name 在 $user 为 null 时只报 Notice(且常被关闭)。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 所有函数返回
error时,用if err != nil包裹后续逻辑,不要只log.Fatal(err)—— 生产环境要区分网络超时、DB 连接失败、参数校验失败 - 声明变量不用
var开头,但类型必须明确:userID int64而非userID := 123(后者推导为int,和 PHP 的整数语义不同) - 切片初始化别漏
make:items := make([]string, 0, 10),而不是items := []string{}(后者底层可能反复扩容)
HTTP 服务别照搬 PHP 的“每个请求一个进程”思维
PHP-FPM 默认每请求 fork 一个进程,天然隔离;Go 的 http.Serve 是长连接 + goroutine 复用,全局变量、未同步的 map、复用的 struct 字段都可能引发并发 bug。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
典型坑点:
- 在 handler 里改全局配置变量(如
Config.Timeout),其他请求会立刻看到——PHP 里不可能发生 - 用
map[string]string当缓存但没加sync.RWMutex,压测时 panic - 把
*http.Request存到结构体字段里跨 goroutine 使用,导致 header 读取混乱或 body 已 close
正确做法:handler 函数内只用局部变量;需要共享状态时,用 context.Context 传参,或用带锁的结构体封装状态。
没有“自动加载”,import 和 vendor 必须手动理清
PHP 的 autoload 让你可以随便 new UserRepo();Go 没有类路径,也没有运行时动态加载。所有依赖必须显式 import,且路径必须精确匹配模块名。
容易踩的坑:
-
import "github.com/xxx/lib"但本地go.mod里写的是module github.com/yyy/lib→ 编译报错unknown import path - 用
go get安装包却没加版本(如go get github.com/gin-gonic/gin),下次go build可能拉到不兼容的 v2 - 误以为
vendor/是可选的,上线时没go mod vendor,导致 CI 环境找不到私有 Git 仓库包
建议:初始化项目就定死 go mod init myapp,所有第三方包用 go get xxx@v1.9.0 显式指定版本,CI 流程中强制 go mod verify。
goroutine 就会的,得在真实压测和线上问题里反复撞墙才能建立直觉。


















