Cover Photo

Introduction to Go for PHP Developers

Profile Picture
Andrew Davis
Jul. 18, 2018 • 9m
go
php
tips

Recently, I started working on an internal CLI app for my team at work. My main programming language of choice is PHP, but I wanted to create this program in a language that could run on any platform without having to have an interpreter already installed. I also wanted the app to be self contained in a single binary for easy distribution and installation. I downloaded Go and was pleasantly surprised at how easy to learn the language is and how productive I got with it in a short amount of time. Go’s procedural programming model really clicked with my PHP brain and I was able to get this app up and running quickly. There are some notable differences with PHP though, so I want to share them for any other PHP developer who wants to learn Go in the future.

Installation

MacOS

I use a Mac so I installed Go using Homebrew: brew install go. If you don’t have Homebrew on your Mac, I highly recommend using it.

Windows & Linux

The Go website has downloads for each OS, including a walk-through installer for Windows that makes the installation easy.

Getting Started

In Go, all source code for each Go project is stored under a single directory called the GOPATH. By default, the GOPATH is set to go in your home folder, e.g. /Users/andrewdavis/go. In the GOPATH, there is a bin directory and a src directory. The bin directory holds any binaries you download as dependencies. You will want to add the bin folder to your PATH environment variable. You can do so in your terminal’s .bashrc/.zshrc file with export PATH=$PATH:$(go env GOPATH)/bin. To start learning Go, you can download the Tour of Go program by running the following in your terminal go get golang.org/x/tour/gotour. go get downloads the source code and binary for a third party dependency using the provided path. Now, you can run gotour in your terminal and it will start a web server and point your browser to it.

To create a project, make a directory under src in your GOPATH: mkdir -p $GOPATH/src/helloworld. Open that folder cd $GOPATH/src/helloworld and create a file called main, touch main.go. In that file, put the following:

package main

import "fmt"

func main() {
  fmt.Println("Hello world!")
}

The starting point for all Go programs is the main function in the main package. Next, you can run go run main.go to run the program. You can also run go install and the program will be compiled and put in the bin directory so you can execute helloworld in your terminal and it will run your code.

Major Differences from PHP

Now that you have a project set up, you can start exploring the different Go features. One of the first things you will notice is that semi-colons are not required in Go. The end of a statement is detected by a new line. Here are some more differences that took me some time to understand:

Variables

Go is a statically and strongly typed language so every variable has a type assigned to it. Variables in functions are assigned using the := operator and this operator will automatically set the variable type for you: name := "Andrew" // name is now a string. To create a variable without setting any data in it or to create one outside of a function you have to use the var keyword: var name string.

If statements

If statements work the same as they do in PHP, however they don’t have to use parentheses around the boolean check. The difference confused me at first when reading Go code. However, I think it makes the code a little easier to read.

package main

import "fmt"

func main() {
  value := false
  if value {
    fmt.Println("Value is true")
  } else {
    fmt.Println("Value is false")
  }
}

Packages vs Namespaces

Go uses the term package to namespace it’s content. If you have a folder called controllers in your Go code, each file in that folder would start with package controllers. To import controllers from another package, you would write import “helloworld/controllers”. Anything in your package that has a name that starts with a capital letter can be used in another package. If you have a function named, func HelloWorld() in controllers, you would then be able to call controllers.HelloWorld() to run the function once controllers is imported. Anything that does not start with a capital letter can only be used from the same package. No need for private or public!

Strings

In Go, all strings must be surrounded by double quotes. A single quoted value in Go is for a rune (a single Unicode code point). By habit, I type my strings with single quotes since that is common practice in PHP. It takes a little time to adjust to always using double quotes.

var name = "Andrew"
var copy = '©'

Structs vs Classes

Go does not have a class system like PHP. Instead, it uses structs to model custom data structures. You can write a struct like this:

package main

type Cup struct {
  name string
  color string
  volume int
}

You can add methods to a struct by creating a function that references a struct in parentheses before the function name.

func (c Cup) nameAndColor() string {
  return c.name + ": " + c.color
}

You can then create an instance of a struct by writing the struct name and passing in its initial values in curly braces. Method execution uses dot notation.

func main() {
  c := Cup{name: "Solo", color: "Red", volume: 12}
  c.nameAndColor() // returns "Solo: Red"
}

To create a method that modifies the struct instance, the method must reference a pointer to the struct:

func (c *Cup) crush() {
  c.volume = 0
}

Errors

In Go, errors are not treated like exceptions. There is no throw or catch mechanism. Instead, errors are returned from functions if one has occurred. Go supports returning multiple values from a function. If you call a function that could return an error, you have to check if the error is not nil to handle the error condition.

package main

import "fmt"

func GetName(name string) (string, error) {
  if name == "Bob" {
    return "", fmt.Errorf("Name cannot be Bob")
  }

  return name, nil
}

func main() {
  name, err := GetName("Bob")
  if err != nil {
    fmt.Println("Uh-oh an error has occurred")
  }
}

Fin

Of course, there is a lot more to learn about Go, but hopefully this will help you get started. There are a lot of great resources for studying Go. The most helpful for me were the Go docs and Go By Example. If you have any thoughts or questions, please leave a comment. Thanks for reading!

The PHP logo comes from the PHP website. The Go gopher image comes from @egonelbre.