January 21, 2021
Hot Topics:

Anatomy of a Google Go Program

  • By Edmon Begoli
  • Send Email »
  • More Articles »

"Go" is a systems programming language developed by Google software engineers, who set out to create a simple, fast alternative for building systems software and software components that could run natively on various hardware platforms. As Go is a compiled language, its programs are linked, compiled, and executed similarly to C programs.

Two Go compilers currently are available, one for the x86 platform and another for AMD. This approach allows you to compile source programs using the command 8g (8 for x86) or 6g (6 for AMD). However, to enable programs to be compiled by Go, you must link them to an out executable with the command 8l or 6l.

In this article, I will demonstrate Go's features and syntax through a very simple, but very common, scenario: reading in lines of multiple, space-delimited records from a text file and processing each line concurrently. I will use the Go compiler and linker for the x86 platform.

Organization of Programs

Go programs are organized in packages. In the demo program, I declare two packages: main and acct. By Go conventions, main is a package that contains an executable main function and acct contains accounting routines referenced by main. To refer to a function from a package, you simply prefix the name of the function with a package name. Packages in Go serve as the classes for routines. To avoid naming collisions, you can custom name packages after importing them.

import format "fmt";

Despite being a small language, Go incorporates a significant number of very useful packages, including XML, JSON, HTTP and web services processing.

To import a custom package, in this case acct, specify:

import "./acct"

No Parenthesis and Semicolons Sometimes

Control statements in Go do not accept parenthesis. While the most common control statement, if, would take this form in C, C++, C# or Java:

if ( count > MAX_ITEMS ) {

In Go, it would have the following form:

if count > MAX_ITEMS {

Semicolons in Go are optional. A single statement does not require a semicolon at all. Semicolons are required only in control blocks with multiple statements, where they delineate every statement from the previous one. The last statement in the list does not require a semicolon.

for j := 0; j<3; j++  {
           localSum := <-sum;            
           fmt.Printf( "sum is %f \n", localSum )

However, you can terminate any Go statement with a semicolon.

Types, Objects and Memory Management

Go lacks strength as a typed language. You do not need to explicitly declare types of variables. Instead, Go implicitly assigns the type to the untyped variable when the value is first assigned to the variable.

You can declare variables explicitly:

var newline string;

Or declare and initialize them implicitly with a := assignment.

newLine := string(contents);

In this case, the newLine variable is declared as a string and assigned a string value of the contents byte array.

When you have declared the type of the variable, you cannot re-declare it. So, the following would result in an error:

sum = total + 1;
newLine = sum;

You declare and allocate structs and other non-primitive objects with the familiar keyword new. Go supports referencing types by value or by reference using the & prefix, which will be familiar to anyone who has programmed in C or C++.

You declare and allocate maps, arrays, and channels with the keyword make, which greatly resembles the syntax of malloc; it accepts type and optionally the size of the allocated object.

In this example, I allocate a channel variable called sum, which I will use to pass data between the worker threads (goroutines) and the server:

sum = make (channel float, 50 )

I will address channels and concurrency shortly.

Because Go is a garbage-collected language, you do not need to manually de-allocate dynamically allocated variables. Go's garbage collector de-allocates the memory of unreferenced variables.


Go has a peculiar function syntax and implementation. Its functions are declared with the keyword func followed by parameters and return types. So, you would declare a function that takes a channel of float types and returns a float like this:

func CalculateTotal(channel float) float{ ...

More interestingly, Go functions can return more than one type. So, Go native functions commonly return either error types or expected, normally produced types in the same invocation. Think of errors in this case as exceptions in Java or C#.

This is how I invoke the file-reading routine, which can produce a reading error:

contents, err := ioutil.ReadFile( "test.txt" );
if err != nil{
    fmt.Sprintf( "Error parsing file e %q", err );

Notice that in addition to the expected result from a ReadFile (byte array), I also accept the err type, which is returned when the ReadFile fails.

Originally published on https://www.developer.com.

Page 1 of 2

This article was originally published on February 4, 2010

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date