package main
import (
"errors"
format "fmt"
"math/rand"
"strconv"
"sync"
)
// single way channel
type Sender chan<- int
type Receiver <-chan int
type Animal interface {
Grow()
Move(string) string
}
type Cat struct {
Name string
Age int
Status string
}
func (cat *Cat) Grow() {
}
func (cat *Cat) Move(x string) string {
return "nil"
}
func main() {
// variable
var x int = 3
// array
var numbers [2]int
numbers[0] = 0
numbers[1] = 1
// alternative initialize method
var ori = [5]int{1, 2, 3, 4, 5}
tmpSlice := ori[2:]
format.Print("xxx")
format.Print(x)
format.Print(len(numbers))
format.Print(tmpSlice)
// slice
var numbers3 = [5]int{1, 2, 3, 4, 5}
slice3 := numbers3[2 : len(numbers3) - 1]
length := (2) // length is the size
capacity := (3) // capacity is the span from the starting index of the index to the final index of the original array
format.Printf("%v, %v\n", (length == len(slice3)), (capacity == cap(slice3)))
// map
mm2 := map[string]int{"golang": 42, "java": 1, "python": 8}
mm2["scala"] = 25
mm2["erlang"] = 50
mm2["python"] = 0
format.Printf("%d, %d, %d \n", mm2["scala"], mm2["erlang"], mm2["python"])
// channel
ch2 := make(chan string, 1)
go func() {
ch2 <- ("Arrived!")
}()
var value string = "Data"
getFromChannel, ok := <- ch2
value = value + (getFromChannel) + strconv.FormatBool(ok)
format.Println(value)
// declare buffer as 0 to make a block channel
var myChannel = make(chan int, (0))
var number = 6
var wg sync.WaitGroup
wg.Add(2)
go func() {
var sender Sender = myChannel
sender <- number
format.Println("Sent!")
wg.Done()
}()
go func() {
var receiver Receiver = myChannel
format.Println("Received!", <-receiver)
wg.Done()
}()
wg.Wait()
// until 'Received', the 'Sent' go routine stops
myCat := Cat{"Little C", 2, "In the house"}
// type assert
animal, ok := interface{}(&myCat).(Animal)
format.Printf("%v, %v\n", ok, animal)
// logic control
var num int = 5
if num += 4; 10 > num {
// 标识符重声明
var num int
num += 3
format.Print(num) // print 3 here
} else if 10 < num {
num -= 2
format.Print(num)
}
// inner num variable life cycle ends, here print the outer num variable, 5 + 4 = 9
format.Println(num) // print 9 here
// slice of empty interface, which could be used to refer to any variable
ia := []interface{}{byte(6), 'a', uint(10), int32(-4)}
switch v := ia[rand.Intn(4) % 2]; interface{}(v).(type) {
case rune:
format.Println("Case A.")
case byte :
format.Println("Case B.")
default:
format.Println("Unknown!")
}
// iteration
map1 := map[int]string{1: "Golang", 2: "Java", 3: "Python", 4: "C"}
for k, v := range(map1) {
format.Printf("%d: %s\n", k, v)
}
// select clause combine with case to control channel behavior
selectTest()
// defer clause, make the referring statement to be executed at the end of the method
// if multiple statements, should be executed from down to top
downTop(3)
//time.Sleep(time.Second)
format.Println("Enter main")
// recover must run with defer
defer globalRecover()
outerFunc()
format.Println("Quit main")
/**
缓冲的channel:保证往缓冲中存数据先于对应的取数据,简单说就是在取的时候里面肯定有数据,否则就因取不到而阻塞。所以缓冲的channel可能在取数据的时候发生阻塞。
非缓冲的channel:保证取数据先于存数据,就是保证存的时候肯定有其他的goroutine在取,否则就因放不进去而阻塞。所以非缓冲的channel可能在存数据的时候会发生阻塞。
*/
}
func downTop(n int) {
for i := 0; i < n; i++ {
defer format.Println("down top" + strconv.Itoa(i))
}
}
func selectTest() {
ch4 := make(chan int, 1)
for i := 0; i < 4; i++ {
select {
case e, ok := <-ch4:
if !ok {
format.Println("End.")
return
}
format.Println(e)
// close the channel to make
// e, ok := <-ch4:
// ok = false
close(ch4)
default:
format.Println("No Data!")
ch4 <- 1
}
}
}
func innerFunc() {
format.Println("Enter innerFunc")
panic(errors.New("Occur a panic!"))
format.Println("Quit innerFunc")
}
func outerFunc() {
format.Println("Enter outerFunc")
innerFunc()
format.Println("Quit outerFunc")
}
func globalRecover() {
if p := recover(); p != nil {
format.Printf("Fatal error: %s\n", p)
}
}