Page 1 of 12
1. Variables
Declaration
var <var_name> int = 42
// name type value
or
i := 42
While initializing, we can omit the above things by:
i := 42
Note:
fmt.Printf is a format
%v→ value%T→ type
Types
intfloat32(later)
Multiple Declarations
var (
n int = 1
y int = 2
)
Note:
Shadowing works the same as C/C++. → Shadowing works the same as C++.
Note:
Unused variable is an error here. → Unused variables are an error here.
You can bypass this by using variable names as _.
Note:
- Lower case variable name → scope is package level
- Upper case variable name → global level scope
Page 2 of 12
Type Conversion
var i float32
i = int(i)
j := 42
var j string
j = string(i)
i := ""
// unicode-char
String conversion in GoLang is done by:
import (
"strconv"
)
strconv.Itoa(i)
2. Primitives
Note: All primitives have 0 as the default value.
Boolean
var n bool = true
Numeric
| Type | Default/Description | Type | Example |
|---|---|---|---|
| int | default int | float32 | var n float32 |
| int8 | float64 | n := 3.14 | |
| int16 | (float64) | ||
| int32 | |||
| int64 | |||
| byte | = uint8 | ||
| uint8 | |||
| uint16 | |||
| uint32 | |||
| uint64 |
Page 3 of 12
Complex Numbers
var n complex64 = 1 + 2i
// complex128
Functions:
real(n)
imag(n)
var n complex128 = complex(-5, 12)
Strings (Text)
var s string = "this is"
s[2]
// uint8/byte
s[2] = "u" // Strings are immutable, but can be concatenated.
Note:
We can convert a string into a collection of bytes:
b := []byte(s)
Runes
- Alias for
int32 - It is for UTF-32 encoded strings
3. Constants
const constVar int = 42 // Need to be initialized
- Constants can also be shadowed.
Page 4 of 12
Enumerated Constants
const (
a = iota
b
c
)
const (
x = iota
y
z
)
Note:
Newline is required in GoLang on semicolon.
const (
_ = iota
KB = 1 << (10 * iota)
MB
GB
)
A smart example of using iota.
Page 5 of 12
4. Arrays & Slices
grades := [3]int{97, 85, 93}
or
var grades [3]int
grades = [...]int{97, 85, 93}
grades[0] = 1
len(grades)gives length
Note:
There are pointers in arrays (GoLang):
a := [...]int{1, 2}
b := &a
Now, array's size needs to be known at compile time, so we use slices:
a := []int{1, 2, 3}
Note:
Slices are like objects (one change changes another reference).
b := a[1:2] // Slicing can be done on both arrays and slices.
Slice Operations
a = append(a, 1)
5. Maps & Structs
population := map[string]int{
"California": 24,
"Texas": 12,
}
population["NY"] = 120delete(population, "NY")
Page 6 of 12
type Doctor struct {
number int
name string
patients []string
}
aDoctor := Doctor{
number: 3,
name: "SK",
patients: []string{"Bro", "Go"},
}
aDoctor.name
GoLang doesn't support OOPs but can support composition by embedding structs.
6. If & Switch Statements
Note:
No single block statement in GoLang.
if true {
}
Operators:
switch value {
case 1:
case 2:
default:
}
- No
breakrequired. - If we do want to continue the case, we can use the
fallthroughkeyword. - Also, you can use
break(for loop interruption).
Page 7 of 12
Note:
There is no "comma" operator in GoLang.
7. Looping
for i := 0; i < 5; i++ {
}
Multiple variables:
for i, j := 0, 0; i < 5; i, j = i+1, j+2 {
}
For-range loop:
for k, v := range arr {
fmt.Printf(k, v)
}
- Same can be done for strings, maps.
Infinite loop:
for {
}
8. Defer, Panic, and Recover
defer → runs the statement at the end before function returns.
Note:
It does fast evaluate the statement but executes it at the end. → It evaluates the statement immediately but executes it at the end.
They all run in "LIFO" order.
a := "start"
defer fmt.Println(a)
a = "end"
- Output: "start"
Page 8 of 12
Panic
panic("some string")
- Usually done when program can't continue at all.
- It basically halts the program.
Recover
- Used to recover from panics.
- Only useful in deferred functions.
9. Pointers
var b *int = &a
*b // value of a
Note:
Pointer arithmetic is not available in GoLang.
We can have pointers to arrays, structs, maps, etc.
- "nil" is synonym to "NULL" in C/C++.
10. Functions
func <func_name> ret-type(param1 type, param2 type) {
// ...
}
Everything else is similar to C/C++.
Note:
There are anonymous functions in GoLang but lacks closures.
Page 9 of 12
11. Interfaces
- Describe behaviors (unlike structs which describe variables)
type <interface-name> interface {
Write([]byte) (int, error)
// Method Definition
}
type ConsoleWriter struct {}
func (cw ConsoleWriter) Write(data []byte) (int, error) {
n, err := fmt.Println(string(data))
return n, err
}
Embedding Interfaces
type WriterCloser interface {
Writer // ← Interface1
Closer // ← Interface2
}
12. Go-routines (Abstraction of Thread)
go func-routine()
- "Go" has a scheduler that runs these "small threads" called go-routines.
- Go is better because threads are lighter.
- Main function is another go-routine.
Page 10 of 12
Note:
We can create sync between different go-routines using "mutex".
import (
"sync"
)
var wg = sync.WaitGroup{}
var m = sync.Mutex{}
wg.Add(1)wg.Done()// reduces by 1wg.Wait()// waits for wg to equal 0
Note:
runtime.GOMAXPROCS(-1)
→ returns threads available.
runtime.GOMAXPROCS(10)
→ sets number of threads.
- Threading is also possible here.
Best Practices
- Don't create go-routines in libraries.
- Know how a go-routine will end.
- Check for race conditions at compile time:
go run -race ./main.go - It's better to have no go-routines when we need to create hard synchronization.
Page 11 of 12
13. Channels
- Ways to share data between go-routines while avoiding race conditions.
var wg = sync.WaitGroup{}
func main() {
ch := make(chan int)
wg.Add(2)
go func() {
i := <-ch // receive data from channel
fmt.Println(i) // 42
wg.Done()
}()
go func() {
ch <- 42 // send data to channel
wg.Done()
}()
wg.Wait()
}
- Each channel can only have 1 data at a time, so any other go-routine waits for channel to receive data.
- Channels are bi-directional but can be casted to uni-directional.
- Unless we use buffer channel:
ch := make(chan int, 50)
Page 12 of 12
sync.Cond (Condition Variable)
a) Some threads working on a shared data
b) Some process waiting for that "cond" to become true
var mu = sync.Mutex{}
cond := sync.NewCond(&mu)
go func() {
mu.Lock()
defer mu.Unlock()
cond.Broadcast()
}()
Main thread:
mu.Lock()
for cond=fals {
cond.Wait()
}
mu.Unlock()
References & Related Topics
- Official Go Documentation
- Go Tour: https://tour.golang.org/
- Go by Example: https://gobyexample.com/
- Related Topics: Goroutines, Channels, Mutexes, Interfaces, Type Assertions, Error Handling, Concurrency Patterns