Golang
[WIP]
Todo
- [x] Functions
- [x] Array & Slices
- [ ] Structures, Methods
- [ ] Interface
- [ ] Errors
Functions
Call by Value
func foo(y int){
y = y+2
}
func main(){
x := 2
foo(x)
fmt.Println(x)
}
- Pros : Encapsulation
- Cons : Copy time
Call by Pointers
func foo(y *int){
*y = *y+2
}
func main(){
x := 2
foo(&x)
fmt.Println(x)
}
- Pros : No extra copy time
- Cons : No encapsulation
Functional cohesion : Function should perform only one "operation"
Function are first-class
Variables as functions
func incFunc(x int) int {
return x+1
}
func main(){
var funcVar func(int) int
funcVar = incFunc
fmt.Println(funcVar(1))
}
Functions as arguments
func applyIt( afx func (int) int,
val int) int{
return afx(val)
}
Anonymous functions / Lambda functions
func applyIt( afx func (int) int, val int) int{
return afx(val)
}
func main(){
v := applyIt(
func (x int) int {return x + 1}, 2)
fmt.Println(v)
}
Passing a function as an argument implies passing the closure (function + environment). For example, in the following code, originX and originY are set for the new function which is then returned by MakeDistOrigin.
Returning functions
func MakeDistOrigin(originX, originY float64)
func (float64, float64) float64 { // Return type
fn := func (x , y float64) float64 {
return math.Sqrt( math.Pow(x-originX,2) + math.Pow(y-originY,2) )
}
return fn
}
func main(){
Dist1 := MakeDistOrigin(0,0)
Dist2 := MakeDistOrigin(1,1)
fmt.Println(Dist1(1,1)) // 1.4142135623730951
fmt.Println(Dist2(1,1)) // 0
}
Variadic functions treat multiple input arguments as a slice. They could also accept a slice as an argument (requires ... prefix)
Variadic functions
func getMax(vals ...int) int {
maxVal := -1
for _,v := range vals{
if v > maxVal {
maxVal = v
}
}
return maxVal
}
func main(){
vslice := []int{1,2,3,4,10}
fmt.Println(getMax(vslice...))
}
Deferred function call
func main(){
defer fmt.Println("Bye")
fmt.Println("Hello")
}
Arguments of deferred function calls are evaluated immediately
Deferred function call
func main(){
i := 1
defer fmt.Println(i+1)
i++
fmt.Println("Hello")
}
The above code will print "Hello 2"
Arrays and Slices
Slices contain a pointer to the array. Try to use slices, specially when passing array pointers.
Bad : Passing arrays using pointers
func foo(x *[3]int){
(*x)[0] = (*x)[0]+1
}
func main(){
a := [3]int{1,2,3}
foo(&a)
fmt.Println(a[0])
}
Good : Using slices
func foo(sli int){
sli[0] = sli[0] + 1
}
func main(){
a := []int{1,2,3}
foo(a)
fmt.Println(a)
}
Channels
Concurrency != Parallelism
c1 := make(chan string)
...
func f(c chan string)
Channels are 'blocking' in nature.
Always a good practice to close channel from sender's end. Closing a channel from receivers end might cause sender to panic.