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.
Top comments (16)
This is a "no go" for me.
At first, I wasn't a fan of this. It made the code feel cumbersome. After a bit, I not only got used to it, but came to embrace it. It makes error handling much more a natural part of the way you code. You can avoid the scoping of a
try/catch
block because you don't have to put your code into another block.The compiler will ensure that you've recognized the error is part of the return (when using a multi-return function) so you don't have to worry about being unaware of it. If you do anything with it and what you do is up to you. You could choose to ignore it by assigning it to
_
instead of a variable.It’s not as bad as you might think. It forces you to account for each error which makes your code a little more resilient.
I read that same line and instantly thought `oh, crap. error catching is going to be a mess'. But then I thought about it; most error catching I do should be handled in a much more graceful way. Not a 'here is an error, return stack trace'. After reading this article I feel like going Go a try, again.
4 steps to love it:
1 try to implement clean project structure
2 use exceptions to propagate errors
3 realize that exception is part of interface, and to avoid coupling, or catching SQL exceptions in HTTP controller you need exception per layer
4 give up and embrace go’s way of handling errors
not to mention that throw is essentialy a GOTO instruction, its slow and ask yourself - how many times, when catching “business-logic” related exception from your code you were interested in stacktrace?
I honestly love it. As a hardcore C user, it feels pretty natural to me and makes you deal with the error as soon as possible instead of ignoring it.
Can second this
Great article.
I have been working in both PHP and Go on the last months in my company, and I think they really complement each other very well. Some of the known weak points of PHP like concurrency or long running processes are the strengths of Go.
Plus, Go is really great for applications like system tools, command line tools or small services (ex: slack bots, webhooks listeners, etc), because since it compiles into a single binary makes it incredibility easy to install and run in any system.
PHP is still one of my favorite languages for general web application development as I can write clean code really fast, thanks to OOP design and frameworks like Symfony.
Adding a mix of Go for more specific use cases and you can build almost anything.
So,if you are a PHP developer, I really recommend taking the time to learn Go.
Great insights.
I am curious to see whether you had an instance where GO would consume the data received by the Symfony APP i.e. listening to some form of events etc? If so could you please give some examples as to how you went about this.
Thanks :)
This would be much better served by satisfying the Stringer interface:
I would recommend following the tour here: tour.golang.org/methods/17
To see in greater detail why this is a more useful way to do this.
Thanks for pointing that out. I just wrote the method as an example, nothing more.
hey, you said Go is a"program in a language that could run on any platform without having to have an interpreter already installed". Could you explain how that works, so you can write Go App and run it on other machines without having to install some kind of interpreter?
I was just thinking about picking up Go, when your post popped up on Facebook, as if they were reading my mind...or search history...God damn you Zuck, you lizard!
It's definitely worth checking out. I like it because it stretches my brain in ways that PHP and JavaScript do not.
golang.org/x/tour/gotour has moved to golang.org/x/tour
GO seems combining features of several languages. Package system from Java, Structs from C, Pointers from C. Indentation from python. Seems powerful.