First, “web development” is a very broad term and might, therefore, mean a lot of things including server-side rendered HTML pages, JSON APIs, microservices, etc.

Second, let’s define what makes a programming language qualify for web development. (sorted by importance)

  • Ecosystem
    • Tooling
    • Libraries
    • Developer market
    • Success stories
  • Maintainability
    • Language design
    • Ecosystem consistency
  • Performance
    • Asynchronous execution for increased throughput
    • Low latency
    • Raw number-crunching performance
  • Infrastructure
    • Hosting and deployment
    • Memory usage and cost in general

So, let’s get ready to compare!

Ecosystem (it depends)

Both PHP and Go have created huge web-development ecosystems but they are focusing on different goals. PHP is usually rather about server-side rendered HTML pages and CMS systems while Go is rather about APIs, microservices and high-load systems.

  • Even though PHP is often used to build JSON serving APIs - it’s actually a very poor choice compared to Go for reasons described below.

  • Even though Go is sometimes successfully used for server-side HTML rendering - it’s ecosystem is not (yet?) as advanced as PHP’s in this regard.

Developer market (PHP)

PHP’s ecosystem had more time to gain more momentum meaning there’s still far more PHP developers than Go developers on the market right now. One might argue that Go developers are usually on a somewhat higher skill-level in general but I’ll let you decide for yourself.

Success stories

80% of the entire web is estimated to run PHP (2017) but that number is constantly fading in a 5-year long retrospection:

Go vs PHP - Google Trends

There are several success stories in Go’s portfolio and even a big list of businesses using Go worldwide.

Libraries

In terms of libraries, both Go (Awesome Go) and PHP (ziadoz/awesome-php) are quite rich. You’ll usually find everything you need for a typical web-based product.

Tooling (Go)

In terms of tooling, I’d give Go the lead. Go was built by Google with almost all tooling in mind during the design phase.

Testing (Go)

There are several 3rd-party testing libraries for PHP like PHPUnit, the rules aren’t dictated by the language though but by de-facto community standards.

In contrast, Go standardizes the way tests are written (unit tests, integration tests, .. etc.) by implementing it in the standard library and toolchain. This way all Go projects approach testing identically improving the consistency of the ecosystem.

It’s possible to write custom testing frameworks for Go, there even are frameworks extending Go’s built-in testing library like onsi/ginkgo and stretchr/testify.

It’s really a question of preferences but I personally like strict rules preserving consistency more. So Go is the way to go.

Benchmarking (Go)

The importance of benchmarking should not be underestimated. We constantly burn more compute-power than we actually need and the lack of standardized reliable benchmarking tools leads to an overall less efficient ecosystem.

Go allows all sorts of benchmarking out-of-the-box. You can even do micro-benchmarking (like what string concatenation method is the most efficient one).

PHP code, however, is not as easy to benchmark. The language never really focused on efficiency and most benchmarking is usually done on the application as a whole. The fact that PHP is not exactly self-sufficient and requires external services like a web-server makes benchmarking even more difficult.

Profiling (Go)

The pprof profiler is built-in to the Go language and its tool-chain out-of-the-box. This allows us to find and resolve bottlenecks in our application code.

Even though there are comparable tools for PHP like Xdebug - I’d still give Go the upper hand because it’s self-contained and therefore makes high-performance software easier to develop and profile.

Tracing (Go)

Go provides an execution tracer with a web-based GUI out-of-the-box. This tool allows us to investigate latency issues and runtime behavior:

  • How many goroutines and threads have there been and when?
  • How many system calls did our application do and when?
  • When were the garbage collection phases on what threads?
  • When and where was there any contention? .. etc.

There are some tracers for PHP but they seem to be less sophisticated. Again, when tracing a Go process - we’re tracing a self-contained binary and can, therefore, get more accurate results.

Maintainability (Go)

Maintainability is a very important factor in the realms of business software. Developers come and go but code-bases usually stay. The more consistent and minimalistic an ecosystem and language is - the less likely will you face maintainability problems.

I’ve often seen people rewrite entire PHP code-bases just because the guy who previously wrote it and left the company afterward used a different framework, which there are hundreds of (and you should feel lucky if it wasn’t a self-rolled one). In Go the standard library is so powerful and simple it’s used through the entire ecosystem and the “frameworks” approach is usually not common in Go.

Language design (Go)

In terms of language design Go is far superior. Go is strongly statically typed making Go code much easier to maintain and read. Any type-errors will be resolved at compile-time. PHP’s type hinting concept isn’t nearly as useful.

Also, Go is a minimalistic language with an orthogonal design while I’d call PHP a legacy monster. It all starts with the fact that PHP has 68 keywords while Go has only 25 and from that, you can sort of imagine how much simpler the Go language is in terms of design.

Go was also designed as a true general-purpose programming language which could be used to write any (long-lived) program while PHP is rather just about REQ-REP scripting.

For example, I’ve written an LL parser for a compiler in Go, I’ve written REST & GraphQL APIs in it, I’ve written WebSocket services in it, I’ve written CLI automation tools, even concurrent simulators just for fun. I couldn’t write most of this in pure PHP because of the language restrictions.

Performance (Go)

Go is designed with performance and efficiency in mind, PHP is not. Go is compiled down to an optimized system-native binary while PHP is interpreted dynamically which is much slower!

PHP 8 and 7.4 will finally get a Just-in-time (JIT) compiler but the V8 JavaScript engine which is used in Node.js had this for years (and I trust Google to have developed a way more sophisticated runtime than the PHP developer community will be able to pull off) and still loses to Go in both memory and CPU time consumption.

It’s simple: in computing, anything dynamic will always add overhead, no matter how many millions of dollars you throw at it.

Asynchronicity (Go)

In terms of asynchronicity and non-blocking execution Go is worlds ahead because it was designed to be non-blocking by nature.

PHP was originally a purely synchronous blocking language and only now do folks begin to realize how much compute power (and therefore money spent on infrastructure) they throw away by blocking on I/O operations and similar. The Swoole PHP framework is one of the attempt to keep PHP up to date and make it possible to write asynchronous PHP code but it’s stuck somewhere in the era of JavaScript ES5 approaching async code style with simple callbacks (which can become a nightmare).

Go, however, is inherently asynchronous even though Go code looks synchronous. In Go, there’s no Promise, no async/await, no Future, just stupid blocking code, yet when a goroutine executing this code blocks on a database query, an HTTP request or any other I/O operation - it will suspend itself and let other goroutines do their work (cooperative multitasking) avoiding blocking any system threads. All goroutines are multiplexed through a runtime-internal thread pool making them use all CPU cores available by default.

Concurrency (Go)

PHP achieves concurrency by executing scripts on different threads, but this can sometimes be a problem because those scripts are isolated from each other and can’t share any state. It sure reduces code complexity but it’s also far less efficient.

Go on the other hand allows writing actual concurrent code and safely communicating between goroutine through channels. You can even go down to the level of atomics if you really need that multi-core performance.

Goroutines are a mix of coroutines and lightweight threads, there’s nothing comparable in PHP because it’s fundamentally more restricted.

Don’t get me wrong, PHP’s technical restrictions may be a good thing in terms of code complexity, especially when the people using it don’t know the basics of multi-threaded programming yet, but if you really need optimal multi-core performance you’ll probably need to say goodbye to PHP. Also, you normally don’t do much multi-threaded programming in Go either, you just let libraries do it safely for you while you just write the business logic but the cool thing is that you don’t need to leave the boundaries of the language in order to be able to write concurrent code.

Memory usage (Go)

Due to the fact that Go is statically compiled down to binary code, it naturally uses much fewer memory resources than dynamic PHP scripts.

Infrastructure

Go binaries are simple self-sufficient binary files while PHP scripts require an external runtime environment.

Hosting and deployment (it depends)

I’d say PHP wins when it comes to simple hosting because there’s plenty of hosting solutions for PHP on the market while Go requires you to basically run a virtual private server. Even though containerization has simplified deployment - Go produces just a single self-sufficient binary file which you just run on the server with no external dependencies whatsoever while PHP usually requires a complete setup including a web-server, a process manager, etc.

Bonuses (Go)

Go has a few bonuses like the fact that you can do closed-source software development which is far more difficult to achieve with PHP.

Conclusion

I used PHP for years and I wouldn’t like to return since I know Go which ..

  • allows me to read other people’s code without burning my eyes out thanks to gofmt and strong static typing.
  • allows me to keep code clean, maintainable and easily refactorable.
  • allows me to write almost anything I want.
  • allows me to make more out of the CPU/memory I get.

Some see Go as complementary to PHP but I personally disagree and rather see PHP as an obsolete piece of technology that’s just here because it gained a lot of momentum once which is slowly fading away now. From a technical point of view, PHP is severely outdated. I think even for CMS systems we will see a slow transition from PHP to headless CMS written in Go headed by PWAs/SPAs.

I really see no reason to use PHP (5.x, 7.x and the upcoming 8.x) in 2020+ for any new codebase. In scripting and prototyping, Python will probably take the throne. In APIs and similar Go will take the throne. Functional languages like Elixir will also gain more popularity over time. I don’t see a bright future for PHP though.

Again, don’t get me wrong, it’s not like PHP is going to die in 2022 or 2023, it’ll probably never die out completely like any language that gained that much momentum but as engineers we should be aware of our tools and understand what problems they might cause to our lives and businesses and whether or not we’re willing to deal with them.