Switching from PHP to Go : top 10 differences

Wacław The Developer
5 min readDec 23, 2021

Hi everybody! Go (golang) becomes more and more popular in PHP devs community. Today I want to describe top fundamental differences for newcomers and remind people who are learning Go now.

Photo by Isabella and Zsa Fischer on Unsplash

Go program is not a script

The first i need to mention is that Go is a compilable language. The result of the compilation will be binary executable. Instead of it, PHP file is the script that need to be translated and executed (php has acomplicated system of caches, opcode caches, byte code generation, etc). If we want to get an answer from webpage/api endpoint — the chain of execution will be next:

PHP script: request → Webserver → php-fcgi/fpm/module (*.php file→php engine)→ response

Go app: request → Go App →response

This provides very good performance in comparison with PHP (it can be it tens of times faster, you can google the benchmarks)

You should take care of types

PHP is dynamic typed language. Go is staticaly. So, for PHP it is ok to execute that:

$a = 1;
$b = “2”;
print($a+$b);
// output will be 3

It is because PHP automatically handles the data types.

If you are trying to do the same in Go

a := 1
b := "2"
println(a + b)

The compiler will reject that code

./main.go:6:12: invalid operation: a + b (mismatched types int and string)Compilation finished with exit code 2

Statically typed languages allow us to avoid bugs (most of IDEs will warn us that type is wrong for function or another part of code) and significantly increase the performance.

Your vars can live after end of request handling

If you use the scripts — you keep in mind that variables will disappear after the response to the client. But Go server will clean the variable that was created in a body of the handler. Other words, if you will assign some value to a global-accessible variable -this variable will hold this variable until Go app will be restarted or other handlers will modify that variable. For example:

var n = 0

func main() {
http.HandleFunc("/", CounterServer)
http.ListenAndServe(":8080", nil)
}

func CounterServer(w http.ResponseWriter, r *http.Request) {
n++
fmt.Fprintf(w, "It was request number %d", n)
}

Anyway, this example is a bad parctice, because of race condition or bottleneck in case of a using mutex. Don`t use global vars

Pointers and references

Go has ability to operate with address in memory, not the data in memory. The address of var can be used as a pointer. For example:

func main() {
var n int

var pointerToVar *int
pointerToVar = &n

n = 0
incrementMyVar(pointerToVar)
print(n) //output will be 1
}

func incrementMyVar(n *int) {
*n++
}

Goroutines

PHP has some kind of multithreading since PHP8.1 — Fibers (25 Nov 2021).

In go you can call any function in asyncronious mode. To do that — just call the function like that:

func main() {
go function(1)
go function(2)
go function(3)
time.Sleep(time.Second)
}

func function(number int) {
println(number)
}

Functions may return more than one variable

Functions in Go can return multiple values. For example:

func main() {
a, b, c := getNumbers()
println(a)
println(b)
println(c)
}

func getNumbers() (int, int, int) {
return 1, 2, 3
}

Interfaces and methods are not the same things from OOP languages

In Go we have 4basic things. Structure, Interface, Function, Method.

Structure holds the data something like that:

type Person struct {
name string
lastname string
}

Function was declared this way:

func main() {
nick := Person{
name: "Nick",
lastname: "Doe",
}
fmt.Println(nick)
}

But method is the function, that will apply on structure:

func (p Person) PrintData() {
fmt.Printf("Hello, %s %s\n", p.name, p.lastname)
}

Usage:

nick := Person{
name: "Nick",
lastname: "Doe",
}
nick.PrintData()

So, let’s see what interface is: interface is the set of signatures of methods, that you are required to implement to have ability to use your structure by interface name. To be clear:

func main() {
var cat, parrot Pet
cat = Cat{
name: "Jack",
tailSize: 10,
}
parrot = Parrot{
name: "Tom",
color: "Green",
}
DescribeAll(cat, parrot)
}

func DescribeAll(first Pet, second Pet) {
first.Describe()
second.Describe()
}

type Cat struct {
name string
tailSize int
}

type Parrot struct {
name string
color string
}

type Pet interface {
Describe()
}

func (p Cat) Describe() {
fmt.Printf("It is cat with name:%s and %d tail size\n", p.name, p.name, p.tailSize)
}

func (p Parrot) Describe() {
fmt.Printf("It is parrot with name:%s and %s colored\n", p.name, p.name, p.color)
}

Error handling

Go doesn’t have the Exceptions. We are using the checks for error after most valuable functions calls. This approach allows to provide more speed for execution and decrease side-effects. Example:

func main() {
if err := sayHello(""); err != nil {
panic(err)
}

}

func sayHello(name string) error {
if name == "" {
return errors.New("the name is empty")
}
fmt.Printf("Hello, %s", name)
return nil
}
//Output: panic: the name is empty

Slices and arrays

Arrays in Go have fixed size. For example, we can create this array:

var arr = [3]int{1, 2, 3}

But how to work with dynamic sets of data?

There is something called slice. Slice does not store data, just points to sections of array.

This slice points at range of arr (0–1 element):

var slice = arr[0:2]
fmt.Println(slice)
//Output: [1 2]

If you want from slice to handle your data automatically — it is can be done easily without creating an array.

var slice []int
slice = append(slice, 1, 2, 3)
fmt.Println(slice)

Classes, Access modifiers

As I mentioned before, Go is not object-oriented language. So, there are no such things as classes or access modifiers. More than that. I (and many people) advise you to try building the architecture that you need in your project. It is mistake to copy Laravel architecture to Go. So, you can use packages to separate logic. Packages are almost the same as Java packages and look like namespaces in PHP. To hide the variables and function (for example internal logic) — you just need to name it starting with lowercase. Overwise — it will be accessible from other packages. Example:

package printer//Not visible from main.go
const message = "hello world"
//Only one thing that visible from main.go
func
PrintMessage() {
print(getMessage())
}
//Not visible from main.go
func getMessage() string{
return message
}

Conclusion:

Go language is not a regular language. It’s simplicity and compilability allow to serve tens times more request per seconds than script languages. To understand Go deeper — I advise you to reads all of the sections in the official tour. Also, be free to try playground — a place to try your code while you will study.

--

--