Intro To Go Programming Part 2

Welcome back to the continuation of the introduction into Go Programming. Last blog was a simple introduction to what is Go, how to install it onto your machine and create your first simple program, the hello world! program. Now we will go deeper into the language and learn about types, variables, control structures, arrays, functions, and end with pointers.

Types

Practically the same as Java, you can declare int, double, float, boolean, and String. Go is a statically typed programming language meaning that variables are always going to be a specific type and that type cannot change. For numbers, they are usually split into two types, integers and floating-point numbers.
Integers act exactly the same as integers in Java. How Go’s integers are unique compared to Java is that they can have set aside for the variables how many bytes it can hold as well integers can be set as unsigned integer by using uint instead of int.

int8, int16, int32, int64, uint8, uint16, uint32, uint64

You can tell how much byte the integer uses by the number next to the variable. 8, 16, 32, 64 are how much bytes they can hold. As for unsigned integers, they are somewhat different. They only contain positive numbers and zero. Generally you would use int as appose to uint since you generally work with integers. Unsigned integers are not normally used, they mostly seen use in certain architecture types.

Floating point numbers act the same as their Java counterpart. But just like the integers of Go, you can set the size of the floats either 32 or 64. Normally 32 is referred to single precision and 64 is double precision. The higher the byte, the more precise the number will be. There are several values that the floats can represent: NaN, and positive infinity and negative infinity.

NaN, +∞, −∞

Floats can also represent complex numbers by using complex64 andcomplex128.

String act the same with the difference being that you can declare a string by using double quotes(“) or by using single quotes(‘). The difference is double quotes strings cannot contain newline characters and they are allowed special escape sequences. An example of this is \n gets replaced with a newline, and \t gets replaced with a tab. character. You can find the length of the string by using len before the string and by using [n] after the string you can find the character at n.

len("Hello World!") would return the length so 11 woudl be returned
"Hello World"[2] would return the character at position 2 so l would be returned

Boolean are exactly the same as in Java, there are no differences. They are 1 bit integer type used to represent true or false and three logical operators are used with boolean.

&&  and
|| or
! not

Variables

Variable declaration is the same as in C. You must first declare the var then the name of the variable followed by the type.

var x string = "Hello World!"

In Go you can choose to declare it like C, or shorten the declaration by using a simpler way to declare variables. You can simple have the variable set to anything and Go’s compiler will be able to infer the type based on the literal value you assign to the variable.

x := "Hello World!"
y := 9
z := 155.55

For the examples above, the compiler will recognize that x is a string, y is a integer, and z is a float based on the literal values assigned.

Another way Go shorthands variable declaration is you can declare multiple variables at once.

var (             var (
a = 5 a int
b = 10 b,c float
c = 25 d double
) )

For the example above, you can see that you can declare multiple variables together. If they are the same type then there is no need to put the type, but if there are multiple different types, they must all be declared right after the variable.

Control Structures

For loop
If statement

For both the for loop and if statements, they are exactly the same as how you would code them in Java or C, the only difference is you would not need to include brackets.

Switch statement

The difference with Go’s switch statement and Java’s switch statement, instead of needing to include breaks after each case, Go can recognized when a new case is started when the word case and the number is used and when default is used.

Arrays

An array is a numbered sequence of elements of a single type with a fixed length. In Go they look like this:

var x [5]int

An array is declared the same way as you would in C, you would declare the var, then the name of the array, then the size and then the type. You can also declare each element of the array.

var x [5]float64
x[0] = 50
x[1] = 53
x[2] = 60
x[3] = 88
x[4] = 83

Go provides a short hand way to declare arrays. We don’t need to declare the type since Go’s compiler will be able to figure it out.

x := [5]float64{ 50, 53, 60, 88, 83 }
Or
x := [5]float64{
50,
53,
60,
88,
83,
}

Go also lets you create slices, they are a segment of an array. Slices are created similarly to arrays except their length is allowed to change.

var x []float64

Another way to create a slice would be to use Go’s build in function make to create a slice.

x := make([]float64, 5)

This slice created above is associated with a float64 array with a length of 5. A slice is always associated with another array, as well they cannot be larger then the array but they can be shorter.

func main() {
slice1 := []int{1,2,3,4}
slice2 := append(slice1, 5, 6)
fmt.Println(slice1, slice2)
}

Go has two unique built in functions that are associated with slices, they are append and copy. Append would create a new slice by taking an existing slice and appending all the following arguments to it. So when the above example is run, slice1 should be 1,2,3,4 while slice2 since having slice1 in it’s argument, would create a new slice for slice2 to include slice 1 with 5 and 6 appended to the end of slice2. So slice2 should be 1,2,3,4,5,6.

func main() {
slice1 := []int{1,2,3}
slice2 := make([]int, 2)
copy(slice2, slice1)
fmt.Println(slice1, slice2)
}

Copy would copy the contents of the slice into the another slice, and will only copy as much information as long as the slice has room for. For the example above, the program will copy the contents of slice1 into slice2, but since slice2 only has size of 2, only the first two elements from slice1 are copied into slice2.

Functions

Functions inside Go are the same as Java and C. They have parameters, may or may not have a return and help break your program down into readable sections. Functions inside Go do have some unique qualities to them. You can have multiple returns, this is useful for error checking. The three changes to a function to make it have multiple returns are:
1. Change the return type to contain multiple types seperated by ,
2. Change the expression after the return so that it contains multiple expressions separated by ,
3. Change the assignment statement so that multiple values are on the left side of the :=
Here is some examples to better show how Go’s function can return multiple return values.

package main
import (
"fmt"
)
func SumProductDiff(i, j int) (int, int, int) {
return i+j, i*j, i-j
}
func main() { 
sum, prod, diff := SumProductDiff(3,4)
fmt.Println("Sum:", sum, "| Product:",prod, "| Diff:", diff)
}

Output

You can see that the function returns 3 separate integer values. Next example shows how error checking is handled.

package main
import (
"fmt"
"errors"
"math"
)
func MySqrt(f float64) (float64, error) {
//return an error as second parameter if invalid input
if (f < 0) {
return float64(math.NaN()), errors.New("I won't be able to do a sqrt of negative number!")
}
//otherwise use default square root function
return math.Sqrt(f), nil
}
func main() { 
fmt.Print("First example with -1: ")
ret1, err1 := MySqrt(-1)
if err1 != nil {
fmt.Println("Error! Return values are", ret1, err1)
} else {
fmt.Println("It's ok! Return values are", ret1, err1)
}
fmt.Print("Second example with 5: ")
//you could also write it like this
if ret2, err2 := MySqrt(5); err2 != nil {
fmt.Println("Error! Return values are", ret2, err2)
} else {
fmt.Println("It's ok! Return values are", ret2, err2) }
}

Output

This program, the first example would return an error since you can’t square root a negative number, so instead of returning an error, it returns the error value and a message that tells that the error occurred. For the second example, since no error occurs the value is returned.

Pointers

Pointers in Go are represented by * character followed by the type of the stored value. * is also used to dereference the pointer variables. Dereferencing a pointer can give us access to the value the pointer is pointing at. Using the & operator, we can find the address of the variable. Another way to get a pointer is to use Go’s built in function called new. New takes a type as the argument, allocates enough memory to fit a value of that type and returns a pointer to it. The good thing with using pointers in Go, is that Go has a garbage collection, so any memory is cleaned up automatically if nothing is referred to it.

package main
import "fmt"
func zeroval(ival int) {
ival = 0
}
func zeroptr(iptr *int) {
*iptr = 0
}
func main() {
i := 1
fmt.Println("initial:", i)
zeroval(i)
fmt.Println("zeroval:", i)
zeroptr(&i)
fmt.Println("zeroptr:", i)
fmt.Println("pointer:", &i)
}

Output

initial: 1
zeroval: 1
zeroptr: 0
pointer: 0x42131100

You can see that zerptr is still pointing to 0 instead of pointing to 1 since the * is still referencing to the value of 0. While the & shows the memory location of the pointer.

This concludes the second part of my introduction to Go programming language. I hope my insight has given you knowledge and interest into the Go programming language.