You are on page 1of 8

3.6.

2018 Moving from PHP to Go and learning to love them both

José Carlos Chávez
Software Engineer @Typeform. Wine lover and Llama ambassador
Feb 27 · 9 min read

Moving from PHP to Go and learning to
love them both

Irrelevant picture for the post just to discourage you to buy ivory

A few days ago I read this post and remembered mixed feeling and
some “heated” discussions that I had with my colleagues about Go. At
that time I was just starting out with Go after working primarily with
PHP for the previous 5 years.

Following from a year working with both languages on a daily basis I


am in a good position to share my personal experience in this journey. I
believe explaining my initial thoughts and how they changed across
time might help others in a similar situation (moving to Go or thinking
about it) to get an insight into what you can face during the process and
some advice on to make more informed decisions (in case you want to
quit or keep going).

Go is a great language, so is PHP, but in my opinion it is not the most


friendly host language albeit the massive documentation and tutorials
all around the internet (playground is something every single

https://medium.com/devthoughts/moving-from-php-to-go-and-learning-to-love-them-both-45847de0266c 1/9
3.6.2018 Moving from PHP to Go and learning to love them both

programming language should o cially o er and support). On top of


that you will nd a strong opinionated community, usually technically
well educated. I have worked with PHP, Python and JS and I’ve never
felt as much pressure to write idiomatic code as when working with Go
(which is a good thing in my opinion) maybe because go was created
with a style guide from the beginning whereas other languages built
their guides on the y.

The beginnings
It is impossible not to draw comparisons when moving from one
language to another so my very rst impressions about Go were not as
tolerant as they are now:

• Highly imperative: Even though you can write declarative code,


by design Go is highly imperative.

• Strong typing: Go is a strongly typed language and, while I did


not like the fact that I had to explicitly state the type of the
returned values every time, in the end I found it more convenient
as I could catch problems before they arose.

• Interface implementation is not explicit: I considered this a


disadvantage at the beginning because I thought people could
misuse one struct instead of another just because it ful lls the
signature (which does not always re ect an intention to ful ll the
contract). My experience now is that this is very unlikely to
happen, because in a single purpose application there is not much
room for confusion. It also bothered me that right after an
interface changed you had to chase down all the structs that were
implementing it in order to make them ful ll the contract again
but this is probably something IDE related.

• Capitalization for package visibility: Personally I dislike the


inconsistency of some objects/functions having names starting
with an uppercase letter and others with a lowercase one.

• Struct annotations for marshalling/unmarshalling make it


feel like the object is coupled to implementation details: I still
think this is true.

• No default values for function/methods’ arguments: This is


true, but if your function requires a lot of optional parameters

https://medium.com/devthoughts/moving-from-php-to-go-and-learning-to-love-them-both-45847de0266c 2/9
3.6.2018 Moving from PHP to Go and learning to love them both

there is probably something wrong with it. Still, in situations


where you really need to pass optional arguments, you can use
zero value check arguments, pointer arguments or variadic
function arguments.

• if err !=nil {...} everywhere: This seems odd at rst but at


some point you realize it is the same as doing try/catch for
exceptions. The main di erence -in feeling- is that you repeat this
check many times whereas with try/catch you can treat a big block
and handle di erent exceptions in di erent ways, however this
sometimes means you lose the context on which exception could
be thrown by which method:

<?php

try {
functionA();
functionB();
} catch (ExceptionTypeC $e) {
...
} catch (ExceptionTypeD $e) {
...
}

If you really want it to understand where the errors have come from,
you might need to do something like

<?php
try {
functionA();
} catch (ExceptionTypeC $e) {
...
}

try {
functionB();
} catch (ExceptionTypeD $e) {
...
}

Which is essentially

https://medium.com/devthoughts/moving-from-php-to-go-and-learning-to-love-them-both-45847de0266c 3/9
3.6.2018 Moving from PHP to Go and learning to love them both

err := functionA()
if err != nil {
...
}

err = functionB()
if err != nil {
...
}

• Array functions and array manipulation in general: Functions


like array_map or array_filter are things I missed, but you can
still do it as described here.

• There’s no ternary (?:) operator: I really missed this as I nd it


more readable and I still don’t like the idiomatic suggestion of
assigning the default value rst and then overriding it later
depending on conditions.

• Versioning and vendoring: This is probably the thing I missed


the most. Using external dependencies in Go means that you have
to choose between including all the code used in a library and
using the master of the repository. Both approaches seem
inconvenient to me but between them I prefer the vendoring one. I
don’t like the massive PRs including vendored les that are all over
repositories in github using this approach though.

On the other hand, what I liked about Go from the very beginning was:

• Go does not have inheritance (thank God for that): Instead you
have to use some other techniques such as embedded objects

which look more like composition to me. I have heard many


times about how is inheritance one of the biggest bene ts of OOP.
In my opinion that is a very awed claim.

• Ability to return multiple values: I really missed this in C and


PHP. Of course you can return an array or list of values in PHP but
that looks very odd and not idiomatic. Also might require some
type checking in runtime.

• Strong typing: This is an area where PHP is improving; PHP7


includes return types and I am really thankful for this. PHP 7.1
even includes a nullable return type. Still, the check is in runtime

https://medium.com/devthoughts/moving-from-php-to-go-and-learning-to-love-them-both-45847de0266c 4/9
3.6.2018 Moving from PHP to Go and learning to love them both

not in compile time, and, although there are tools such as phpstan
that help you overcome this limitation, it is really nice that in Go it
is a built in feature of the language.

• map/list with types: This is something I really missed in PHP —


there is no way to declare a map[string]Something forcing you to
do runtime checks for array elements.

• Go compiler forces you to drop unused functions, variables


and imports: At the start this was a pain (while hacking around
with some examples), but in a space of a few days I really found it
convenient as make the code simpler and clearer.

• Circular dependencies are avoided:Even if the language allows


you to do it I highly recommend avoid it.

Despite what I like about the Go language, I would like to mention a


couple of things I did not like from what is described as idiomatic go:

• I don’t agree with the one letter variable , I think over the past
40 years the software industry has agreed that developers spend
much more time reading code than actually writing it, meaning
that the code should be written thinking about readers. I don't
want to have to remember that r most likely stands for Request

and w for Writer .

• Coupling is sometimes associated with idiomatic go, it’s easy to


nd examples in which business logic is strongly coupled with
infrastructure or implementation details. Personally I try, even
when writing Go, to decouple my code as much as possible with
the help of DDD and CQRS, and, I don’t think Go was ever
intended to be used in such a way, it’s totally doable. Good code
principles apply when working with any language and Go should
not be an exception.

My opinions about the Ivan Jaros’ post
I would really like to share my opinions about the post that spurred me
on to create this blog post, bear in mind my opinions are based on my
experience working with Go and PHP.

Go was born out of frustration with existing languages and


environments for systems programming.

https://medium.com/devthoughts/moving-from-php-to-go-and-learning-to-love-them-both-45847de0266c 5/9
3.6.2018 Moving from PHP to Go and learning to love them both

I can understand the pain. I am a Maths student, and for my studies I’ve
been working with C for the past 10 months. I must confess that every
time I nished something I told myself: “I could write this in half of the
time with Go”. Even more I pair programmed with a colleague in a kata
some months ago and we really missed Go’s simplicity and syntax over
C.

In addition, something important to mention (thanks Marc) is that


what Go understands as a system is not the same as what C
understands as a system. Go includes features that makes it di erent
from classical systems language, so we have to understand the system
as a cloud system, made of microservices that communicate each other,
so systems for the purposes of writing Go are one layer up from the OS.

Go’s simplicity works very well in your favour if you are creating a
single purpose low-level library or application that is small in size and
purpose.

Go has been designed for simple single purpose applications (aka


microservices) and that is not a defect but a feature. I like the
“monolith rst” approach and I’d certainly not write a monolith using
Go.

But another point I want to make is that in Go, you absolutely, under no
circumstances, should be even trying to reuse code or de ne an
interface. Sooner or later, it will bite you in the ass. […] For example,
Go would be perfect language to use for a micro service whose purpose
is to receive events from event store in event sourced architecture and
normalize them into consumable messages for the message broker to
distribute to interested 3rd parties. Now imagine a microservice where
you have to connect to a database, fetch some results, perform some
business logic and send some messages out.

At Typeform we use Go not only for low level tasks/tools but also for
writing microservices using DDD and CQRS. Go has proven compatible
with this and it also made me realize that sometimes we abuse of
classes in order to make the so called Domain objects. In addition, one
feature that I love in Go (and from C actually) is how easy is create
custom types and associate them with some behaviour.

https://medium.com/devthoughts/moving-from-php-to-go-and-learning-to-love-them-both-45847de0266c 6/9
3.6.2018 Moving from PHP to Go and learning to love them both

Something worth to mention here is how we understand the concept of


microservice. I recommend this talk from Udi Dahan about what is and
what is not a microservice.

When it comes to Go, spaghetti code is what you want to write. Go has
composition instead of inheritance and polymorphism but you will be
running in circles if you’ll try to create any re-usable code. You will fail
badly.

It is entirely possible to write reusable code in Go you just have to


consider that if it will be reusable it is better to ship it in a di erent
package.But remember, as the author said before, Go is designed for
single purpose applications, how often do you expect to reuse your
code if that’s the case?

There is a reason why Go is lacking “real” frameworks. Sure, you have


Go Kit, Micro, Gin and few others but they will never be able to come
even close to Symfony, Laravel, RoR, Django or Flask.

You don’t need a framework for Go applications as they have a single


purpose, it is not very likely you will nd a Go application routing,
dispatching events, serving assets and rendering html all at the same
time. Microservices do very speci c things and for doing speci c things
you don’t need a full-stack framework like Rails or Symfony. These kind
of frameworks are meant to write monoliths and Go is not intended for
that.

Conclusions
After some months working with Go, some of my dislikes for the
language became my likes, so right now if I am asked about what do I
prefer I would reply: It depends.

• I really believe in the monolith rst approach and if I were to write


a monolith I would not write it in Go because it is not meant for
this.

• I would be perfectly happy to write a microservice in PHP unless


the implementation required certain features like high availability,
concurrency, async tasks, multithreading, etc. If that was the case I
would de nitely use Go, not because these things are not possible
in PHP (although concurrency is de nitely not possible in PHP

https://medium.com/devthoughts/moving-from-php-to-go-and-learning-to-love-them-both-45847de0266c 7/9
3.6.2018 Moving from PHP to Go and learning to love them both

SAPI), but because it is more natural in Go, because of the ease of


sharing data across channels (I recently saw this talk where
@adrianco shows how to send channels over channels) over the
complicated restrictive model of pthreads.

https://medium.com/devthoughts/moving-from-php-to-go-and-learning-to-love-them-both-45847de0266c 8/9

You might also like