<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ### go特性 - 1.自動垃圾回收。 - 2.更豐富的內置類型。 - 3.函數多返回值。 - 4.錯誤處理。 - 5.匿名函數和閉包。 - 6.類型和接口。 - 7.并發編程。 - 8.反射。 - 9.語言交互性。 ### 路徑 - GOPATH 項目路徑 - GOROOT go安裝路徑 設置路徑如下: ```bash vi ~/.bashrc export GOROOT=/usr/lib/go export GOPATH=/data/wwwroot/go export PATH=$GOROOT/bin:$GOPATH/bin:$PATH export PATH=$PATH:/opt/php7/bin ``` ### 命令 - go run:go run 編譯并直接運行程序,它會產生一個臨時文件(但不會生成 .exe 文件),直接在命令行輸出程序執行結果,方便用戶調試。 - go build:go build 用于測試編譯包,主要檢查是否會有編譯錯誤,如果是一個可執行文件的源碼(即是 main 包),就會直接生成一個可執行文件。 - go install:go install 的作用有兩步:第一步是編譯導入的包文件,所有導入的包文件編譯完才會編譯主程序;第二步是將編譯后生成的可執行文件放到 bin 目錄下($GOPATH/bin),編譯后的包文件放到 pkg 目錄下($GOPATH/pkg)。 ### go數據類型 - channel - map - slice - struct ### 聲明變量可見性 在 Go 中,包中成員以名稱首字母大小寫決定訪問權限。首字母大寫的名稱是被導出的。如下變量的聲明為例子: - 函數內部,僅函數可見 - 函數外部,對當前包可見 - 函數外部且首字母是大寫,對所有包可見 ### 首行代碼 package <name> 表示當前文件屬于哪個包,如果是package main表示當前文件是編譯后是一個可執行文件,編譯后可執行文件存放在bin目錄 > 但是同一目錄下的文件包名必須一致 ### import 導入包 ```bash import "os/exec" -> /usr/local/go/pkg/darwin_amd64/os/exec.a import "fmt" 最常用的一種形式(系統包) import "shorturl/model 加載gopath/src/shorturl/model模塊(絕對路徑) import f "fmt" 導入fmt,并給他啟別名f import . "fmt" 將fmt啟用別名".",這樣就可以直接使用其內容,而不用再添加fmt。 如fmt.Println可以直接寫成Println import _ "fmt" 表示不使用該包,而是只是使用該包的init函數,并不顯示的使用該包的其他內容。 注意:這種形式的import,當import時就執行了fmt包中的init函數,而不能夠使用該包的其他函數。 ``` Note: 包路徑為src目錄下,不要用相對路徑 ### 項目構建和編譯 - src: 源碼文件 - pkg: 包文件 - bin: 相關執行文件 ### 下劃線 ```go import _ "fmt" // 表示不使用fmt包,只使用fmt的init函數 f, _ := os.Open("xxxxxx") // 返回句柄和錯誤,“_”表示忽略error錯誤 ``` ### 常量值省略 在常量組中,如不提供類型和初始化值,那么視作與上一個常量相同。一般只要第一個常量初始化值即可 ```go const ( s = "abc" x // x = "abc" ) ``` ### iota 在每一個const關鍵字出現時,被重置為0,然后再下一個const出現之前,每出現一次iota,其所代表的數字會自動增加1 ```go const ( Sunday = iota Monday //通常省略后續行表達式 Tuesday Wednesday Thursday Friday Saturday ) func main() { fmt.Println(Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday) } // 輸出:0 1 2 3 4 5 6 ``` ### struct類型 類型C語言的結構體,用來定義復雜的數據類型 ### array類型 和C語言不一樣,go數組是值類型,這意味著賦值,傳參會復制數組,而不是指針 #### 初始化數組 初始化數組是可以使用索引號的 ```go var arr = [長度]類型{值,值,值} var arr1 = [5]int{1, 2, 3, 4, 5} var str = [5]string{3: "hello world", 4: "tom"} var arr2 = [...]int{1, 2, 3, 4, 5, 6} var users = [...]struct { name string age uint8 }{ {"user1", 10}, // 可省略元素類型。 {"user2", 20}, // 別忘了最后一行的逗號。 } a := [2]int{} // 默認值為0 ``` 長度可以用...代替,表示通過初始化值確定數組長度 #### 多維數組初始化 ```go a := [2][3]int{{1, 2, 3}, {4, 5, 6}} // 2行3列,每一個為一個花括號 b := [...][2]int{{1, 1}, {2, 2}, {3, 3}} // 第 2 緯度不能用 "..." ``` 指針數組 ?? 數組指針 ?? ### new和make的區別 - make和new用于分配內存 - make 用來創建map、slice、channel,返回對象非指針 - new 用來創建值類型,返回指向類型值的指針 ### slice用于變長數組 slice切片,引用數組,引用數組,引用數組(切片修改的值,原數組也會改變),初始化如下: ```go arr := arr[start:end] arr := [10]int{0,1,2,3,4,5,6,7,8,9} arr2 := arr[1:3] // 1,2 ``` - start為0時是可以省略,表示從頭開始切切 - end省略表示切切到結尾結束 - start表示從下標start開始,end表示從下標end-1結束 #### make創建slice ```go arr := make([]int, len, cap) ``` - len 可以使用的長度 - cap 容量,append擴展長度時,如果新的長度小于容量,不會更換底層數組,否則,go 會新申請一個底層數組,拷貝這邊的值過去,把原來的數組丟掉 #### append追加切片 append追加切片,并返回新slice對象;可以用兩種用法; ```go slice = append(slice, elem1, elem2) slice = append(slice, anotherSlice...) // 拼接兩個切片 ``` 具體如下: ```go var a = []int{1, 2, 3, 8:10} // 聲明并初始化一個切片,可以使用索引號 fmt.Printf("slice a : %v\n", a) var b = []int{4, 5, 6} fmt.Printf("slice b : %v\n", b) c := append(a, b...) fmt.Printf("slice c : %v\n", c) d := append(c, 7) fmt.Printf("slice d : %v\n", d) e := append(d, 8, 9, 10) fmt.Printf("slice e : %v\n", e) // 輸出結果: slice a : [1 2 3] slice b : [4 5 6] slice c : [1 2 3 4 5 6] slice d : [1 2 3 4 5 6 7] slice e : [1 2 3 4 5 6 7 8 9 10] ``` #### 切片結構 [x:y:z] a[x:y:z] 切片內容 [x:y] 切片長度: y-x 切片容量:z-x x是可以忽略的,即a[:y:z]的長度為y,切片容量為z ### 容器map 聲明和初始化: map[keyType]valueType,這塊相當于一個類型 ```go var m1 map[string]float32 = map[string]float32{"c":5, "go":5.5} // 或者 m2 := map[string]float32{"c":5, "go":5.5} ``` #### 通過make創建map ```go // 創建了一個鍵類型為string,值類型為int的map m1 := make(map[string]int) ``` #### map增刪查改 ```go m1 := map[string]string{"key2": "value2", "key3": "value3"} m1["key4"] = "value4" // 新增 fmt.Printf("增加key4:%v\n", m1) m1["key2"] = "new_value2" fmt.Printf("修改key2:%v\n", m1) if val, ok := m1["key3"]; ok { fmt.Println("key3 has found", val) } delete(m1, "key3") fmt.Println("刪除key3", m1) len := len(m1) fmt.Printf("m1 len is %v\n", len) ``` #### map遍歷 map遍歷不能保證迭代返回次序,通常是隨機結果 ```go m := make(map[int]int) for i := 0; i < 10; i++ { m[i] = i } for j := 0; j < 2; j++ { fmt.Println("---------------------") for k, v := range m { fmt.Printf("key -> value : %v -> %v\n", k, v) } } ``` ### map和slice使用 ```go len := 10 items := make([]map[int]int, len) for i := 0; i < len; i++ { items[i] = make(map[int]int) items[i][0] = i items[i][1] = i + 1 } fmt.Println(items) ``` ### channel管道 - 類似于unix管道(pipe) - 線程安全,多個goroutine同時訪問,不需要加鎖 channel聲明和初始化: chan type,這塊相當于一個類型 ```go var ch0 chan int // 一個只能存放整數的名字叫ch0的管道channel var ch1 chan int = make(chan int) // 通過make創建一個channel類型 ``` ### channel緩沖 通過make第二個參數可以指定channel緩沖大小,這個意義在于: - 對于發送者來說,直到channel滿時會阻塞,直到被接收者接受; - 對于接收者來說,channel為空時,接收會阻塞,直到channel有數據 ### channel發送和接受,關閉 ```go var ch chan int = make(chan int) ch <- 1 // 發送數據到channel x := <- ch // 從接受channel數據 close(ch) // 向關閉的channel發送數據會引起panic,接收數據會得到零值 ``` - 執行關閉的channel,此時如果channel還有數據,則會在channel接收完畢后返回零值 ```go var ch0 chan int ch0 = make(chan int, 11) ch0 <- 99 for i := 0; i < 10; i++ { ch0 <- i } frist_ch, ok := <-ch0 if ok { fmt.Printf("fist ch is %v\n", frist_ch) } ch0 <- 10 close(ch0) // 關閉channel,若channel有值,則可以繼續接收channel,但是不能在向channel發送新數據 for { var num int num, ok := <-ch0 if ok == false { fmt.Println("has close") break } fmt.Println(num) } fmt.Println("all done") ``` 或者 ```go close(ch0) for num := range ch0 { fmt.Println(num) } ``` #### 單向channel ```go c := make(chan int, 3) var send chan<- int = c // send-only var recv <-chan int = c // receive-only send <- 1 // <-send // Error: receive from send-only type chan<- int val, ok := <-recv if ok { fmt.Println(val) } // recv <- 2 // Error: send to receive-only type <-chan int ``` - chan<- 只發送數到channel - <-chan 只從channel接收數據 #### channel demo ```go package main import "fmt" type Request struct { data []int ret chan int } func NewRequest(data ...int) *Request { return &Request{data, make(chan int, 1)} } func Process(req *Request) { x := 0 for _, i := range req.data { x += i } req.ret <- x } func main() { req := NewRequest(10, 20, 30) Process(req) fmt.Println(<-req.ret) } ``` ### 函數 聲明方式: func 函數名稱(參數 參數類型) (返回類型) {} ```go func test(x, y int, s string) (int, string) {} func test(x int) int {} ``` - 合并同類型參數,用逗號隔開,類型放后面 - 沒有返回類型可以省略 #### 匿名函數 - 沒有函數名 - 可以賦值給變量 - 可以作為一種類型,例如func() string ```go package main import ( "fmt" "math" ) func main() { // 普通使用 getSprt := func(a float64) float64 { return math.Sqrt(a) } fmt.Println(getSprt(4)) // 作為管道 fc := make(chan func() string, 2) fc <- func() string { return "hello world" } fmt.Println((<-fc)()) // 作為結構體的一個字段 d := struct { fn func() string name string }{ fn: func() string { return "struct function" }, name: "good name", } fmt.Println(d.fn(), d.name) } ``` #### 函數閉包 一個函數嵌套另一個函數,閉包中變量始終存在,以下面為例: ```go package main import "fmt" func test() func() int { i := 0 fn := func() int { i++ fmt.Println(i) return i } return fn } func main() { a := test() a() // 1 a() // 2 a() // 3 b := test() b() // 1 b() // 2 b() // 3 } ``` - a實際上指向了test()函數中的fn函數,每一次a()調用是直接指向fn函數,所以說,test函數中的i:=0只會在a:=test()執行一次 - a和b屬于兩個不同的環境 ### defer延遲調用 - 最后執行 - 多個defer按照先進后出的方式執行 - 閉包中會先執行值,最后再調用結果 ```go package main import ( "fmt" // "time" ) func main() { v := 1 fn1 := func() { fmt.Println("fn1", v) } fn2 := func() { fmt.Println("fn2", v) } fn3 := func() func() { fmt.Println("閉包") return func() { fmt.Println("fn3") } } defer fn1() defer fn2() defer fn3()() // 當代碼到這一步時,不會調用,但是會執行閉包內的值 v = 2 // 改變了v的值,輸出結果也跟著改變 fmt.Println("runing") } ``` 輸出結果: ```go 閉包 runing fn3 fn2 2 fn1 2 ``` ### 異常處理 - panic拋出錯誤 - recover捕獲錯誤 go通過panic拋出一個異常,然后在defer中通過recover捕獲這個異常 ```go package main import ( "errors" "fmt" ) var ErrDivByZero = errors.New("division by zero") func div(x, y int) (int, error) { if y == 0 { return 0, ErrDivByZero } return x / y, nil } func main() { defer func() { fmt.Println(recover()) }() switch z, err := div(10, 0); err { case nil: println(z) case ErrDivByZero: panic(err) } } ``` ### 錯誤處理 error是一個類型,類似int,float64 ### 接口 一個類型實現了所有接口中定義的方法 實現的接口的類型,其i.(type)是接口名字 ### 類型斷言 - 參數是任意類型,如i interface{} - i.(type) ,其中i是接口值,type是類型 type兩種情況,具體類型和接口類型 - 具體類型:斷言成功,可以獲得i的具體值,失敗則panic - 接口類型:... ### 類型轉換 顯示 靜態類型 底層類型 底層類型相同,也需要強制轉換 - 普通類型向接口類型的轉換是隱式的。 - 接口類型向普通類型轉換需要類型斷言。 ### nil nil可以和channel,func,interface,map,slice作比較 ### 方法 類型, 該類型擁有的方法 叫方法的接受者是類型 類型只能是T或*T 值類型調用方法, 指針類型調用方法 無視類型調用方法,根據接受者類型操作內部 匿名字段 ### 終端讀取 從os.Stdin讀取 fmt.Scanln(&a, &b) 終端多個值空格隔開,直到換行 fmt.SScan(string, format, &a, &b, &c)從字符串string按照format格式分別讀取a,b,c三個值 ### 緩沖IO 緩沖的IO的作用避免大數據塊讀寫帶來的開銷 ### windown和linux,mac交叉編譯 ```go CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build gofile.go // mac CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build gofile.go // window CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build gofile.go // window ``` - GOOS:目標可執行程序運行操作系統,支持 darwin,freebsd,linux,windows - GOARCH:目標可執行程序操作系統構架,包括 386,amd64,arm ### 反射reflect 反射機制就是在運行時動態的調用對象的方法和屬性,官方自帶的reflect包就是反射相關的,reflect可以識別interface{}底層具體類型和具體值 - reflect.Type // 具體類型 - reflect.Value // 具體值 - reflect.TypeOf(obj) // 返回具體類型 - reflect.ValueOf(obj) // 返回具體值 - reflect.TypeOf(obj).Kind() // 返回具體類型的類別 - reflect.ValueOf(obj).Numfield() // 具體值有多少個字段 - reflect.ValueOf(obj).Field(num) // 第num個字段的值 - Int() // 將值轉為int - String() // 將值轉為string ```go package main import ( "fmt" "reflect" ) type Order struct { ID int Name string Age int } func (o Order) Create() { fmt.Println("生成訂單") } func main() { order := Order{1, "Allen.Wu", 25} t := reflect.TypeOf(order) v := reflect.ValueOf(order) k := t.Kind() fmt.Println("reflect.Type=", t) fmt.Println("reflect.Value=", v) fmt.Println("t.Kind()=", k) fmt.Println("reflect.ValueOf().NumField()=", v.NumField()) fmt.Println("reflect.ValueOf().Field(i)=", v.Field(0)) fmt.Println("reflect.ValueOf().Field(i).Interface()=", v.Field(0).Interface()) fmt.Println("reflect.TypeOf().NumField()=", t.NumField()) fmt.Println("reflect.TypeOf().Field(i)=", t.Field(0)) fmt.Println("reflect.TypeOf().Field(i).Name=", t.Field(0).Name) fmt.Println("reflect.TypeOf().Field(i).Type=", t.Field(0).Type) fmt.Println("reflect.TypeOf().NumMethod()=", t.NumMethod()) fmt.Println("reflect.TypeOf().Method(i)=", t.Method(0)) fmt.Println("reflect.TypeOf().Method(i).Name=", t.Method(0).Name) fmt.Println("reflect.TypeOf().Method(i).Type=", t.Method(0).Type) if reflect.TypeOf(order).Kind() == reflect.Struct { v := reflect.ValueOf(order) fmt.Println("number of fields:", v.NumField()) for i := 0; i < v.NumField(); i++ { fmt.Printf("Field:%d type:%T value:%v v:%v \n", i, v.Field(i), v.Field(i), v.Field(i).Interface()) } } } ``` 結果如下: ``` reflect.Type= main.Order reflect.Value= {1 Allen.Wu 25} t.Kind()= struct reflect.ValueOf().NumField()= 3 reflect.ValueOf().Field(i)= 1 reflect.ValueOf().Field(i).Interface()= 1 reflect.TypeOf().NumField()= 3 reflect.TypeOf().Field(i)= {ID int 0 [0] false} reflect.TypeOf().Field(i).Name= ID reflect.TypeOf().Field(i).Type= int reflect.TypeOf().NumMethod()= 1 reflect.TypeOf().Method(i)= {Create func(main.Order) <func(main.Order) Value> 0} reflect.TypeOf().Method(i).Name= Create reflect.TypeOf().Method(i).Type= func(main.Order) number of fields: 3 Field:0 type:reflect.Value value:1 v:1 Field:1 type:reflect.Value value:Allen.Wu v:Allen.Wu Field:2 type:reflect.Value value:25 v:25 ``` - Order的字段首字母需要大寫,否則v.Field(0).Interface()報錯 - Field是struct結構才有的,像float64,int是沒有這個的 - 類型轉換,struct結構可以通過v.Field(0).Interface()獲得結果,而float64則需要通過v.Interface().(float64)獲得結果 - reflect.TypeOf(n)等效于reflect.ValueOf(n).Type() #### reflect類型 - reflect.Int - reflect.String - reflect.Struct - reflect.Func 可以調用.Call() #### reflect具體類型轉換 通過reflect.ValueOf(t interface{})可以獲得類型為reflect.Value的值,如果需要進一步使用該值,需要進行轉換,如下: 強制類型轉換用Interface().(type);格式為:reflect.ValueOf(t).Interface().(type) ```go package main import ( "fmt" "reflect" ) func main() { var n float64 = 1.23456 value := reflect.ValueOf(n) fmt.Printf("類型是%T,值是%v \n", value, value) var v float64 v = value.Interface().(float64) fmt.Printf("類型是%T,值是%f \n", v, v) } ``` 輸出結果: ``` 類型是reflect.Value,值是1.23456 類型是float64,值是1.234560 ``` 需要注意的是,轉換的時候需要區分指針和值,如value.Interface().(float64)和value.Interface().(*float64)是不一樣的 #### 通過反射調用方法 reflect.ValueOf(n).MethodByName("funcName").Call([]reflect.Value)流程如下: - 獲得reflect.Value反射類型對象 - 通過reflect.Value調用MethodByName()獲得reflect.Value方法名 - 參數格式[]reflect.Value - 調用Call ```go package main import ( "fmt" "reflect" ) type Order struct { Id int Name string } func (o Order) Handle(code string) { fmt.Println("處理訂單號:", code) } func (o Order) Create() { fmt.Println("創建訂單成功") } func main() { var order = Order{1, "淘寶"} getValue := reflect.ValueOf(order) // 沒有參數 createMethod := getValue.MethodByName("Create") args := make([]reflect.Value, 0) createMethod.Call(args) // 有參數 handleMethod := getValue.MethodByName("Handle") args2 := []reflect.Value{reflect.ValueOf("xxxxdeewew33242342343333")} handleMethod.Call(args2) } ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看