這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
寫在前面
Golang的文法足夠簡單,但變化很多,剛接觸只需要掌握典型的用法即可,不需要知道所有的文法糖,所以代碼中並不會包含所有可能的文法形式。
並發是Golang的一大主題,後續有專門的一節,並不出現在這一節。
還有一些『約定』:
- 可見度。Java中有private,protect,public。Golang預設採用首字母大小寫來判斷:首字母大寫的變數、方法為public,所有範圍內可見;首字母小寫為private,本檔案內可見。
- 簡潔性。import引入的包以及定義的變數必須被使用,否則程式編譯不通過。因此,代碼
var p ClassA
不是一個聲明定義,而是包含了初始化,實際上記憶體已經被分配了,這一點很容易忽視。
下面上代碼:
//一段普通的Go語言代碼,用於go語言學習,作者知米無忌於2016-11-29//聲明包,包名和目錄的路徑一致,以$GOPATH/src為根,如src/math/add.go的包為math。// 此外,如果為入口(即包含main函數)則包名為main,此時可以被go build編譯為可執行檔。package main//塊狀import注意://import必須被使用,不能import了但不用他import ( "fmt" "strconv" "reflect")//塊狀定義變數var ( // int 類型包括了rune, int8, int16, int32, int64和byte, uint8, uint16, uint32, uint64。其中rune是int32的別稱,byte是uint8的別稱。 myInt int //float 包括了float32,float64 myFloat float32 myBool bool myString string)//塊狀聲明常量const ( constString = "hello world,世界")// 全域單獨定義的變數var globalDefinedVar interface{}// 定義一個結構體(也是類,因為golang沒有類的概念),物件導向type person struct { name string age int}//person 的成員函數,顯式的指定p,即Java中的this指標,python中的函數第一個參數selffunc (p *person) introduceMyself() { fmt.Println("my name is " + p.name) fmt.Println(p.age)}func (p *person) shoot() { fmt.Println("I can shoot, so I can play football.")}//定義一個介面type footballPlayer interface { shoot()}func main() { //////////// // 1.變數定義 //////////// var localString string localString = `字串是 一對雙引號(表示單行)或反引號(表示多行) 括起來定義` //////////// // 2.rune, byte數組,string的關係 //////////// myRune := '我' fmt.Println(myRune) //rune轉為string myRuneString:= string(myRune) fmt.Println(myRuneString) //rune轉為位元組數組 bytes:=[]byte(myRuneString) fmt.Println(bytes) // interface{} 類型可賦值任意類型,類似Java的Object類型 globalDefinedVar = localString newVar := ":=是聲明並初始化的簡寫形式,由系統自動推測類型" fmt.Println(newVar) //////////// // 3.數組定義並初始化 //////////// myArray := [3]int{1, 2, 3} //數組定義,預設初始化為了5個0 var myArray2 [5]int fmt.Println(myArray2) fmt.Println(myArray) //////////// // 4.slice //////////// mySlice := []int{1, 2, 3, 4} //從數組建立slice,注意1:的使用方式,從第一個元素取到末尾,還可以[1:4]從第一個取到第四個(不包含)。來自於python(作者注) mySlice2 := myArray[1:] mySlice=append(mySlice,5,6,7) //////////// // 5.if,else塊沒什麼特殊,myBool未定義預設為false,執行else //////////// if myBool { fmt.Println("if") } else { fmt.Println("else") } //////////// // 6.for 迴圈 //////////// for index, value := range mySlice { fmt.Printf("index: %d,value:%d \n", index, value) } for (true) { fmt.Println("還可以這樣使用,相當於while(true)") //避免無限迴圈,直接break掉 break } //////////// // 7.map建立,刪除和使用,range關鍵字使用 //////////// myMap := make(map[string]int) myMap["a"] = 1 myMap["b"] = 2 myMap["c"] = 3 delete(myMap, "a") for key, value := range myMap { fmt.Printf("key: %s,value:%d", key, value) } //////////// // 8.物件導向 //////////// // 對象初始化的兩種方式,第一種返回的是指標,第二種返回的是對象。 //注意new永遠返回指標 jack := new(person) jack.name = "jack" jack.age = 17 amy := person{"amy", 16} jack.introduceMyself() //證明是指標 (*jack).introduceMyself() amy.introduceMyself() //拋異常 invalid indirect of amy (type person) //(*amy).introduceMyself() fmt.Println(reflect.TypeOf(jack)) fmt.Println(reflect.TypeOf(amy)) //////////// // 9.介面使用 //////////// //介面的賦值,可以看出來不需要jack的person類實現該介面就可以實現,只需要擁有介面所需的功能即可。 var footballPlayer1 = jack footballPlayer1.shoot() //函數調用,可以多傳回值 myString = "golang is awesome" myRet1, myRet2 := receive2Return2(myString, myInt) fmt.Println(myRet1, myRet2) //////////// // 10.異常處理 //////////// //錯誤處理,調用了一個拋異常的方法 malfunction() //兩個知識點: //1.recover會收集到由調用棧中的panic拋出的異常資訊 //2.defer的執行時機是執行defer的函數退出的時候,類似於java中的finally,但是不需要把一大段代碼用大括弧包圍,這樣代碼層次減少了。 defer func() { if err := recover(); err != nil { fmt.Println(err) } }() //每個定義過的變數和常量都要被使用,不允許垃圾存在,這裡做個列印 fmt.Println(myBool, myFloat,constString,mySlice2)}func receive2Return2(param1 string, param2 int) (ret1 string, ret2 int) { fmt.Println("param1:" + param1) fmt.Println("param2:" + strconv.Itoa(param2)) return "returned " + param1, param2 + 1}func malfunction() { panic("some thing went wrong!")}