宏觀, 安裝, 配置, 工程命令, 標準命令, 語法
意味著版本與開發速度上的快速, 回顧看看C/C++ JAVA的歷史, 他們起初就不是開源
降低直譯式語言所需要的型別檢查成本
其實叫做跨平台支援......
自動, 甚至允許手動
可以先理解成比C語言的pthread輕量幾十倍的執行緒
goroutine, channel(後面會提)
同時具備 物件導向 函數編程
無繼承層次的輕量級物件導向
非侵入式接口(利於測試)
函數類型叫做第一等類性(後面會說明)
惰性求值
依賴管理明確
gc的能力使你不用過度干涉記憶體管理 大幅降低原始碼長度 開發效率提高
還要我說嗎?(去用Scala吧)
我看$不爽可以吧XD
效能
運行速度還不及
不然等著創造坑自己踩進去吧
Hello World
package main import "fmt" func main() { fmt.Printf("Hello World!\n") }
變數宣告
var x string = "Hello World" var y string y = "Hello World" z := "Hello World"
流程控制
// for i := 1 for i <= 10 { fmt.Println(i) i = i + 1 } // also for for i := 1; i <= 10; i++ { fmt.Println(i) } // add if for i := 1; i <= 10; i++ { if i%2 == 0 { fmt.Println(i, "even") } else { fmt.Println(i, "odd") } } // switch switch i { case 0: fmt.Println("Zero") case 1: fmt.Println("One")
陣列
// int array var x [5]int x[4] = 100 fmt.Println(x) //auto fill 0 with non-assignment // go through array var y [5]float64 y[0] = 98 y[1] = 93 y[2] = 77 y[3] = 82 y[4] = 83 var total float64 = 0 for i := 0; i < len(y); i++ { total += y[i] } fmt.Println("Total =", total) fmt.Println("Average =", total/float64(len(y))) //Mind len(y) is int // slice不固定大小的陣列( have append copy function....etc) z := make([]float64, 4, 10) fmt.Println(z) fmt.Println(y[1:4]) // same as python //append fmt.Println(append(z, 100, 200, 300, 400, 555, 666, 777, 888)) // Map, need memory malloc by using make elements := make(map[string]string) elements["H"] = "Hydrogen" elements["He"] = "Helium" elements["Li"] = "Lithium" elements["Be"] = "Beryllium" elements["B"] = "Boron" elements["C"] = "Carbon" elements["N"] = "Nitrogen" elements["O"] = "Oxygen" elements["F"] = "Fluorine" elements["Ne"] = "Neon" fmt.Println(elements["Li"]) fmt.Println(elements) // add if name, ok := elements["Li"] fmt.Println(name, ok) // Map in Map people := map[string]map[string]string{ "H": map[string]string{ "name": "Hydrogen", "state": "gas", }, "He": map[string]string{ "name": "Helium", "state": "gas", }, "Li": map[string]string{ "name": "Lithium", "state": "solid", }, "Be": map[string]string{ "name": "Beryllium", "state": "solid", }, "B": map[string]string{ "name": "Boron", "state": "solid", }, "C": map[string]string{ "name": "Carbon", "state": "solid", }, "N": map[string]string{ "name": "Nitrogen", "state": "gas", }, "O": map[string]string{ "name": "Oxygen", "state": "gas", }, "F": map[string]string{ "name": "Fluorine", "state": "gas", }, "Ne": map[string]string{ "name": "Neon", "state": "gas", }, } if el, ok := people["Li"]; ok { fmt.Println(el["name"], el["state"]) fmt.Println(el)
Normal
func average(scores []float64) (float64) { total := 0.0 for _, value := range scores { total += value } return total / float64(len(scores)) }
多個input參數
func add(arguments ...int) int { total := 0 for _, value := range arguments { total += value } return total }
Generator
func makeEvenGenerator() func() uint { i := uint(0) fmt.Println("this only be called once") return func() (ret uint) { ret = i i += 2 return } }
遞迴
func factorial(x uint) uint { if x == 0 { return 1 } return x * factorial(x-1) }
defer
func first() { fmt.Println("first") } func second() { fmt.Println("second") } func main() { defer first() second() } //output: //second //first
傳參數
func zero(x int) { x = 0 } func main() { x := 5 zero(x) fmt.Println(x) // x is still 5 }
傳參考
func zeroByRef(xPtr *int) { *xPtr = 0 } func main() { x := 5 zeroByRef(&x) fmt.Println(x) // x change to 0 }
傳指標變數
func two(xPtr *int) { *xPtr = 2 } func main() { xPtr := new(int) two(xPtr) fmt.Println(*xPtr) //xPtr is 2 }
交換變數的例子
func swap(x *int, y *int) { zPtr := new(int) *zPtr = *x *x = *y *y = *zPtr } func main() { var ( a = 2 b = 1 ) swap(&a, &b) fmt.Println("a =", a, "b =", b) }
Go千萬不要這樣實作
Go的變數參考可以略過那個tmp
func main() { var ( a = 2 b = 1 ) a, b = b, a fmt.Println("a =", a, "b =", b) }
Goroutine
func f(n int) { for i := 0; i < 10; i++ { fmt.Println(n, ":", i) amt := time.Duration(rand.Intn(250)) time.Sleep(time.Millisecond * amt) } } func main() { for i := 0; i < 10; i++ { go f(i) } var input string fmt.Scanln(&input) }
Goroutine IPC with channel
func tim(tim chan<- string) { // 傳入channal 然後一直將 "tim" send進去 tim這個channal for i := 1; ; i++ { // go's while ( true ) in C lang tim <- "tim" } } func randy(randy chan<- string) { //可以將傳入方向放在argument宣告 方便讀懂code 如果是雙向都要的時候就不指定方向 for i := 0; ; i++ { randy <- "randy" } } func receiveChannalAndPrint(leo <-chan string) { // 傳入 channal 然後每秒接收channal的內容 for { // another go's while ( true ) in C lang msg := <-leo fmt.Println(msg) time.Sleep(time.Second * 1) } } func main() { var c chan string = make(chan string) go tim(c) //相當於發起thread go randy(c) go receiveChannalAndPrint(c) var input string fmt.Scanln(&input) //故意讓主程式停住 }
Goroutine with Bufferd channel
chan1 := make(chan string, 10) chan2 := make(chan string, 10) go func() { for { chan1 <- "from tim" time.Sleep(time.Second * 1) } }() //很像Javascript吧XD go func() { for { chan2 <- "from randy" time.Sleep(time.Second * 1) } }() go func() { for { select { case msg1 := <-chan1: fmt.Println("message 1", msg1) case msg2 := <-chan2: fmt.Println("message 2", msg2) case <-time.After(time.Second): fmt.Println("timeout") default: fmt.Println("nothing") time.Sleep(time.Second * 1) } } }()
使用自定義/內建/第三方函式庫
使用自己的要注意目錄結構(除非你另外放在github上import)
package math
package math // Finds the average of a series of numbers func Average(xs []float64) float64 { total := float64(0) for _, x := range xs { total += x } return total / float64(len(xs)) }
package main
package main import ( "./math" "fmt" ) func main() { xs := []float64{1, 2, 3, 4} avg := math.Average(xs) fmt.Println(avg) }
沒有繼承問題
沒有侵入式接口問題
沒有非同步無法測試的問題(Javascript有實做一些方式幫助你處理)
方式你可能覺得跟Javascript超像
沒錯!! 因為它帶了Javascript的優良部份過來
說實在我沒有很喜歡XD
因為不太直觀
average.go
package math // Finds the average of a series of numbers func Average(xs []float64) float64 { total := float64(0) for _, x := range xs { total += x } return total / float64(len(xs)) }
average_test.go
package math import "testing" type testpair struct { values []float64 average float64 } var tests = []testpair{ {[]float64{1, 2}, 1.5}, {[]float64{1, 1, 1, 1, 1, 1}, 1}, {[]float64{-1, 1}, 0}, } func TestAverage(t *testing.T) { for _, pair := range tests { v := Average(pair.values) if v != pair.average { t.Error( "For", pair.values, "expected", pair.average, "got", v, ) } } }
跳坑玩家提供
https://github.com/stretchr/testifyadd.go
package math // Finds the sum of a series of numbers func Add(xs []float64) float64 { total := float64(0) for _, x := range xs { total += x } return total }
add_test.go
package math import ( "github.com/stretchr/testify/assert" "testing" ) type addtestpair struct { values []float64 sum float64 } var addtests = []addtestpair{ {[]float64{1, 2}, 3}, {[]float64{1, 1, 1, 1, 1, 1}, 6}, {[]float64{-1, 1}, 0}, {[]float64{1.1, 2.3}, 3.4}, } func TestAdd(t *testing.T) { for _, pair := range addtests { v := Add(pair.values) assert.Equal(t, v, pair.sum, "they should be equal") } }
就照著Google提供的規範走吧
package main import ( "fmt" "strings" ) func main() { fmt.Println( // true strings.Contains("test", "es"), // 2 strings.Count("test", "t"), // true strings.HasPrefix("test", "te"), // true strings.HasSuffix("test", "st"), // 1 strings.Index("test", "e"), // "a-b" strings.Join([]string{"a", "b"}, "-"), // == "aaaaa" strings.Repeat("a", 5), // "bbaa" strings.Replace("aaaa", "a", "b", 2), // []string{"a","b","c","d","e"} strings.Split("a-b-c-d-e", "-"), // "test" strings.ToLower("TEST"), // "TEST" strings.ToUpper("test"), ) }