Google’s Go programming language has been around since 2009 and in 2012, the language reached its official v1.0 status. In those intervening years, much has changed including how the the language is installed. Back in its infancy, there weren’t any official binary distributions and you either had to build Go from the source code, which was the recommended method since the language was changing frequently, or use a pre-built package for your Linux distribution. Back then Windows support was limited as was support for CPU architectures other than Intel.
Things have improved vastly since then. For Linux, there are two easy ways to install Go. Download the official Linux binary build from the Go downloads page or opt for a pre-built package for your Linux distribution. The easiest way to install Go on Ubuntu is to use apt-get
:
sudo apt-get install golang
Once Go is installed, you can start to develop programs. One of the simplest Go programs is the classic “Hello World!” program. Using a text editor, create a file called “hellomte.go
” with the following short Go code:
package main import "fmt" func main() { fmt.Println("Hello Make Tech Easier!") }
Since v1.0 of Go, the need for individual compile and link commands has been removed and the old 8g
and 8l
commands have been replaced with the go
command.
To run hellomte.go
, open a terminal and change directory to the folder which contains the source code file, then type:
go run hellomte.go
This will compile and run the Go program but it won’t produce an executable binary. To create a binary and then run it use the go build
command:
go build hellomte.go ./hellomte
The power of concurrency
One of the defining features of the Go programming language is its support for concurrency which allows a program to work with multiple tasks at once. Parallelism, which is similar to concurrency, allows a program to execute lots of tasks simultaneously, but concurrency goes one step further in that it allows these separate tasks to communicate and interact. As a result, Go allows programmers to use a whole variety of different concurrent designs including worker pools, pipelines (where one task happens after another), and synchronous or asynchronous background tasks. The foundation of this concurrency is the goroutine
coupled with channels
and Go’s select
statement.
Here is a simple Go program which prints out a string several times using a concurrent goroutine:
package main import ( "fmt" "time" ) func say(s string) { for i := 0; i < 5; i++ { fmt.Println(s) } } func main() { go say("Hello Make Tech Easier!") fmt.Println("Sleep a little...") time.Sleep(100 * time.Millisecond) }
The function say()
just performs a simple loop to print out the string (parameter s
) five times. The interesting thing is how that function is called. Rather than just calling say("Hello Make Tech Easier!")
the keyword go
is placed in front of the function call. This means that the function will be run as a separate task. The rest of the main()
function then just sleeps a little to give time for the goroutine
to complete.
The output may surprise you:
As you can see the say()
function is run as a goroutine
and while it is being setup the rest of the main()
function continues, printing out Sleep a little...
and then going to sleep. By then the goroutine
is active and starts to print out the string five times. Finally the program ends once the timeout limit as been reached.
Channels
goroutines
can communicate using channels. A channel opens up a line of communication between two different parts of a Go program. Typically a function will be called as a goroutine
and if it needs to send back data (say from a network operation) it can use a channel to pass along that data. If another part of the Go program is waiting for that data, it will sleep until the data is ready. Channels are created using the make()
function and they can be passed as parameters to goroutines
.
Consider this code:
package main import ( "fmt" ) func say(s string, c chan int) { var i int for i = 0; i < 5; i++ { fmt.Println(s) } c <- i } func main() { c := make(chan int) go say("Hello Make Tech Easier!", c) sts := <- c fmt.Println(sts) }
The say()
function is very similar to the first example with the exception that the second parameter is a channel and that after printing out the string, the number of iterations will be send down the channel via the c <- i
line of code.
The main function creates a channel, starts the say()
function as a goroutine
and then waits for the data to come down the channel, sts := <- c
before printing the result.
Conclusion
The Go language has progressed significantly over the last few years, if you haven’t looked at it recently the perhaps now is a good time!
Gary has been a technical writer, author and blogger since 2003. He is an expert in open source systems (including Linux), system administration, system security and networking protocols. He also knows several programming languages, as he was previously a software engineer for 10 years. He has a Bachelor of Science in business information systems from a UK University.
Subscribe to our newsletter!
Our latest tutorials delivered straight to your inbox
Sign up for all newsletters.
By signing up, you agree to our Privacy Policy and European users agree to the data transfer policy. We will not share your data and you can unsubscribe at any time. Subscribe