by waynerad | 2025-06-05 23:50:28+00:00
I've been programming in PHP since 2002 and Go since 2011. At work I work primarily with two large PHP codebases, 1 about ~half a million lines of code, and the other about ~3 million lines of code. I'm porting PHP code to Go and writing some new code, like cron jobs, in Go. There's about 55,000 lines of Go code at this point.

What I have learned in this time is: Go is a very good, very high quality, very well designed language. PHP is a terrible, terrible, terrible language -- at least if your mission is creating highly reliable software. If your goal is rapid prototyping of the visual appearance of a webpage, PHP is good for that -- that's what it was originally invented for, back in the 1990s, and it's still the best language for that specific use case.

In PHP, if you are looking at a line of code, it's impossible to tell what happens if an error occurs. There's an error_reporting level that can be changed anywhere else in the codebase at any time. So an error might be thrown in the user's face, or not -- depending on the error_reporting level and what the error is. This can also interact with output buffering. (I guess if the "@" sign is present, at least then you know output of an error message is suppressed.) There's a error_handler function that could be set. Oh but it gets worse! Even if you have the entire codebase and can scour every line of code, and trace every possible execution path, you still can't tell what will happen if an error occurs at the line of code you are looking at -- because there are php.ini settings that come into play!

This is without even mentioning the try/catch exception handling system, which PHP also has, and that you think is such a good thing. So if an error happens on the line you are looking at, execution may switch to somewhere above you in the call stack. But (at least in theory) if you have the complete source code, you can figure out all the places where that might be.

This is an absolute nightmare if you care about reliability. The worst thing you could possibly have in a programming language if you care about reliability is to be unable to tell what happens when an error occurs and reason about the program's behavior.

Contrast this with Go. In Go, I can know what happens if an error occurs because it's right there. There's an "if err != nil {..." block that tells me exactly what happens.

By porting code to Go, I've been able to increase the reliability tremendously. The thing about go, is that using Go doesn't automatically give you reliability -- you have to learn the techniques and tools in Go that give you reliability. But once you do that, the quality of software you can produce is vastly higher.

I've spent the last decade or so learning this. Learning how to structure the code to make maximum use of the compiler's static type checking to catch errors. Making use of the static analysis tools that catch errors. Using a combination of errcheck and staticcheck (mentioned elsewhere in this discussion), you can guarantee every err return value is actually checked and handled. So the oft-cited language flaw of Go allowing you to forget to handle errors becomes a non-issue. Go has built-in support for unit tests and the excellent polymorphism system makes tests easier to make than in PHP. And, getting back to the topic at hand, in Go, I created my own system for handling the err values that get returned so junk errors created by hackers trying to find security vulnerabilities on our server get filtered out, while actual errors that I need to fix get logged and brought swiftly to my attention. Can you do something similar in PHP? In theory, perhaps, but we are to afraid of breaking things to try to massively refactor our ~2 million lines of PHP code in order to do that. So we have various log files and database entries that get clogged with errors, and sometimes we notice errors that we need to fix, but usually we don't. Usually we don't know anything is wrong until we get customer complaints on the Help Desk.

Anyway, I'm glad the Go team rejected the idea of changing Go's error handling. Is Go's error handling verbose, tedious, and repetitive? Yes. But it's also unambiguous and gives you total control over how your program responds when an error occurs, which is exactly what you want if you want to write software with the maximum reliability.

Don't just take my word for it. Notice how lots of "cloud infrastructure" is written in Go. Kubernetes is written in Go, Docker is written in Go, Terraform is written in Go, etc.

Yes, I know some people, like Facebook, have managed to write decently reliable code in PHP. But I suspect Facebook has thrown massive amounts of dollars and people at the problem. Various other PHP projects, like certain website creation systems that shall not be named, have a reputation for being buggy.

Sorry, I couldn't let you say PHP has better error handling without a response. It may be "better" for having more compact, prettier looking code. But it's not better for writing actually reliable software. If you want to write actually reliable software, Go is way better.