Why Go : Easy to use and fast compile time
Features:
-Simple
-Fast compile times
-Auto and fast Garbage collected
-Better in concurrency
Go to https://tour.golang.org and check out all the details. Download Go from here : https://golang.org/dl/ It has nice play area for learning and practicing. Also Try Gopher Slack for GO community
Setting up the environment:
Try to put the absolute path if you are using editors
The installation directory is generally c:/go and it gets distributed in this path also
c:/users/username/go.
Try
GOPATH = Path to your local project
PATH = otherpaths; c:/users/username/go
Now check the installation by going to command prompt and type : “go version”.
Let’s start with sample code:
package main
import “fmt”
func main() {
fmt.Println(“HI”)
}
Here the package name should be declared and main is by default the starting package name, and similarly func main is the entry point of the program
Running and creating executables
I have project name demo1 in folder c:/work/go
To run the file directly, which prints HI
C:\work\go\demo1>go run src/Main.go
Hi
To create executable in bin folder
C:\work\go\demo1>go build test
C:\work\go\demo1>go install test
C:\work\go\demo1\bin>test.exe
HI
Variables
package main
import “fmt”
func main() {
var one int = 1
var two int
two = 2
three := 3
fmt.Printf(“variable name %v and type %T \n”, one, one)
fmt.Printf(“variable name %v and type %T \n”, two, two)
fmt.Printf(“variable name %v and type %T \n”, three, three)
}
C:\work\go\demo1>go run src/test/Main.go
variable name 1 and type int
variable name 2 and type int
variable name 3 and type int
The variable name can be lazy initialized like variable two in above code or directly assigned like variable one above. We can also use := syntax which allows GO compiler to auto detect the type
We can also create variable blocks where we remove the extra var clutter
var(
abc string “one”
def string “two”
i int 2
)
Shadowing: The variable declared in the functions/local overrides the value defined in package level
Local variable which are declared and not used will throw compile time errors
Variables naming conventions and scopes:
Lowercase first letter > scope within package > var e int =0
Uppercase first letter > scope is global and outside package > var E int =0
Within block > scope is within block of code > func abc{ var E int =0}
Working with Strings
Use “strconv” library for converting ints to strings, and if we directly typecast, then we will get asci value of that.We can use strconv.Itoa(i)
Imaginary variables in complex variables: we can declare complex variables having imaginary i value
func main() {
k := 1 + 3i
var b complex64 = 2 + 2i
var c complex64 = complex(3, 4)
fmt.Println(k)
fmt.Println(b)
fmt.Println(c)
}
C:\work\go\demo1>go run src/test/Main.go
(1+3i)
(2+2i)
(3+4i)
Iota: we can use iota as counters. It starts with value 0 and then increments whenever used in that block
const (
a = iota
b = iota
c = iota
d = iota
)
func main() {
fmt.Print(“a , b, c, d “, a, b, c, d)
}
C:\work\go\demo1>go run src/test/Main.go
a , b, c, d 0 1 2 3
Arrays and Slices
Initializing arrays: Ist value is the length of array and then type and if we don’t specify the size, a slice is created
arr := [4]string{“a”, “b”, “c”, “d”}
bb := []int{2, 3}
In arrays, if we copy and change data, the data gets changed in later one only. However, in slice, they both will point to same reference and this on change, both variables gets updated.Arrays have fixed length, whereas slices has variable length. Slices almost doubles up their size when we add new element.
Using make function to create arrays
a := […]int{1, 2, 3, 4}
b := make([]int, 3) // make array of size 3
c := make([]int, 4, 10) // make array of size 3 and capacity 10
fmt.Println(len(a))
fmt.Println(len(b))
fmt.Println(len(c))
C:\work\go\demo1>go run src/test/Main.go
4
3
4
Use of append for slices
a := []int{1, 2, 3, 4}
a = append(a, 5, 1)
fmt.Println(a)
C:\work\go\demo1>go run src/test/Main.go
[1 2 3 4 5 1]
Pointers: Pointers are defined by ‘&’ which specifies that the value will point to the reference of the assigned variable.
Maps and Structs
Ways of making maps
func main() {
m := map[string]int{
“aa”: 12,
“bb”: 13,
}
m2 := make(map[string]int, 5)
fmt.Println(m)
fmt.Println(m2)
}
C:\work\go\demo1>go run src/test/Main.go
map[aa:12 bb:13]
map[]
Some functions of map
m := map[string]int{
“aa”: 12,
“bb”: 13,
}
fmt.Println(m[“aa”]) //prints the value from key
value1, ok := m[“aa”] //, ok check if value exists
fmt.Println(value1, ok) //print value and ok
value1, ok = m[“aa11”] //, ok check if value exists (not existing key)
fmt.Println(value1, ok) //print value and ok
fmt.Println(len(m)) //length of map
fmt.Println(m)
C:\work\go\demo1>go run src/test/Main.go
12
12 true
0 false
2
map[aa:12 bb:13]
Maps are collections having key/value pair and can be created using make or literals.
We can use “check, ok” for checking if there is key in the map. If there is no value, check will have “0” default value and “ok” will be false.
Struct : can hold data of any types. We can consider that as Java classes having different attributes.
type Person struct {
id int
name string
department string
roles []string
}
func main() {
p := Person{
id: 1,
name: “fname”,
department: “finance”,
roles: []string{“HR”, “Maintenance”},
}
fmt.Println(p) //prints the value struct person
}
C:\work\go\demo1>go run src/test/Main.go
{1 fname finance [HR Maintenance]}
Data References: Unlike slices and maps, structs refer to independent references. If we assign struct value to other variable and then change the value in that variable, the current one will still have its old value.
There is no inheritance in golang, but we have composition.
Structs also allow tags which are a nice feature, wherein we can specify some properties, like field validations also. It needs “reflect” package
import (
“fmt”
“reflect”
)
type Person struct {
id int
name string `required`
}
func main() {
p := reflect.TypeOf(Person{})
field, _ := p.FieldByName(“name”)
fmt.Print(field.Tag)
}
C:\work\go\demo1>go run src/test/Main.go
required
If Statements:
func main() {
var i int = 32
if i == 1 {
fmt.Print(“1st condition true”)
} else if i == 2 {
fmt.Print(“1st else if condition true”)
} else {
fmt.Print(“default condition”)
}
The rules are the same as like other languages.
Switch
func main() {
switch “test” {
case “a”:
{
fmt.Print(“case1”)
}
case “test”:
{
fmt.Print(“case2”)
}
default:
{
fmt.Print(“case3”)
}
}
}
C:\work\go\demo1>go run src/test/Main.go
case2
Same applies for switch also where all rules are almost similar to other languages.
For loops
for i := 0; i < 3; i++ {
fmt.Print(i)
}
We can use the above format to create a for a loop.
Defer and panic
Defer statement which is generally used to close the resources are called after the function completes
Defer uses Lifo if there are multiple defers in a function.
Panic is like exceptions.
Panic always happens after defer.
Recover : Recover can be used to come out from panic mode.
Goroutines
These are like threads in GoLang
Add “go” in front of statement and it will be executed as a separate thread
We can also use the wait group to tell the compiler about the threads status.
var waitGroup = sync.WaitGroup{} //creates a wait group
func main() {
fmt.Println(“start”)
waitGroup.Add(1) //tells the waitgroup to add thread
go hello() // calls the thread/goroutine
waitGroup.Wait() //wait till the thread is compelted
fmt.Println(“end”)
}
func hello() {
fmt.Println(“hello”)
waitGroup.Done() // tells the waitgroup that it is done.
}