In this article we’ll walk through the basics of the Go programming language. We'll supplement with code examples that illustrate the point and offer some meaningful code.

It's easy to understand the syntax if you have a little background in C. As Go is well documented, we’ll focus mainly on how quickly we can get into coding and understand it by actually doing it. Let’s first set up the environment.

Setting up Go

  • Installing Go is actually quite simple. Download the compiler. There is precise installation instruction given in the installation guide.
  • There are many free IDEs available that support Go programming through plugins such as Atom, vscode, Eclipse. Here we’ll be using vscode. There are plugins available for Go coding in the vscode marketplace.
  • After the Go compiler has been successfully installed, we need to set up a few environment variables such as GOROOT, GOBIN, GOPATH and PATH. In fact, setting up only GOPATH and PATH is enough but for convenience we’ll set up other environment variables as well.
    • The GOROOT environment variable refers to the go installation directory such as /usr/local/go in Unix/Linux.
    • The GOPATH environment variable specifies your workspace location where we typically keep our programming code. If this environment variable is not set it defaults to a directory named “go” inside the home directory, such as $HOME/go in Unix/Linux or %USERPROFILE%\go in windows. The GOPATH may contain multiple directory paths that refer to different Go projects.
    • The GOBIN environment variable refers to the bin directory inside the go installation directory such as $GOROOT/bin. Setting up this environment variable is particularly useful if we frequently switch between different GOPATH directories. This variable refers to the location where you can find the binaries.
    • PATH is a common operating system environment variable that refers to the directories used by the shell for right executable files. We typically set $GOBIN and $GOPATH/bin directories to the PATH variable so that the executable that comes with GO and the executable we create through Go programming are found correctly.

Once the installation and setup are done properly, we can check if things went right or not from the terminal using the following commands.

  • go version - will show the Go version installed
  • go env - will print the status of the environment variables

If everything went well, go version should show the Go compiler version installed and go env will show the list of environment variables and their content, some of which we may have recently set. A comprehensive documentation of go commands can be found here.

Note: Starting with Go 1.13 module mode of Go development has been a default phenomenon. If we opt to use module mode in Go programming it is not necessary to set up GOPATH. Let’s keep the idea aside for a while and set up GOPATH. We’ll not be using module mode at least now.

Go workspace

Go facilitates source code management through Go workspace. It contains source files, compiled binaries and cached objects for fast compilation. The Go workspace typically contains three directories: bin, pkg, src. 

The src directory will contain all of our source code. So, when we say build path to our workspace directory it is going to find the code file in the src directory. The bin directory shall contain the binaries that we may create after compilation of the source file. The pkg directory contains intermediate binaries such as third-party packages that we may use in our project. These intermediate binaries are stored in the pkg directory. The intermediate binaries do not need to be recompiled, only to be linked during the final step of compilation of the project while creating a single binary executable.

Note that it is typical that Go workspace contains these three directories. A real-life project structure may contain multiple directories where each sub directory has one or more files.

Introducing package, main and init function

The first statement of the Go code always begins with package. This means that one or more source files that are to be compiled together are collected in the same package. Programming elements such as variables, constants, and functions declared in any of the source files within the package are visible across the package.

Go program must have a main package with a main() function that serves as program’s entry point or typically first executed function. This function is automatically called and needs no explicit invocation. 

But there is a function called init() that is executed before main(). Like main() this function also does not take any argument nor return anything. This function is present in all the packages and particularly used for initialization purposes. Unlike main(), there can be multiple init() functions and they are executed in the order of their creation as we can see in the following example:

package main
import "fmt"
func init() {
	fmt.Println("from first init()")
}
func init() {
	fmt.Println("from second init()")
}
func init() {
	fmt.Println("from third init()")
}
func main() {
	fmt.Println("from main()")
}

Output

from first init()
from second init()
from third init()
from main()

Types in Go

  • Boolean Types: To deal with boolean values and expressions Go provides the bool type with standard true and false values. The standard  logical and comparison operators produce bool results.
  • Numeric Types: Go has a wide range of built-in numeric types with standard library inclusion for big.Int.
    • Integer Types: There are 13 integer types such as:
      • signed: int, int8, int16, int32, int64
      • unsigned: uint, uint8, uint16, uint32, uint64
      • byte is same as int uint8
      • rune is same as int32
      • uintptr is unsigned integer to store pointer value
    • Floating-point types: There are two each for floating-point numbers and complex numbers
      • floating-point numbers: float32, float64
      • complex numbers (contains real and imaginary parts): complex64, complex128

For example, this is how we deal with complex type:

package main
import "fmt"
func main() {

	cnum1 := complex(6, 9)
	cnum2 := 5 + 23i
	csum := cnum1 + cnum2
	fmt.Println(csum)
}

Output

(11+32i)

For another example, here's how we may create a pascals’ triangle in Go taking user input from the keyboard.

package main
import "fmt"
func main() {
	//Pascal's triangle
	var rows int
	cof := 1
	fmt.Println("Enter number of rows: ")
	fmt.Scanf("%d", &rows)
	for i := 0; i < rows; i++ {
		for j := 0; j <= i; j++ {
			if j == 0 || i == 0 {
				cof = 1
			} else {
				cof = cof * (i - j + 1) / j
			}
			fmt.Printf("%5d", cof)
		}
		fmt.Printf("\n")
	}
}

Output

Enter number of rows: 
10
    1
    1    1
    1    2    1
    1    3    3    1
    1    4    6    4    1
    1    5   10   10    5    1
    1    6   15   20   15    6    1
    1    7   21   35   35   21    7    1
    1    8   28   56   70   56   28    8    1
    1    9   36   84  126  126   84   36    9    1

Declarations/Assignments in Go

Understand that in the example above we have used two types of assignment operators ‘=‘ and ‘:=’. While the former (=) is a common assignment operator to assign or reassign values to variables that are already declared, while the later (:=) is used to perform short variable declaration without a specified type. For example:

var x int = 10
var  y = 10
var z int
z = 10

can be easily replace by the shorthand assignment expression such as

x :=10
y :=10
z :=10

Note that unlike regular variable declarations, short declarations do not require explicit types. They are more concise than regular variable declarations or assignments. But note that short variable declarations are used inside functions or methods. It is not possible to use short declarations while declaring global variables that are accessible across the package level. In such a case we must declare it as var x int =10.

Let’s try an example that creates a copy of another file. The function io.Copy copies content from source file to destination file until either EOF is reached on the source file or an error occurs. It returns the number of bytes copied and the first error encountered while copying, if any.

package main
import (
	"io"
	"os"
)
func main() {
	filecopy("/home/mano/Documents/kartika_copy.pdf", "/home/mano/Documents/kartika.pdf")
}
func filecopy(destfile, sourcefile string) (written int64, err error) {
	source, err := os.Open(sourcefile)
	if err != nil {
		return
	}
	defer source.Close()
	destination, err := os.Create(destfile)
	if err != nil {
		return
	}
	defer destination.Close()
	return io.Copy(destination, source)
} 

Conclusion

Setting up of the programming environment, understanding the types and variable declarations, loops, conditional statements and functions lays down the foundation of any programming language. The loops and conditional statements are pretty straight forward. They are not explicitly dealt with here. Go documentation is an excellent source to start Go coding. There is more to come, so stay tuned.

References:

Go Documentation

Go Programming Language Specification






This article was originally published on December 4, 2020