Understanding Go Syntax and Language Features
Tags: go, google, programming
Published: 2023-11-05 07:45:06

In this article, I will be introducing you to the basic foundation of reading and writing GoLang. Go is one of the simplest programming languages, which is one of the many reasons many developers love the language so much (find out other reasons why Go is so popular [here](https://dev.to/intellect4all/a-comprehensive-introduction-to-golang-5ab5)). Go programs are stored in a text file with a `.go` extension, e.g `main.go`.

Programming is just a sequence of written instructions for a computer, and large applications are built by the composition of tiny and simple other instructions. Understanding how to create and combine these tiny instructions is the foundation of programming. Let us start from the basics and build our way up.

## **Variables**

A variable serves as a storage location on the computer, identified by a name for easy reference. and since it is a storage, it can hold a quantity of data or object of a particular type. For example, if we need to store the age of a person in memory, we can do so like this,

```go
var age int = 20
```

In this case, `age` is the name of the variable, the type (we are coming to this) of data that the variable contains is `int` (which means integer) and `20` is the value that will be stored in the variable.

Or to store the value of a complex calculation (not really), we can do this, for example

```go
var total int =  1 + 2 + 3 + 4 + 5
```

Declaring a value in GoLang often follows the following format,

```go
var name type = expression
```

The `var` is a keyword in Golang to tell the compiler that we are creating a variable, the `name` is the reference to which we want our variable to be known and accessed, the `type` is the type of data the variable can hold, the `=` is the assignment operator, and the `expression` is the value to be stored in the variable. If the expression is not provided, the variable is created and initialized with the zero value of the type. A zero value simply means a default value.

For instance, if we declare our variable like so,

```go
var age int
```

we did not specify any value to be stored in the variable, so Go creates the variable and sets its value to 0, which is the default value for number types.

**Zero values for different types**

1. 0 for numbers
    
2. false for booleans
    
3. “” for strings (note, “” is an empty string)
    
4. `nil` for interfaces and reference types (we are coming to this)
    

When creating multiple variables of the same type, you can efficiently do so on a single line, as demonstrated below:

```go
var mean, median, mode, total, count int
```

As always, the `var` is the keyword for declaration, `mean, median, mode, total, count` are the variables to be created, and they are all of the same type as the type declared at the end of the line, which is `int` in this case. And remember, since we did not include any expression, they are all created with their zero values, so they all have the value of 0.

If perhaps we know the data ahead, we can create them in one line by providing the values separated by commas in the exact order in which the variables are created, like below,

```go
var mean, median, mode, total, count = 20, 15, 30, 120, 10

// 20 is assigned to mean, 15 to median, and so on, in that order
```

If you want to create many variables of different types in one line, you can do so like this,

```go
var name, age, sex, isPresent = "John", 12, "Male", true

// "John" is assigned to name, 12 to age, "Male" to sex, and true to isPresent
```

Multiple variables can also be created in the format below:

```go
var (
		name      string
		age       int
		sex       string = "Male"
		isPresent bool = false
	)
```

And just like we have established, remember that if we don’t define an expression for the variable, it is created with the zero value. So in this case, `name` and `age` are created with zero values while `sex` and `isPresent` have the values “Male” and `false` respectfully.

Please note that expression can also be the output of a function (think of a function as a group of common code executing a particular task). Let’s say we have a function that computes the square of a number, we can store the result of this function when we calculate the square of 5 in a variable,

```go
package main

import "fmt"

func main() {

	var squareOfFive int = Square(5)

	fmt.Println(squareOfFive)
}

// this is a function, we will discuss it in details in the next article
func Square(number int) int {
	return number * number
}
```

In some cases, especially if you want the variable to automatically be the type of the expression, you don’t need to explicitly specify the type, you can omit it, and Go will automatically infer the type of the variable from the type of value of the expression. So in this case of,

```go
var squareOfFive int = Square(5)
```

we can simply omit the `int` and the variable will automatically assume the type of the returned data, like so:

```go
// squareOfFive will automatically assume the type 
// of the data retured by the Square method, which is int in this case
var squareOfFive = Square(5)
```

This may be useful in some cases, but most times, you always want to declare the type of the variable, so your code can be simple, and readable.

There is an alternate way of creating a variable in GoLang, also known as a short variable declaration. This form of declaration is only permissible within a function and only used to declare local variables within the scope of the function. It takes the form:

```go
// take not of the symbol
variableName := expression 

// the syntax is a semicolon followed by equals, :=
```

This method of variable declaration is prevalent and the syntax `:=` is often confusing for people who are not familiar with Golang syntax. Let’s see it in an example, suppose we want to write a function that returns the average of 5 numbers, we can decide that we will compute the total of the 5 numbers and put it in a variable, then return the division of that variable by the count:

```go
func AverageofFiveNumbers(a,b,c,d,e int) int {
	total := a + b + c + d + e
	return total / 5
}

// you cannot do this outside of a function, it will throw an error
total:= 20
```

This function is purely for demonstration and you will probably never be writing simple code like this in production. As you can see, we omitted the `var` keyword when we declared the `total` variable, other rules of variables apply to this too, as it is simply a variable too, but just created with another syntax (and remember that you can only use this `:=` syntax in a function).

**Variables are mutable and reassignable!**

After we create a variable, we can overwrite the data later in the code to hold new information, as long as the new information is of the same type as the old value. For instance, after calculating the `squareOfFive` in the code below, we can overwrite it later in the code, to hold the wrong data.

```go
package main

import "fmt"

func main() {

	var squareOfFive = Square(5)

	fmt.Println(squareOfFive) // 25 is printed

	squareOfFive = 10

	fmt.Println(squareOfFive) // 10 is printed
}

func Square(number int) int {
	return number * number
}
```

If you run the code, you will see that the value `squareOfFive` is overwritten with the wrong data. For this reason, variables are used to hold data that can be manipulated in the program (hence the name, it is not fixed).

## **Constants**

We have already established that variables can be overwritten and changed in the code, whether intentionally or even by mistake, which is a very good thing, because most times, we make things work by manipulating the variables and changing their values at runtime. However, there are times when we need data storage to be fixed and immutable, i.e. it should be constant.

For example, if we are running a mathematical calculation that involves `Pi` , and some other mathematical constants, we do not want our code to be able to change their values, whether willingly or by mistake. In that case, we use, well, CONSTANTS.

Constants are data storage marked as immutable and are created at the program compile time. They can only be numbers, characters, strings, or booleans. And because they are constants, the expressions that define them must also be constant and can be evaluated by the compiler.

To create a constant, use the keyword `const` , e,g:

```go
const speedOfLight = 299792458 // m/s
```

It follows the same format as when creating a variable, just replace the `var` keyword with `const`. If we try to mutate the value of the constant `speedOfLight` later in our code, we will get an error and our code will not compile.

If we need to create multiple constants, we can do this:

```go
const speedOfLight, speedOfSound = 299792458, 343

// or 

const (
	speedOfLight = 299792458
	speedOfSound = 343
)
```

But remember that constants cannot be mutated, so we cannot have zero values or use any expression that implies that. Every value of the constant must be known at compile time.

There is also an `iota` keyword that is used to enumerate constants. For example, if we need to declare the days of the week with an index, starting with Sunday at index 0, we can use iota to make things easier like so:

```go
const (
		SUNDAY int = iota
		MONDAY
		TUESDAY
		WEDNESDAY
		THURSDAY
		FRIDAY
		SATURDAY
)
```

In this code, the `iota` assigned the value 0 to Sunday, then increments to 1 for Monday, 2 for Tuesday, and so on. This can be very useful if we just need to quickly enumerate and increment some constants by a value.

## **Data Types**

We have established that data type is the type of value that is stored in a variable. It is how we know about the data we have and how we can interact with the data.

In Golang, there are four categories of data types:

1. **Primary types:** Primary types are the data types that are pre-defined and built into the language and are the fundamental building blocks of the language. Examples are integers, strings, and booleans.
    
2. **Aggregate types:** Aggregate types, as the name implies, are data types that combine simple primary data types to form complex ones. Examples are arrays and structs.
    
3. **Reference types:** Reference types are data types that are used for dynamic management and accessibility of data locations and addresses in memory. Examples include pointers, slices, maps, and channels.
    
4. **Interface types:** Interface types are used to express generalization or abstraction about the behaviors of other types.
    

Let us dive into the primary data types in Golang, we will look at the other advanced types later in future articles.

### Integers

Numbers are very important in programming and all languages provide ways to work with different types of numbers for different use cases. In Go, there are several sizes of integers, floating point numbers, and complex numbers to work with.

Go provides both signed and unsigned integer arithmetic. Signed integers simply mean the type can represent both positive and negative numbers, while unsigned integers mean that the type can only represent non-negative numbers. Signed integers are represented by `int` in Go while unsigned integers are represented by `uint`. `int` is the most used integer type and so it is often the recommended choice for integers.

**Sizes of integers**

1. int8 - 8 bits
    
2. int16 - 16 bits
    
3. int32 - 32 bits
    
4. int64 - 64 bits
    
5. uint8 - 8 bits
    
6. uint16 - 16 bits
    
7. uint32 - 32 bits
    
8. uint64 - 64 bits
    

The bits specify the range of the storage capacity of each type, the higher the size of the bit, the more number the type can hold. There is also a type `rune` which is often used in place of `int32`.

Many operations can be performed on integers, some of them are addition `+`, subtraction `-`, multiplication `*` , division `/` , remainder `%`, and comparison operations (compares the values of left and right and returns a boolean) e.g equals `==`, not equal `!=`, less than `<`, greater than `>` and so on. There are also operations like `+=`, `-=`, `*=` which means performing this operation with the expression, and then assigning the result as the new data. For instance:

```go
var total = 0

total += 10

// which is same as
total = total + 10

total -= 10

// which is same as
total = total - 10

total *= 10

// which is samea s
total = total * 10
```

### Floating-Point Numbers

Floating points numbers are simply decimal numbers, and Go provides two data types to work with them - `float32` and `float64`. The difference between these two types is also the data capacity. While the `float32` provides approximately six decimal digits of precision, the `float64` provides 15 digits, so it is often used for most floating number applications.

```go
const pi = 3.141592653589793
const discount = .3 // notice that the 0 is omitted, this is permissible in Go.
```

You can also write floating point numbers with scientific notation,

```go
const r = 3.456e11
```

### Strings

A string is an immutable sequence of bytes, and is often human-readable text.

```go
var name = "John" // John is a string
```

The length of a string can be determined by the `len(string)` function. Strings are just a list of individual characters and are indexed from left to right, and the count starts from zero. E.g

```go
var name = "John"

John
0123

// we can get the first character by passing the index in a square bracket

j := name[0]
o := name[1]
h := name[2]
n := name[3]
```

However, when indexing a string, take note not to let the index go out of the bound of the string length as that can cause an indexing error.

### Booleans

Booleans, represented as `bool` in Go can only be `true` or `false`. They are often used to represent possibilities of two logical states, e.g light is on or off (`true` for on, and `false`, for off.)

```go
var isLightOn bool = false

isLightOn = true
```

They are used in conditions for control flows and are the outputs of comparison operations such as `==`, `<=`, `>=`, `!=`. The `!` syntax is used to negate the values of Booleans, it often reads as `not`. For instance,

```go
var isLightOn bool = false

isLightOn = !isLightOn // note exclamation
```

This code means that the value of `isLightOn` should be the opposite of whatever the current value is, so if it is false, it becomes true, and if it is true, it becomes false.

## **Control Structures: Loops and Conditional Statements.**

Control structures are used to analyze the state of the program and decide the direction of execution based on the given state. They are the basic decision-making process in programming.

Control statements mostly allow you to do two things:

1. Execute some statements while skipping others
    
2. Repeat one or more statements while some conditions are met.
    

### Loops

There is only one way to loop in Go, and that is with the `for` loop. A loop is an iteration/rerun of a block of code until a certain condition is met. The condition is specified by the programmer and the program will not proceed until the condition of the loop becomes false, and if the condition is never met (i.e never false), the loop will run till infinity and eventually crash the computer (don’t worry, most computers can handle this elegantly). A `for` loop usually has this format, notice how the components are separated by semicolons, it is very important.

```go
for initialization; condition; post {
	// do this
}
```

there are three basic parts of the for loop:

* The initialization: this is called before the first iteration, so it is often used to do some pre-calculations, run a short code, or for variable declaration before the loop runs. Often used for short variable declarations, and any variable declared there is only available in the scope of the loop i.e in the block of code contained between the `{` and `}`.
    
* the condition: this is run before every iteration, so it is where the comparison needed to check if the loop should run is done. If the value of this condition is false, then the loop stops running, and the program proceeds to the code following the for loop,
    
* the post: this part of the loop is executed at the end of every iteration, so it is where the necessary variables are incremented and updated ahead of the next iteration.
    

Let us write a simple for loop that counts from 0 to 9;

```go
// remember to import the fmt package

for i := 0; i < 10; i++ {
	fmt.Println(i)
}
```

This code will run 10 times. It declares `i` to be zero at the initialization (which is run only once and before the for loop begins), then it checks the condition `i < 10` , and since `i` is 0 at this point, the condition is true, so the code runs, and 0 is printed to the console. Immediately after that, the post is run and `i++` executed. `++` is a syntax meaning increment the current value by one,

```go
i++

// is the same as 

i = i + 1
```

and since `i` is zero, `++` increments `i` to `1`. This completes the cycle for the first iteration. On the second iteration, the initialization is skipped, and the condition is checked again, this time, we know `i` is 1, so the condition is true again since 1 is `<` 10. The loop is run and `1` printed to the console, after which the post part is run to increment `i` to 2 and complete the cycle of the second iteration. This is repeated until `i` is incremented up to 10 the condition fails and the loop is closed and the program continues to the next line after the loop, which is why you don’t see the 10 printed in the console.

There is no `while` or `do while` that you may be familiar with in other languages in Go. You only have the `for`. To achieve a while loop, you can simply drop the initialization and post part of the for loop, as those are optional, and only declare a condition:

```go
package main

import "fmt"

func main() {
	number := 1000
	noOfTimesDivisibleBy14 := 0

	for number >= 14 { // this works like a while loop
		number -= 14
		noOfTimesDivisibleBy14++
	}

	fmt.Printf("No of times divisible is %v, remainder is %v", noOfTimesDivisibleBy14, number)

}
```

If you omit the condition, you can create an infinite loop that runs forever;

```go
for {
	// this is an infinite loop. 
}
```

To break out of a loop, you can use the `break` keyword to stop the iteration and break away from the loop irrespective of the condition, then the program continues to the next line after the loop body.

```go
count := 0 

for {
	fmt.Println(count)
	if count >= 1000 {
		break // stop the loop and continue
	}
}
// the program continues running here
```

Note that you can also use a `return` keyword to close the loop irrespective of the conditions, but instead of continuing to the next line after the loop like in the case of `break` above, the program returns completely from that scope.

## Conditional Statements

### if

The if statement is used to check if a block of code should be executed or not. it usually follows the following expression:

```go
if initialization; condtion {
	// do something conditionally
}
```

The `initialization`, as we saw in the `for` loop is where we can make some variable declarations before the `condition` is checked, and if the condition is `true` the code in the block `{}` will run and any variable created in the `initialization` will be available in the scope of that block. If the condition is `false`, the block is skipped and the program proceeds to the next line after the if condition.

There is also an `else` part of the if, though it is optional. The `else` block will run if the condition of the if statement is false.

```go
if condtion {
	// do this, only if the condition is true
} else if second condition {
	// or do this, if first condition is false and second condition is true
} else {
	// if any of the previous conditions are not true, then do this
}
```

You can chain as many `else if` as you want (although it is probably not advisable to do so) or you can use the next conditional statement, the `switch`. Not that if you use a `return` inside the if statement, the program returns from the current scope.

### Switch

The `switch` is simply a more compact and easier way to write a chain of `if and else` statements. It runs a condition against preconditions called cases and executes the first case it encounters that satisfies the condition of the execution.

Switch statements follow the following format:

```go
switch initialization; comparator {
	case condition1: 
			// run this if comparator == condition1
	case condition2:
		// run this if comparator != condition1 and comparator == condition2
	default:
		// run this if the comparator matches none of the cases
}

// note that you can have as many cases as required
```

As always, the `initialization` is the part that allows us to create variables or run short codes before the switch is executed, and it is also optional. The `comporator` is the thing we want to check with cases from top to bottom to find a match. if no match is found with any of the cases, the `default` block is executed.

For example, let us write a code that switches between the color of a car:

```go
switch carColor {
	case "red":
			fmt.Println("The car is red")
	case "blue":
			fmt.Println("The car is blue")
	case "green":
			fmt.Println("The car is green")
	default:
			fmt.Println("I don't know the color of the car")
}
```

The `comparator` is also optional, if it is not provided, it defaults to `true` and the program goes through the cases from top to bottom until it finds the first case whose condition is true. For example:

```go
switch {
	case true == false:
			fmt.Println("The is false")
	case false == true:
			fmt.Println("The is false")
	case false != true:
			fmt.Println("The is true")
	default:
			fmt.Println("the default")
}

// in this case, since the comparator is not provided, it defaults to true and
// the program goes through the cases until it executes the third case whose 
// condition is true. 
```

Congratulations! You made it here. That is just the basic syntax of Golang. In the next article, we will dive deeply into advanced data types such as arrays, maps, functions, pointers, and structs.

You can connect with me on [LinkedIn](https://www.linkedin.com/in/abduljemeel-odewole-393a0b105/) here, on [X](https://twitter.com/intellect4all), and my email is [here](http://mailto:odetechit@gmail.com).

Keep GOing

**References:**

Effective Go: [https://go.dev/doc/effective\_go](https://go.dev/doc/effective_go)

The Go Programming Language: Alan A.A Donovan, Brian W. Kernighan