一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Golang學(xué)習(xí)筆記

 shopnc 2018-12-03
  1. Go安裝
    三種安裝方式,源碼安裝、壓縮包安裝
  2. GOPATH和工作空間
    作用?工作空間的目錄結(jié)構(gòu)
  3. GO命令

    1. go build
      • 如果是普通包,就像我們?cè)?.2節(jié)中編寫的mymath包那樣,當(dāng)你執(zhí)行g(shù)o build之后,它不會(huì)產(chǎn)生任何文件。如果你需要在$GOPATH/pkg下生成相應(yīng)的文件,那就得執(zhí)行g(shù)o install。
      • 如果是main包,當(dāng)你執(zhí)行g(shù)o build之后,它就會(huì)在當(dāng)前目錄下生成一個(gè)可執(zhí)行文件。如果你需要在$GOPATH/bin下生成相應(yīng)的文件,需要執(zhí)行g(shù)o install,或者使用go build -o 路徑/a.exe。
      • 你也可以指定編譯輸出的文件名。例如1.2節(jié)中的mathapp應(yīng)用,我們可以指定go build -o astaxie.exe,默認(rèn)情況是你的package名(非main包),或者是第一個(gè)源文件的文件名(main包)。
        (注:實(shí)際上,package名在Go語言規(guī)范中指代碼中“package”后使用的名稱,此名稱可以與文件夾名不同。默認(rèn)生成的可執(zhí)行文件名是文件夾名。)
      • go build會(huì)忽略目錄下以“_”或“.”開頭的go文件。
      • 如果你的源代碼針對(duì)不同的操作系統(tǒng)需要不同的處理,那么你可以根據(jù)不同的操作系統(tǒng)后綴來命名文件。例如有一個(gè)讀取數(shù)組的程序,它對(duì)于不同的操作系統(tǒng)可能有如下幾個(gè)源文件:
        array_linux.go array_darwin.go array_windows.go array_freebsd.go
        go build的時(shí)候會(huì)選擇性地編譯以系統(tǒng)名結(jié)尾的文件(Linux、Darwin、Windows、Freebsd)。例如Linux系統(tǒng)下面編譯只會(huì)選擇array_linux.go文件,其它系統(tǒng)命名后綴文件全部忽略。
        參數(shù)的介紹
        • -o 指定輸出的文件名,可以帶上路徑,例如 go build -o a/b/c
        • -i 安裝相應(yīng)的包,編譯+go install
        • -a 更新全部已經(jīng)是最新的包的,但是對(duì)標(biāo)準(zhǔn)包不適用
        • -n 把需要執(zhí)行的編譯命令打印出來,但是不執(zhí)行,這樣就可以很容易的知道底層是如何運(yùn)行的
        • -p n 指定可以并行可運(yùn)行的編譯數(shù)目,默認(rèn)是CPU數(shù)目
        • -race 開啟編譯的時(shí)候自動(dòng)檢測(cè)數(shù)據(jù)競(jìng)爭(zhēng)的情況,目前只支持64位的機(jī)器
        • -v 打印出來我們正在編譯的包名
        • -work 打印出來編譯時(shí)候的臨時(shí)文件夾名稱,并且如果已經(jīng)存在的話就不要?jiǎng)h除
        • -x 打印出來執(zhí)行的命令,其實(shí)就是和-n的結(jié)果類似,只是這個(gè)會(huì)執(zhí)行
        • -ccflags 'arg list' 傳遞參數(shù)給5c, 6c, 8c 調(diào)用
        • -compiler name 指定相應(yīng)的編譯器,gccgo還是gc
        • -gccgoflags 'arg list' 傳遞參數(shù)給gccgo編譯連接調(diào)用
        • -gcflags 'arg list' 傳遞參數(shù)給5g, 6g, 8g 調(diào)用
        • -installsuffix suffix 為了和默認(rèn)的安裝包區(qū)別開來,采用這個(gè)前綴來重新安裝那些依賴的包,-race的時(shí)候默認(rèn)已經(jīng)是-installsuffix race,大家可以通過-n命令來驗(yàn)證
        • -ldflags 'flag list' 傳遞參數(shù)給5l, 6l, 8l 調(diào)用
        • -tags 'tag list' 設(shè)置在編譯的時(shí)候可以適配的那些tag,詳細(xì)的tag限制參考里面的 Build Constraints
    2. go clean 這個(gè)命令是用來移除當(dāng)前源碼包和關(guān)聯(lián)源碼包里面編譯生成的文件。
    3. go fmt 代碼格式化
      用go fmt命令,其實(shí)是調(diào)用了gofmt,而且需要參數(shù)-w,否則格式化結(jié)果不會(huì)寫入文件。gofmt -w -l src,可以格式化整個(gè)項(xiàng)目。
      所以go fmt是gofmt的上層一個(gè)包裝的命令,我們想要更多的個(gè)性化的格式化可以參考 gofmt
      gofmt的參數(shù)介紹
      • -l 顯示那些需要格式化的文件
    • -w 把改寫后的內(nèi)容直接寫入到文件中,而不是作為結(jié)果打印到標(biāo)準(zhǔn)輸出。
    • -r 添加形如“a[b:len(a)] -> a[b:]”的重寫規(guī)則,方便我們做批量替換
    • -s 簡(jiǎn)化文件中的代碼
    • -d 顯示格式化前后的diff而不是寫入文件,默認(rèn)是false
    • -e 打印所有的語法錯(cuò)誤到標(biāo)準(zhǔn)輸出。如果不使用此標(biāo)記,則只會(huì)打印不同行的前10個(gè)錯(cuò)誤。
    • -cpuprofile 支持調(diào)試模式,寫入相應(yīng)的cpufile到指定的文件
    1. go get 這個(gè)命令是用來動(dòng)態(tài)獲取遠(yuǎn)程代碼包的
      這個(gè)命令在內(nèi)部實(shí)際上分成了兩步操作:第一步是下載源碼包,第二步是執(zhí)行g(shù)o install。下載源碼包的go工具會(huì)自動(dòng)根據(jù)不同的域名調(diào)用不同的源碼工具,
      參數(shù) -d 之只下載不安裝
    2. go install 這個(gè)命令在內(nèi)部實(shí)際上分成了兩步操作:第一步是生成結(jié)果文件(可執(zhí)行文件或者.a包),第二步會(huì)把編譯好的結(jié)果移到$GOPATH/pkg或者$GOPATH/bin。
    3. go test 執(zhí)行這個(gè)命令,會(huì)自動(dòng)讀取源碼目錄下面名為*_test.go的文件,生成并運(yùn)行測(cè)試用的可執(zhí)行文件。
    4. go tool 下面下載聚集了很多命令
    5. go generate 這個(gè)命令是從Go1.4開始才設(shè)計(jì)的,用于在編譯前自動(dòng)化生成某類代碼。
    6. godoc 在Go1.2版本之前還支持go doc命令,但是之后全部已到了godoc這個(gè)命令下,需要這樣安裝go get
    7. go version 查看go當(dāng)前的版本
      go env 查看當(dāng)前go的環(huán)境變量
      go list 列出當(dāng)前全部安裝的package
      go run 編譯并運(yùn)行Go程序

  4. 開發(fā)工具

    • Sublime Text
    • PHPStorm
    • LiteIDE

Go語言基礎(chǔ)

Go使用package(和Python的模塊類似)來組織代碼。main.main()函數(shù)(這個(gè)函數(shù)位于主包)是每一個(gè)獨(dú)立的可運(yùn)行程序的入口點(diǎn)。Go使用UTF-8字符串和標(biāo)識(shí)符(因?yàn)閁TF-8的發(fā)明者也就是Go的發(fā)明者),所以它天生支持多語言。

基礎(chǔ)知識(shí)

  1. 定義變量
    定義一個(gè)名稱為“variableName”,類型為”type”的變量 var variableName type
    定義三個(gè)類型都是“type”的變量var vname1, vname2, vname3 type
    初始化“variableName”的變量為“value”值,類型是“type” var variableName type = value
    定義三個(gè)類型都是”type”的變量,并且分別初始化為相應(yīng)的值 vname1為v1,vname2為v2,vname3為v3 var vname1, vname2, vname3 type= v1, v2, v3
    定義三個(gè)變量,它們分別初始化為相應(yīng)的值 vname1為v1,vname2為v2,vname3為v3 編譯器會(huì)根據(jù)初始化的值自動(dòng)推導(dǎo)出相應(yīng)的類型 vname1, vname2, vname3 := v1, v2, v3

    流程和函數(shù)

    流程控制

  • if Go里面if條件判斷語句中不需要括號(hào),如下代碼所示

    1
    2
    3
    4
    5
    if x > 10 {
    fmt.Println("x is greater than 10")
    } else {
    fmt.Println("x is less than 10")
    }
  • goto 用goto跳轉(zhuǎn)到必須在當(dāng)前函數(shù)內(nèi)定義的標(biāo)簽。

    1
    2
    3
    4
    5
    6
    7
    func myFunc() {
    i := 0
    Here: //這行的第一個(gè)詞,以冒號(hào)結(jié)束作為標(biāo)簽
    println(i)
    i++
    goto Here //跳轉(zhuǎn)到Here去
    }
  • for Go里面最強(qiáng)大的一個(gè)控制邏輯就是for,它即可以用來循環(huán)讀取數(shù)據(jù),又可以當(dāng)作while來控制邏輯,還能迭代操作。它的語法如下:

    1
    2
    3
    for expression1; expression2; expression3 {
    //...
    }

expression1、expression2和expression3都是表達(dá)式,其中expression1和expression3是變量聲明或者函數(shù)調(diào)用返回值之類的,expression2是用來?xiàng)l件判斷,expression1在循環(huán)開始之前調(diào)用,expression3在每輪循環(huán)結(jié)束之時(shí)調(diào)用。
通常用法

1
2
3
4
5
6
7
8
9
10
11
package main
import "fmt"
func main(){
sum := 0;
for index:=0; index < 10 ; index++ {
sum += index
}
fmt.Println("sum is equal to ", sum)
}
// 輸出:sum is equal to 45

循環(huán)

1
2
3
4
sum := 1
for ; sum < 1000; {
sum += sum
}

簡(jiǎn)寫

1
2
3
4
sum := 1
for sum < 1000 {
sum += sum
}

for 中有break 、continue

1
2
3
4
5
6
7
8
for index := 10; index>0; index-- {
if index == 5{
break // 或者continue
}
fmt.Println(index)
}
// break打印出來10、9、8、7、6
// continue打印出來10、9、8、7、6、4、3、2、1

for配合range可以用于讀取slice和map的數(shù)據(jù):

1
2
3
4
for k,v:=range map {
fmt.Println("map's key:",k)
fmt.Println("map's val:",v)
}

由于 Go 支持 “多值返回”, 而對(duì)于“聲明而未被調(diào)用”的變量, 編譯器會(huì)報(bào)錯(cuò), 在這種情況下, 可以使用_來丟棄不需要的返回值 例如

1
2
3
for _, v := range map{
fmt.Println("map's val:", v)
}

  • switch if 不夠用使用switch
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    switch sExpr {
    case expr1:
    some instructions
    case expr2:
    some other instructions
    case expr3:
    some other instructions
    default:
    other code
    }

another

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
integer := 6
switch integer {
case 4:
fmt.Println("The integer was <= 4")
fallthrough
case 5:
fmt.Println("The integer was <= 5")
fallthrough
case 6:
fmt.Println("The integer was <= 6")
fallthrough
case 7:
fmt.Println("The integer was <= 7")
fallthrough
case 8:
fmt.Println("The integer was <= 8")
fallthrough
default:
fmt.Println("default case")
}

函數(shù)

函數(shù)是Go里面的核心設(shè)計(jì),它通過關(guān)鍵字func來聲明,它的格式如下:

1
2
3
4
5
func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) {
//這里是處理邏輯代碼
//返回多個(gè)值
return value1, value2
}

關(guān)鍵字func用來聲明一個(gè)函數(shù)funcName
函數(shù)可以有一個(gè)或者多個(gè)參數(shù),每個(gè)參數(shù)后面帶有類型,通過,分隔
函數(shù)可以返回多個(gè)值
上面返回值聲明了兩個(gè)變量output1和output2,如果你不想聲明也可以,直接就兩個(gè)類型
如果只有一個(gè)返回值且不聲明返回值變量,那么你可以省略 包括返回值 的括號(hào)
如果沒有返回值,那么就直接省略最后的返回信息
如果有返回值, 那么必須在函數(shù)的外層添加return語句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main
import "fmt"
// 返回a、b中最大值.
func max(a, b int) int {
if a > b {
return a
}
return b
}
func main() {
x := 3
y := 4
z := 5
max_xy := max(x, y) //調(diào)用函數(shù)max(x, y)
max_xz := max(x, z) //調(diào)用函數(shù)max(x, z)
fmt.Printf("max(%d, %d) = %d\n", x, y, max_xy)
fmt.Printf("max(%d, %d) = %d\n", x, z, max_xz)
fmt.Printf("max(%d, %d) = %d\n", y, z, max(y,z)) // 也可在這直接調(diào)用它
}

多個(gè)返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main
import "fmt"
//返回 A+B 和 A*B
func SumAndProduct(A, B int) (int, int) {
return A+B, A*B
}
func main() {
x := 3
y := 4
xPLUSy, xTIMESy := SumAndProduct(x, y)
fmt.Printf("%d + %d = %d\n", x, y, xPLUSy)
fmt.Printf("%d * %d = %d\n", x, y, xTIMESy)
}

變參 func myfunc(arg …int) {}
傳值與傳指針

當(dāng)我們傳一個(gè)參數(shù)值到被調(diào)用函數(shù)里面時(shí),實(shí)際上是傳了這個(gè)值的一份copy,當(dāng)在被調(diào)用函數(shù)中修改參數(shù)值的時(shí)候,調(diào)用函數(shù)中相應(yīng)實(shí)參不會(huì)發(fā)生任何變化,因?yàn)閿?shù)值變化只作用在copy上。
傳指針使得多個(gè)函數(shù)能操作同一個(gè)對(duì)象。
傳指針比較輕量級(jí) (8bytes),只是傳內(nèi)存地址,我們可以用指針傳遞體積大的結(jié)構(gòu)體。如果用參數(shù)值傳遞的話, 在每次copy上面就會(huì)花費(fèi)相對(duì)較多的系統(tǒng)開銷(內(nèi)存和時(shí)間)。所以當(dāng)你要傳遞大的結(jié)構(gòu)體的時(shí)候,用指針是一個(gè)明智的選擇。
Go語言中channel,slice,map這三種類型的實(shí)現(xiàn)機(jī)制類似指針,所以可以直接傳遞,而不用取地址后傳遞指針。(注:若函數(shù)需改變slice的長(zhǎng)度,則仍需要取地址傳遞指針)

defer
Panic和Recover

struct類型

Go語言中,也和C或者其他語言一樣,我們可以聲明新的類型,作為其它類型的屬性或字段的容器。例如,我們可以創(chuàng)建一個(gè)自定義類型person代表一個(gè)人的實(shí)體。這個(gè)實(shí)體擁有屬性:姓名和年齡。這樣的類型我們稱之struct。如下代碼所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type person struct {
name string
age int
}
type person struct {
name string
age int
}
var P person // P現(xiàn)在就是person類型的變量了
P.name = "Astaxie" // 賦值"Astaxie"給P的name屬性.
P.age = 25 // 賦值"25"給變量P的age屬性
fmt.Printf("The person's name is %s", P.name) // 訪問P的name屬性.

除了上面這種P的聲明使用之外,還有另外幾種聲明使用方式:

  • 1.按照順序提供初始化值
    P := person{“Tom”, 25}
  • 2.通過field:value的方式初始化,這樣可以任意順序
    P := person{age:24, name:”Tom”}
  • 3.當(dāng)然也可以通過new函數(shù)分配一個(gè)指針,此處P的類型為*person
    P := new(person)

面向?qū)ο?/h3>

帶有接收者的函數(shù),我們稱為method
計(jì)算面積的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//原始的函數(shù)
package main
import "fmt"
type Rectangle struct {
width, height float64
}
func area(r Rectangle) float64 {
return r.width*r.height
}
func main() {
r1 := Rectangle{12, 2}
r2 := Rectangle{9, 4}
fmt.Println("Area of r1 is: ", area(r1))
fmt.Println("Area of r2 is: ", area(r2))
}
//接受者
type Rectangle struct {
width, height float64
}
type Circle struct {
radius float64
}
func (r Rectangle) area() float64 {
return r.width*r.height
}
func (c Circle) area() float64 {
return c.radius * c.radius * math.Pi
}
func main() {
r1 := Rectangle{12, 2}
r2 := Rectangle{9, 4}
c1 := Circle{10}
c2 := Circle{25}
fmt.Println("Area of r1 is: ", r1.area())
fmt.Println("Area of r2 is: ", r2.area())
fmt.Println("Area of c1 is: ", c1.area())
fmt.Println("Area of c2 is: ", c2.area())
}

method繼承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main
import "fmt"
type Human struct {
name string
age int
phone string
}
type Student struct {
Human //匿名字段
school string
}
type Employee struct {
Human //匿名字段
company string
}
//在human上面定義了一個(gè)method
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
func main() {
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
mark.SayHi()
sam.SayHi()
}

interface

Go語言里面設(shè)計(jì)最精妙的應(yīng)該算interface,它讓面向?qū)ο?,?nèi)容組織實(shí)現(xiàn)非常的方便
簡(jiǎn)單的說,interface是一組method的組合,我們通過interface來定義對(duì)象的一組行為。

并發(fā)

  • goroutine
    goroutine是通過Go的runtime管理的一個(gè)線程管理器。goroutine通過go關(guān)鍵字實(shí)現(xiàn)了,其實(shí)就是一個(gè)普通的函數(shù)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    package main
    import (
    "fmt"
    "runtime"
    )
    func say(s string) {
    for i := 0; i < 5; i++ {
    runtime.Gosched()
    fmt.Println(s)
    }
    }
    func main() {
    go say("world") //開一個(gè)新的Goroutines執(zhí)行
    say("hello") //當(dāng)前Goroutines執(zhí)行
    }

    runtime.Gosched()表示讓CPU把時(shí)間片讓給別人,下次某個(gè)時(shí)候繼續(xù)恢復(fù)執(zhí)行該goroutine

  • channels

    goroutine運(yùn)行在相同的地址空間,因此訪問共享內(nèi)存必須做好同步。那么goroutine之間如何進(jìn)行數(shù)據(jù)的通信呢,Go提供了一個(gè)很好的通信機(jī)制channel。channel可以與Unix shell 中的雙向管道做類比:可以通過它發(fā)送或者接收值。這些值只能是特定的類型:channel類型。定義一個(gè)channel時(shí),也需要定義發(fā)送到channel的值的類型。注意,必須使用make 創(chuàng)建channel:

    1
    2
    3
    4
    5
    6
    ci := make(chan int)
    cs := make(chan string)
    cf := make(chan interface{})
    //channel通過操作符<-來接收和發(fā)送數(shù)據(jù)
    ch <- v // 發(fā)送v到channel ch.
    v := <-ch // 從ch中接收數(shù)據(jù),并賦值給v

channel例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main
import "fmt"
func sum(a []int, c chan int) {
total := 0
for _, v := range a {
total += v
}
c <- total // send total to c
}
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x + y)
}

Buffered Channels

1
2
3
4
5
6
7
8
9
10
11
12
13
package main
import "fmt"
func main() {
c := make(chan int, 2)//修改2為1就報(bào)錯(cuò),修改2為3可以正常運(yùn)行
c <- 1
c <- 2
fmt.Println(<-c)
fmt.Println(<-c)
}
//修改為1報(bào)如下的錯(cuò)誤:
//fatal error: all goroutines are asleep - deadlock!

web基礎(chǔ)

  • web工作原理
  • http包建立Web服務(wù)器
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    package main
    import (
    "fmt"
    "net/http"
    "strings"
    "log"
    )
    func sayhelloName(w http.ResponseWriter, r *http.Request) {
    r.ParseForm() //解析參數(shù),默認(rèn)是不會(huì)解析的
    fmt.Println(r.Form) //這些信息是輸出到服務(wù)器端的打印信息
    fmt.Println("path", r.URL.Path)
    fmt.Println("scheme", r.URL.Scheme)
    fmt.Println(r.Form["url_long"])
    for k, v := range r.Form {
    fmt.Println("key:", k)
    fmt.Println("val:", strings.Join(v, ""))
    }
    fmt.Fprintf(w, "Hello astaxie!") //這個(gè)寫入到w的是輸出到客戶端的
    }
    func main() {
    http.HandleFunc("/", sayhelloName) //設(shè)置訪問的路由
    err := http.ListenAndServe(":9090", nil) //設(shè)置監(jiān)聽的端口
    if err != nil {
    log.Fatal("ListenAndServe: ", err)
    }
    }

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    在线观看视频国产你懂的| 国产一区二区三区午夜精品| 亚洲欧洲精品一区二区三区| 高清在线精品一区二区| 五月婷婷综合缴情六月| 欧美精品久久99九九| 欧美日韩国产精品黄片| 久久99午夜福利视频| 国产精品流白浆无遮挡| 少妇人妻一级片一区二区三区| 欧美三级大黄片免费看| 欧美一区二区口爆吞精| 都市激情小说在线一区二区三区| 日韩日韩日韩日韩在线| 日本视频在线观看不卡| 日本高清一区免费不卡| 国产精品一区二区高潮| 久久女同精品一区二区| 国内午夜精品视频在线观看| 五月激情综合在线视频| 欧美精品亚洲精品日韩精品| 欧美日韩国产综合在线| 黄色三级日本在线观看| 亚洲国产四季欧美一区| 欧美国产亚洲一区二区三区| 国产精品免费视频视频| 草草草草在线观看视频| 国产又粗又猛又大爽又黄| 国产精品偷拍视频一区| 亚洲精品高清国产一线久久| 精品国产亚洲免费91| 激情五月综五月综合网| 国产高清三级视频在线观看| 欧美激情床戏一区二区三| 国产精品福利一级久久| 人妻一区二区三区多毛女| 丰满人妻一二三区av| 日韩少妇人妻中文字幕| 亚洲av专区在线观看| 日韩性生活片免费观看| 亚洲精品成人福利在线|