Notes
Search…
Basics

Go basics

In this section some basics of go are noted down.

Basic data types

Go's basic data types are,
1
bool
2
3
string
4
5
int int8 int16 int32 int64
6
uint uint8 uint16 uint32 uint64 uintptr
7
8
byte // alias for uint8
9
10
rune // alias for int32
11
// represents a Unicode code point
12
13
float32 float64
14
15
complex64 complex128
Copied!
Ref: A Tour of Go

Variables

Variable is the name given to a memory location to store a value of a specific type.

Declaring single variable

Syntax: var name type
Example:
1
var age int
Copied!

Declaring variable with initial value

Syntax: var name type = initialvalue
Example:
1
var age int = 29
Copied!

Type inference

If a variable has an initial value, Go will automatically be able to infer the type of that variable using that initial value.
Syntax: var name = initialvalue
Example:
1
var age = 29
Copied!

Multiple variable declaration

Syntax: var name1, name2 type
Example:
1
var width, height int
Copied!
With initial value
1
var width, height = 100, 50
Copied!
Variables of different types
1
var (
2
name string
3
age int
4
height float32
5
)
Copied!
with initial value
1
var (
2
name = "naveen"
3
age = 29
4
height = 5.32
5
)
Copied!

Short hand declaration

Syntax: name := initialvalue
Example:
1
name := "emruz"
2
age, weight := 24, 65
Copied!
Short hand syntax can only be used when at least one of the variables in the left side of := is newly declared.
1
a, b := 20, 30 // declare variables a and b
2
b, c := 40, 50 // b is already declared but c is new
3
a, b := 40, 50 //error, no new variables
Copied!

Constant

Once declared, can not be reassigned,
Syntax: const name = value
Example:
1
const a = 55 //allowed
2
a = 89 //reassignment not allowed
Copied!
The value of a constant should be known at compile time.
1
var a = math.Sqrt(4)//allowed
2
const b = math.Sqrt(4)//not allowed
Copied!
b is a constant and the value of b needs to be know at compile time. The function math.Sqrt(4) will be evaluated only during run time and hence const b = math.Sqrt(4) throws error.
Go is strongly typed language. So, mixing type during assignment is not allowed.
Hence,
1
var defaultName = "Sam" //allowed. type of defaultName is "string"
2
type myString string
3
var customName myString = "Sam" //allowed. type of customName is "myString"
4
customName = defaultName //not allowed. Error: cannot use defaultName (type string) as type myString in assignment
Copied!
Although myString is alias of string, Go does not allow to assign string type variable into myString type variable.
Constant does not have a type. They can provide a type on the fly depending on the context.
For example,
1
package main
2
import "fmt"
3
4
func main() {
5
const name = "Sam"
6
const age = 24
7
fmt.Printf("value: %v type: %T\n", name, name)
8
fmt.Printf("value: %v type: %T\n", age, age)
9
}
Copied!
Output:
1
value: Sam type: string
2
value: 24 type: int
Copied!
Again,
1
package main
2
import "fmt"
3
4
func main() {
5
const a = 5
6
var intVar int = a
7
var int32Var int32 = a
8
var float64Var float64 = a
9
var complex64Var complex64 = a
10
fmt.Println("intVar",intVar, "\nint32Var", int32Var, "\nfloat64Var", float64Var, "\ncomplex64Var",complex64Var)
11
}
Copied!
Output:
1
intVar 5
2
int32Var 5
3
float64Var 5
4
complex64Var (5+0i)
Copied!
This program does not give any error because a is constant, so it does not have any type. When a is assigned to different type variable, it is taking type of this variable.

Functions

A function is a block of code that performs a specific task.
Structure:
1
func functionname(parametername type) returntype {
2
//function body
3
}
Copied!
Sample function:
1
func calculateBill(price int, no int) int {
2
var totalPrice = price * no
3
return totalPrice
4
}
Copied!
If consecutive parameters has same type, writing type each time can be avoided by writing once at the end.
1
func calculateBill(price, no int) int {
2
var totalPrice = price * no
3
return totalPrice
4
}
Copied!
Multiple return value:
1
func rectProps(length, width float64)(float64, float64) {
2
var area = length * width
3
var perimeter = (length + width) * 2
4
return area, perimeter
5
}
Copied!
Named returned value:
If a return value is named, it will be considered as a variable declared at the first line of the function. They don't need to return explicitly.
1
func rectProps(length, width float64)(area, perimeter float64) {
2
area = length * width
3
perimeter = (length + width) * 2
4
return //no explicit return value
5
}
Copied!
Blank identifier: _ is know as the blank identifier in Go. It can be used in place of any value of any type. It is used to discard a returned value.
1
func rectProps(length, width float64) (float64, float64) {
2
var area = length * width
3
var perimeter = (length + width) * 2
4
return area, perimeter
5
}
6
func main() {
7
area, _ := rectProps(10.8, 5.6) // perimeter is discarded
8
fmt.Printf("Area %f ", area)
9
}
Copied!

Packages

Packages are used to organise go source code for better reusability and readability.

main function and main package

Every executable go application must contain a main function. This function is the entry point for execution. The main function should reside in the main package.
First line of every go source file should be package packagename which indicate that this source file belong to which pakage.
Source files belonging to a package should be placed in separate folders of their own. It is a convention in Go to name this folder with the same name of the package.
Package Example:
Sample Go project structure:
1
src
2
|-- geometry
3
|-- geometry.go
4
|-- rectangle
5
|-- rectprops.go
Copied!
rectangle package:
1
//rectprops.go
2
package rectangle
3
4
import "math"
5
6
func Area(len, wid float64) float64 {
7
area := len * wid
8
return area
9
}
10
11
func Diagonal(len, wid float64) float64 {
12
diagonal := math.Sqrt((len * len) + (wid * wid))
13
return diagonal
14
}
Copied!
main package:
1
//geometry.go
2
package main
3
4
import (
5
"fmt"
6
"geometry/rectangle" //importing custom package
7
)
8
9
func main() {
10
var rectLen, rectWidth float64 = 6, 7
11
fmt.Println("Geometrical shape properties")
12
/*Area function of rectangle package used
13
*/
14
fmt.Printf("area of rectangle %.2f\n", rectangle.Area(rectLen, rectWidth))
15
/*Diagonal function of rectangle package used
16
*/
17
fmt.Printf("diagonal of the rectangle %.2f ",rectangle.Diagonal(rectLen, rectWidth))
18
}
Copied!

Exported Names

Any variable or function which starts with a capital letter are exported names in go. Only exported functions and variables can be accessed from other packages.

init function

Every package can have init function.
The init function should not have any return type and should not have any parameters.
The init function cannot be called explicitly in our source code.
init function structure:
1
func init() {
2
}
Copied!
The init function can be used to perform initialisation tasks and can also be used to verify the correctness of the program before the execution starts.
The order of initialisation of a package:
  1. 1.
    If a package imports other packages, the imported packages are initialised first.
  2. 2.
    Package level variables are initialised then.
  3. 3.
    init function is called next. A package can have multiple init functions (either in a single file or distributed across multiple files) and they are called in the order in which they are presented to the compiler.
A package will be initialised only once even if it is imported from multiple packages.
Initialisation Example:
rectangle package:
1
//rectprops.go
2
package rectangle
3
4
import "math"
5
import "fmt"
6
7
/*
8
* init function added
9
*/
10
func init() {
11
fmt.Println("rectangle package initialized")
12
}
13
func Area(len, wid float64) float64 {
14
area := len * wid
15
return area
16
}
17
18
func Diagonal(len, wid float64) float64 {
19
diagonal := math.Sqrt((len * len) + (wid * wid))
20
return diagonal
21
}
Copied!
main package:
1
//geometry.go
2
package main
3
4
import (
5
"fmt"
6
"geometry/rectangle" //importing custom package
7
"log"
8
)
9
/*
10
* 1. package variables
11
*/
12
var rectLen, rectWidth float64 = 6, 7
13
14
/*
15
*2. init function to check if length and width are greater than zero
16
*/
17
func init() {
18
println("main package initialized")
19
if rectLen < 0 {
20
log.Fatal("length is less than zero")
21
}
22
if rectWidth < 0 {
23
log.Fatal("width is less than zero")
24
}
25
}
26
27
func main() {
28
fmt.Println("Geometrical shape properties")
29
fmt.Printf("area of rectangle %.2f\n", rectangle.Area(rectLen, rectWidth))
30
fmt.Printf("diagonal of the rectangle %.2f ",rectangle.Diagonal(rectLen, rectWidth))
31
}
Copied!
Output:
1
rectangle package initialized
2
main package initialized
3
Geometrical shape properties
4
area of rectangle 42.00
5
diagonal of the rectangle 9.22
Copied!
The order of initialisation of main package,
  1. 1.
    Imported package are initialized first. Hence, rectangle package will be initialized first.
  2. 2.
    Package level variable rectLen and rectWidth are initialized then.
  3. 3.
    Then, init function of main package is called.
  4. 4.
    Finally, main function is called.

Use of blank identifier

Go does not allow to import any package without using it. So,
  • If we want to import a package without using now but we may use later.
  • Or, we want to make sure that initialization of a particular pakage happen even though we don't want to use it.
We can use blank identifier ( _ ).
1
package main
2
import (
3
_ "geometry/rectangle"
4
)
5
func main() {
6
}
Copied!

Conditional statement (if else)

Simple if structure:
1
if condition {
2
//statement
3
}
Copied!
if-else statement:
1
if condition {
2
//statement
3
} else {
4
//statement
5
}
Copied!
if - else if - else chain:
1
if condition {
2
//statement
3
} else if condition {
4
//statement
5
} else {
6
//statement
7
}
Copied!
if variant:
1
if statement; condition {
2
//statement
3
}
Copied!

Loop

Go has only for loop.
for loop structure:
1
for initialisation; condition; post {
2
//statement
3
}
Copied!
Example:
1
for i := 1; i <= 10; i++ {
2
fmt.Printf(" %d",i)
3
}
Copied!
break
1
for i := 1; i <= 10; i++ {
2
if i > 5 {
3
break //loop is terminated if i > 5
4
}
5
fmt.Printf("%d ", i)
6
}
Copied!
continue
1
for i := 1; i <= 10; i++ {
2
if i%2 == 0 {
3
continue
4
}
5
fmt.Printf("%d ", i)
6
}
Copied!
Variant:
1
for ;i <= 10; { // initialisation and post are omitted
2
fmt.Printf("%d ", i)
3
i += 2
4
}
Copied!
1
//multiple initialisation and increment
2
for no, i := 10, 1; i <= 10 && no <= 19; i, no = i+1, no+1 {
3
fmt.Printf("%d * %d = %d\n", no, i, no*i)
4
}
Copied!
Infinite loop:
1
for {
2
// statement
3
}
Copied!

Switch Statement

Structure:
1
switch value {
2
case 1:
3
// statement
4
case 2:
5
// statement
6
case 3:
7
// statement
8
default:
9
// statement
10
}
Copied!
Multiple Expression:
1
switch letter {
2
case "a", "e", "i", "o", "u": //multiple expressions in case
3
fmt.Println("vowel")
4
default:
5
fmt.Println("not a vowel")
6
}
Copied!
Expressionless switch:
switch is considered to be switch true and it will behave like if - else if chain.
1
switch { // expression is omitted
2
case num >= 0 && num <= 50:
3
fmt.Println("num is greater than 0 and less than 50")
4
case num >= 51 && num <= 100:
5
fmt.Println("num is greater than 51 and less than 100")
6
case num >= 101:
7
fmt.Println("num is greater than 100")
8
}
Copied!
Fallthrough:
When a case is executed, program control get out of the switch. A fallthrough statement is used to transfer control to the first statement of the case that is present immediately after the case which has been executed.
1
switch num := number(); { //num is not a constant
2
case num < 50:
3
fmt.Printf("%d is lesser than 50\n", num)
4
fallthrough
5
case num < 100:
6
fmt.Printf("%d is lesser than 100\n", num)
7
fallthrough
8
case num < 200:
9
fmt.Printf("%d is lesser than 200", num)
10
}
Copied!
Switch and case expressions need not be only constants. They can be evaluated at runtime too. In the program above num is initialised to the return value of the function number().
If the number is 75 then output will be.
1
75 is lesser than 100
2
75 is lesser than 200
Copied!
fallthrough should be the last statement in a case. If it present somewhere in the middle, the compiler will throw error fallthrough statement out of place