• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            30分鐘上手GO語言--基礎語法

            轉載自:http://studygolang.com/topics/548

            本章主要分成三個部分:第一部分包括基本語法和數據結構;第二部分討論方法和接口;第三部分介紹并發機制。 包、變量和函數 先看一個例子Packages.go:

            package main  import (     "fmt"     "math/rand" )  func add(x int, y int) int {     return x + y }  func main() {     fmt.Println("My favorite number is", rand.Intn(10))     fmt.Println(add(42, 13)) } 

            包:每個 Go 程序都是由包(package)組成的,程序運行的入口是包 main

            導入:這個代碼用圓括號組合了導入,這是“打包”導入語句。同樣可以編寫多個導入語句,例如:

            import "fmt" import "math" 

            這個程序使用并導入了包 "fmt" 和 "math/rand"。包名與導入路徑的最后一個目錄一致。例如,如果你導入了"math/rand",那么你就可以在程序里面直接寫rand.Intn(10),但如果你導入的是"math",那么你就得寫math.rand.Intn(10)。

            函數:函數可以沒有參數或接受多個參數。在這個例子中,add 接受兩個 int 類型的參數,注意類型在變量名之后。有沒有覺得很奇怪呢,下面就詳細解釋一下go這樣做的原因。 看一個c的例子:

            int (*fp)(int (*ff)(int x, int y), int b) 

            我相信學過c的同學為了看懂這個都下了不少功夫吧,有沒有感覺到痛苦或者說痛苦之后的那一點點優越感。 什么?你還能看懂?那么再來一個:

            int (*(*fp)(int (*)(int, int), int))(int, int);// 10s內看懂的同學給我回復下這個定義是啥,我請你吃飯。 

            用go語言的話這兩個例子的定義如下:

            f func(func(int,int) int, int) int f func(func(int,int) int, int) func(int, int) int 

            是不是清晰多了,原來f返回的是一個函數啊。。。

            函數參數: 當兩個或多個連續的函數命名參數是同一類型,則除了最后一個類型之外,其他都可以省略,比如func add(x int, y int) int可以寫為func add(x, y int) int 函數返回值:

            函數可以返回任意數量的返回值,比如func swap(x, y string) (string, string)。 并且,函數的返回值還可以被命名,并且像變量那樣使用,比如

            func split(sum int) (x, y int) {     x = sum * 4 / 9     y = sum - x     return } 

            沒有參數的 return 語句返回結果的當前值。 變量: var 語句定義了一個變量的列表;跟函數的參數列表一樣,類型在后面,可以定義在包或函數級別。比如:

            package main import "fmt" var c, python, java bool func main() {     var i int     fmt.Println(i, c, python, java) } 

            變量的初始化: 變量定義可以包含初始值,每個變量對應一個。如果初始化是使用表達式,則可以省略類型;變量從初始值中獲得類型。比如:var i, j int = 1, 2或者var c, python, java = true, false, "no!" 短聲明變量:在函數中,:= 簡潔賦值語句在明確類型的地方,可以用于替代 var 定義。 函數外的每個語句都必須以關鍵字開始(varfunc、等等),:= 結構不能使用在函數外。比如:

            package main import "fmt" func main() {     var i, j int = 1, 2     k := 3     c, python, java := true, false, "no!"     fmt.Println(i, j, k, c, python, java) } 

            Go的基本類型:這里先簡單列一下,后面再具體講

            bool string int  int8  int16  int32  int64 uint uint8 uint16 uint32 uint64 uintptr byte // uint8 的別名 rune // int32 的別名// 代表一個Unicode碼 float32 float64 complex64 complex128 

            零值:變量在定義時沒有明確的初始化時會賦值為零值。數值類型為 0,布爾類型為 false,字符串為 ""。 類型轉換:Go 的在不同類型之間的項目賦值時需要顯式轉換。表達式 T(v) 將值 v 轉換為類型 T。比如:

            var i int = 42 var f float64 = float64(i) var u uint = uint(f) 

            或者,更加簡單的形式:

            i := 42 f := float64(i) u := uint(f) 

            類型推導:在定義一個變量但不指定其類型時(使用沒有類型的 var 或 := 語句), 變量的類型由右值推導得出。 var i int j := i // j 也是一個 int 但是當右邊包含了未指名類型的數字常量時,新的變量就可能是 int 、 float64 或complex128。 這取決于常量的精度:

            i := 42           // int f := 3.142        // float64 g := 0.867 + 0.5i // complex128 

            常量:常量的定義與變量類似,只不過使用 const 關鍵字,常量可以是字符、字符串、布爾或數字類型的值,常量不能使用 := 語法定義。 流程控制語句 for循環:Go 只有一種循環結構for循環。基本的 for 循環除了沒有了 ( ) 之外(,看起來跟 C 或者 Java 中做的一樣,而 { } 是必須的。比如:

            package main import "fmt" func main() {     sum := 0     for i := 0; i < 10; i++ {         sum += i     }     fmt.Println(sum) } 

            死循環:如果省略了循環條件,循環就不會結束,因此可以用更簡潔地形式表達死循環。

            package main func main() {     for {     } } 

            If語句:if 語句除了沒有了 ( ) 之外,看起來跟 C 或者 Java 中的一樣,而 { } 是必須的。

            func sqrt(x float64) string {     if x < 0 {         return sqrt(-x) + "i"     }     return fmt.Sprint(math.Sqrt(x)) } 

            可以在if條件之前執行一個簡單的語句,由這個語句定義的變量的作用域僅在 if 范圍之內,比如:

            func pow(x, n, lim float64) float64 {     if v := math.Pow(x, n); v < lim {         return v     }     return lim } 

            在 if 的便捷語句定義的變量同樣可以在任何對應的 else 塊中使用,比如:

            func pow(x, n, lim float64) float64 {     if v := math.Pow(x, n); v < lim {         return v     } else {         fmt.Printf("%g >= %g\n", v, lim)     }     // 這里開始就不能使用 v 了     return lim } 

            Switch語句:switch 的條件從上到下的執行,當匹配成功的時候停止,除非以 fallthrough 語句結束,否則分支會自動終止。比如:

            switch i { case 0: case f(): } 

            當 i==0 時不會調用 f。沒有條件的 switch 同 switch true 一樣,這一構造使得可以用更清晰的形式來編寫長的 if-then-else 鏈。

            func main() {     t := time.Now()     switch {     case t.Hour() < 12:         fmt.Println("Good morning!")     case t.Hour() < 17:         fmt.Println("Good afternoon.")     default:         fmt.Println("Good evening.")     } } 

            Defer語句:defer 語句會延遲函數的執行直到上層函數返回,延遲調用的參數會立刻生成,但是在上層函數返回前函數都不會被調用。比如打印hello world:

            func main() {     defer fmt.Println("world")     fmt.Println("hello") } 

            延遲的函數調用被壓入一個棧中。當函數返回時, 會按照后進先出的順序調用被延遲的函數調用。

            func main() {     fmt.Println("counting")     for i := 0; i < 10; i++ {         defer fmt.Println(i)     }     fmt.Println("done") } 

            輸出

            counting done 9 8 7 6 5 4 3 2 1 0 

            這個功能用來做清理工作非常清晰且強大,可以用結構化編程的思路處理面向對象編程中類似析構函數的功能。舉一個實際點的例子:

            func CopyFile(dstName, srcName string) (written int64, err error) {     src, err := os.Open(srcName)     if err != nil {         return     }     defer src.Close()      dst, err := os.Create(dstName)     if err != nil {         return     }     defer dst.Close()      return io.Copy(dst, src) } 

            復雜類型 指針:Go 具有指針。 指針保存了變量的內存地址,類型 T 是指向類型 T 的值的指針。其零值是 nil,& 符號會生成一個指向其作用對象的指針, 符號表示指針指向的底層的值。

            var p *int i := 42 p = &i fmt.Println(*p) // 通過指針 p 讀取 i *p = 21         // 通過指針 p 設置 i 

            與 C 不同,Go 沒有指針運算。 結構體:一個結構體(struct)就是一個字段的集合,跟C類似,結構體字段使用點號來訪問,結構體字段可以通過結構體指針來訪問。

            type Vertex struct {     X int     Y int }  func main() {     fmt.Println(Vertex{1, 2})     v.X = 4     fmt.Println(v.X)     p := &v     p.X = 1e9 } 

            結構體文法:結構體文法表示通過結構體字段的值作為列表來新分配一個結構體。使用 Name: 語法可以僅列出部分字段。(字段名的順序無關。)特殊的前綴 & 返回一個指向結構體的指針。

            type Vertex struct {     X, Y int }  var (     v1 = Vertex{1, 2}  // 類型為 Vertex     v2 = Vertex{X: 1}  // Y:0 被省略     v3 = Vertex{}      // X:0 和 Y:0     p  = &Vertex{1, 2} // 類型為 *Vertex ) 

            數組:類型 [n]T 是一個有 n 個類型為 T 的值的數組,數組的長度是其類型的一部分,因此數組不能改變大小。 Slice:一個 slice 會指向一個序列的值,并且包含了長度信息,[]T 是一個元素類型為 T 的 slice。slice 可以重新切片,創建一個新的 slice 值指向相同的數組。s[lo:hi] 表示從 lo 到 hi-1 的 slice 元素,含兩端,因此s[lo:lo] 是空的。下標從0開始。

            package main import "fmt"  func main() {     p := []int{2, 3, 5, 7, 11, 13}     fmt.Println("p ==", p)     fmt.Println("p[1:4] ==", p[1:4])      // 省略下標代表從 0 開始     fmt.Println("p[:3] ==", p[:3])      // 省略上標代表到 len(s) 結束     fmt.Println("p[4:] ==", p[4:]) } 

            構造slice:slice 由函數 make 創建。這會分配一個零長度的數組并且返回一個 slice 指向這個數組,比如:

            a := make([]int, 5)  // len(a)=5 

            為了指定容量,可傳遞第三個參數到 make

            b := make([]int, 0, 5) // len(b)=0, cap(b)=5 b = b[:cap(b)] // len(b)=5, cap(b)=5 b = b[1:]      // len(b)=4, cap(b)=4 

            slice 的零值是 nil,一個 nil 的 slice 的長度和容量是 0。 向slice添加元素: func append(s []T, vs ...T) []T append 的第一個參數 s 是一個類型為 T 的數組,append 的結果是一個包含原 slice 所有元素加上新添加的元素的 slice,如果 s 的底層數組太小,而不能容納所有值時,會分配一個更大的數組,返回的 slice 會指向這個新分配的數組。 range: for 循環的 range 格式可以對 slice 或者 map 進行迭代循環。

            package main import "fmt"  var pow = []int{1, 2, 4, 8, 16, 32, 64, 128} func main() {     for i, v := range pow {         fmt.Printf("2**%d = %d\n", i, v)     } } 

            可以通過賦值給 _ 來忽略序號和值,如果只需要索引值,去掉“, value”的部分即可。

            func main() {     pow := make([]int, 10)     for i := range pow {         pow[i] = 1 << uint(i)     }     for _, value := range pow {         fmt.Printf("%d\n", value)     } } 

            map:map 在使用之前必須用 make 而不是 new 來創建;值為 nil 的 map 是空的,并且不能賦值。

            type Vertex struct {     Lat, Long float64 }  var m map[string]Vertex  func main() {     m = make(map[string]Vertex)     m["Bell Labs"] = Vertex{         40.68433, -74.39967,     }     fmt.Println(m["Bell Labs"]) } 

            map 的文法跟結構體文法相似,不過必須有鍵名。

            var m = map[string]Vertex{     "Bell Labs": Vertex{         40.68433, -74.39967,     },     "Google": Vertex{         37.42202, -122.08408,     }, } 

            如果頂級的類型只有類型名的話,可以在文法的元素中省略鍵名。

            var m = map[string]Vertex{     "Bell Labs": {40.68433, -74.39967},     "Google":    {37.42202, -122.08408}, } 

            修改 map: 在 map m 中插入或修改一個元素:m[key] = elem 獲得元素:elem = m[key] 刪除元素:delete(m, key) 通過雙賦值檢測某個鍵存在:elem, ok = m[key] 如果 key 在 m 中,ok 為 true 。否則, ok 為 false,并且 elem 是 map 的元素類型的零值,同樣的,當從 map 中讀取某個不存在的鍵時,結果是 map 的元素類型的零值。

            函數值:函數也是值。

            package main import (     "fmt"     "math" )  func main() {     hypot := func(x, y float64) float64 {         return math.Sqrt(x*x + y*y)     }     fmt.Println(hypot(3, 4)) } 

            函數的閉包:這個意思簡單點就是以函數作為返回值。 Go 函數可以是閉包的。閉包是一個函數值,它來自函數體的外部的變量引用。 函數可以對這個引用值進行訪問和賦值;換句話說這個函數被“綁定”在這個變量上。

            package main  import "fmt"  func adder() func(int) int {     sum := 0     return func(x int) int {         sum += x         return sum     } }  func main() {     pos, neg := adder(), adder()     for i := 0; i < 10; i++ {         fmt.Println(             pos(i),             neg(-2*i),         )     } } 

            posted on 2016-10-19 22:20 楊粼波 閱讀(468) 評論(0)  編輯 收藏 引用

            国产精品久久国产精品99盘| 香蕉久久永久视频| 成人综合久久精品色婷婷| 99久久精品免费看国产免费| 久久天堂AV综合合色蜜桃网 | av国内精品久久久久影院 | 久久毛片一区二区| 久久精品中文字幕大胸| 看全色黄大色大片免费久久久| 青青青青久久精品国产| 久久久久久久综合日本亚洲| 国产69精品久久久久777| av无码久久久久不卡免费网站| 97热久久免费频精品99| 久久青青草原国产精品免费| 国产精品久久久久影院色| 伊人久久大香线蕉精品| 99久久精品这里只有精品| 国产精品无码久久综合网| 亚洲精品视频久久久| 久久综合香蕉国产蜜臀AV| 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲 | 国产亚洲精久久久久久无码77777| 久久亚洲精品国产亚洲老地址| 香蕉久久夜色精品国产2020| 色综合久久久久久久久五月| 久久国产精品99精品国产987| 久久久99精品一区二区 | 国产成人精品综合久久久| 亚洲国产精品久久电影欧美| 国产∨亚洲V天堂无码久久久| 99久久国产综合精品网成人影院| 久久一区二区三区99| 亚洲精品无码久久久久sm| 欧美日韩中文字幕久久伊人| 久久婷婷五月综合成人D啪 | 东京热TOKYO综合久久精品 | 国产一区二区精品久久岳| 97精品依人久久久大香线蕉97| 中文字幕成人精品久久不卡| 亚洲女久久久噜噜噜熟女|