Last active
November 16, 2020 16:49
-
-
Save mingen-pan/170a79709065df8ebd7a84149e1c9016 to your computer and use it in GitHub Desktop.
Basic Go examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package tutorial | |
import ( | |
"fmt" | |
"math/rand" | |
"strconv" | |
"sync" | |
"testing" | |
"time" | |
) | |
func TestGoBasic(t *testing.T) { | |
// Define variable | |
// name and type, different from C. | |
var a int | |
// Type inference | |
// Think about the auto in C++ | |
b := 2 | |
a = b + 1 | |
// If-else statement | |
// No need to use parenthesis | |
if a > 0 { | |
fmt.Println("I am good") | |
} else { | |
fmt.Println("I am bad") | |
} | |
// static array | |
arr := [3]int{1, 2, 3} | |
for i, num := range arr { | |
fmt.Printf("arr[%v]= %v\n", i, num) | |
} | |
// Dynamic Array | |
dynArray := make([]int, 10) | |
fmt.Printf("len(dynArray) = %d\n", len(dynArray)) // size = 10 | |
dynArray = make([]int, 0, 10) | |
fmt.Printf("len(dynArray) = %d, cap(dynArray)= %d\n", | |
len(dynArray), cap(dynArray)) // size = 0, capacity = 10 | |
for i := 0; i < 10; i++ { | |
dynArray = append(dynArray, i*i) | |
} | |
fmt.Printf("len(dynArray) = %d, cap(dynArray)= %d\n", | |
len(dynArray), cap(dynArray)) // size = 10, capacity = 10 | |
// dynamic map | |
myMap := make(map[string]string) | |
myMap["key"] = "value" | |
myMap = map[string]string{ | |
"key1": "value1", | |
"key2": "value2", | |
"key3": "value3", | |
} | |
for k, v := range myMap { | |
fmt.Printf("map[%s]=%s\n", k, v) | |
} | |
} | |
func sleepAndPrint(num int) { | |
time.Sleep(time.Duration(num) * time.Millisecond) | |
fmt.Print(num, " ") | |
} | |
func TestGoRoutine(t *testing.T) { | |
arr := []int{5, 3, 2, 1, 4, 10, 12, 6} | |
// Lambda Expression is allowed in Go | |
// The slice []int is reference, so there is no need to use pointer. | |
sleepSort := func(arr []int) { | |
for _, num := range arr { | |
go sleepAndPrint(num) | |
} | |
} | |
sleepSort(arr) | |
time.Sleep(1 * time.Second) | |
fmt.Println() | |
} | |
func sleepAndReturn(num int, c chan int) { | |
time.Sleep(time.Duration(num) * time.Millisecond) | |
c <- num | |
} | |
func TestChannel(t *testing.T) { | |
arr := []int{5, 3, 2, 1, 4, 10, 12, 6} | |
// Lambda Expression is allowed in Go | |
// The slice []int is reference, so there is no need to use pointer. | |
sleepSort := func(arr []int) { | |
// make a channel with size of the array | |
c := make(chan int, len(arr)) | |
for _, num := range arr { | |
go sleepAndReturn(num, c) | |
} | |
for i := 0; i < len(arr); i++ { | |
num := <-c | |
fmt.Print(num, " ") | |
} | |
} | |
sleepSort(arr) | |
fmt.Println() | |
} | |
type Entry struct { | |
// Capitalization means public | |
Index int | |
// private variable can be only accessed by the same package | |
val string | |
} | |
// Type method | |
func (entry Entry) increaseIndexByOneFake() { | |
entry.Index++ | |
} | |
func (entry *Entry) increaseIndexByOneReal() { | |
entry.Index++ | |
} | |
func increaseIndexByOneAnotherWay(entry *Entry) { | |
entry.Index++ | |
} | |
func TestPointer(t *testing.T) { | |
entry := Entry{ | |
Index: 0, | |
val: "val", | |
} | |
fmt.Println("index: " + strconv.Itoa(entry.Index)) | |
entry.increaseIndexByOneFake() | |
fmt.Println("index: " + strconv.Itoa(entry.Index)) | |
entry.increaseIndexByOneReal() | |
fmt.Println("index: " + strconv.Itoa(entry.Index)) | |
increaseIndexByOneAnotherWay(&entry) | |
fmt.Println("index: " + strconv.Itoa(entry.Index)) | |
} | |
func printType(i interface{}) { | |
switch v := i.(type) { | |
case int: | |
fmt.Printf("%v is int\n", v) | |
case string: | |
fmt.Printf("%v is string\n", v) | |
default: | |
fmt.Printf("I don't know about type %T!\n", v) | |
} | |
} | |
func TestTypeCasting(t *testing.T) { | |
var i interface{} = "hello" | |
s := i.(string) | |
fmt.Println(s) | |
s, ok := i.(string) | |
fmt.Println(s, ok) | |
f, ok := i.(float64) | |
fmt.Println(f, ok) | |
//f = i.(float64) // panic | |
//fmt.Println(f) | |
printType(10) | |
printType("abc") | |
printType(nil) | |
printType(12.2) | |
} | |
func goodLockHabit(lock *sync.Mutex) int { | |
lock.Lock() | |
defer lock.Unlock() | |
// Early stop | |
// Don't have to unlock before every return | |
if rand.Int()%2 == 0 { | |
return 1 | |
} | |
// more logic | |
// ... | |
return 0 | |
} | |
func badLockHabit(lock *sync.Mutex) int { | |
lock.Lock() | |
// Early stop | |
if rand.Int()%2 == 0 { | |
return 1 | |
} | |
// more logic | |
// ... | |
lock.Unlock() | |
return 0 | |
} | |
func TestLock(t *testing.T) { | |
lock := sync.Mutex{} | |
for i := 0; i < 10; i++ { | |
// There will be no dead lock don't worry | |
goodLockHabit(&lock) | |
} | |
defer func() { | |
if recover() != nil { | |
fmt.Println("A dead lock happens") | |
} | |
}() | |
for i := 0; i < 10; i++ { | |
// you will lock it twice sometime | |
badLockHabit(&lock) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment