我的第一個go app

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

一、安裝

1.下載和解壓縮

# wget https://storage.googleapis.com/golang/go1.7.1.linux-amd64.tar.gz# tar -C /usr/local -xzf go1.7.1.linux-amd64.tar.gz

2、添加環境變數

2.1 Add /usr/local/go/bin to the PATH environment variable

在控制台臨時設定變數

# export GOROOT=/usr/local/go# export PATH=$PATH:$GOROOT/bin

在設定檔中 vim /etc/profile 永久設定變數,具體方法問百度。

3、測試環境

# mkdir -p $HOME/go/workspace# export GOPATH=$HOME/go/workspace# mkdir $GOPATH/src/hello# echo "" > $GOPATH/src/hello/hello.go  #新增go檔案

在hello.go裡面的內容

package mainimport "fmt"func main() {    fmt.Printf("hello, world\n")}

使用go tool 編譯該項目

# go install hello# $GOPATH/bin/hellohello, world

二、go 文法學習

基本類型

boolstringint  int8  int16  int32  int64uint uint8 uint16 uint32 uint64 uintptrbyte // uint8 的別名rune // int32 的別名     // 代表一個Unicode碼float32 float64complex64 complex128

這個例子示範了具有不同類型的變數。 同時與匯入語句一樣,變數的定義“打包”在一個文法塊中。

intuintuintptr 類型在32位的系統上一般是32位,而在64位系統上是64位。當你需要使用一個整數類型時,你應該首選 int,僅當有特別的理由才使用定長整數類型或者不帶正負號的整數類型。

1、匯入包:

1)包使用“”標示  2)包路徑/

單獨匯入

import "fmt"import "math/rand"

組合匯入 1、使用括弧組織包 2、,3、包之間換行 4、

import ("fmt""math/rand")

2、匯出名

只有首字母大寫可以被匯出

Func Foo(){}Func FOO(){}Func foo(){}

Foo 和FOO可以被匯出,foo 首字母小寫無法匯出。

3、函數

3.1 注意類型在變數名 之後 。

func(x int, y int ) int {    return (x + y);}

3.2 當兩個或多個連續的函數具名引數是同一類型,則除了最後一個類型之外,其他都可以省略

func(x, y, z int ) int {    return (x + y + z);}

3.3 可以返回任何數量的傳回值

package mainimport "fmt"func swap(x, y string) (string, string) {return y, x}func main() {a, b := swap("hello", "world")fmt.Println(a, b)}

3.4 命名傳回值 下面代碼命名了 x,y int

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

4 var 定義變數列表

var 語句定義了一個變數的列表;跟函數的參數列表一樣,類型在後面。

var c, python, java boolvar (ToBe   bool       = falseMaxInt uint64     = 1<<64 - 1z      complex128 = cmplx.Sqrt(-5 + 12i))

5、初始設定變數

定義變數可以包含初始化值,每個變數對應一個值

var a , b , c string = "hello1","hello2","hello3"

如果初始設定變數值是運算式,可以忽略變數類型;變數類型從運算式結果中獲得

var a , b , c  = "hello1","hello2","hello3"

6、短聲明變數 :=

該用法不可以使用在函數外面。在函數中,簡潔指派陳述式在類型明確的地方,可以用於替換 var

a , b , c := "hello11","hello22","hello33"

7、變數在定義時沒有明確初始化,會預設為零值

數值為0,bool 為 false,string 為 ""(Null 字元串)

8、類型轉換

運算式 T(v),將值 v 轉換為類型T ,不通類型轉換必須顯式轉換。

9、常量

const Pi = 3.14

10、for 迴圈

10.1for 迴圈並不需要使用括弧括起來:初始化語句;迴圈條件運算式;後置語句;但是迴圈體必須使用{}括起來。

    sum := 0;    for i := 0; i < 10; i++  {        sum += i    }    fmt.Println(sum)

10.2 for初始化語句和後置語句是可選的

sum := 1for ; sum < 1000; {    sum += sum}

11 for 是go 的while

sum := 1for sum < 1000 {    sum += sum}

12 死迴圈

忽略了迴圈條件,迴圈就不會結束,因此可以用更簡潔的語句表達死迴圈

for {}

13 if 的便捷運算式

跟 for 一樣, if 語句可以在條件之前執行一個簡單語句。該語句定義的變數範圍僅在if /else 範圍內

if v := math.Pow(3,3); v < 20 {    fmt.Println(v)} else {    fmt.Println(v)}

14 switch 的便捷運算式

跟 for 一樣, switch 語句可以在條件之前執行一個簡單語句。該語句定義的變數範圍僅在switch 範圍內

switch os := runtime.GOOS; os {case "darwin":fmt.Println("OS X.")case "linux":fmt.Println("Linux.")default:// freebsd, openbsd,// plan9, windows...fmt.Printf("%s.", os)}

switch 分支不需要break,除非以 fallthrough 語句結束,否則分支會自動終止

15 defer

defer 語句會延遲函數的執行直到上層函數返回。

1) 延遲調用的參數會立刻產生,但是在上層函數返回前函數都不會被調用

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

func main() {        fmt.Println("start")        for i := 0 ; i < 10; i++ {           fmt.Println(i)        }        fmt.Println("done")}
#./teststartdone9876543210

16、指標

go沒有指標運行符

x, y := 12,13p := &xfmt.Println(*p)  #即將列印12p = &y*p = 21fmt.Println(y)  #即將列印21

 

17、結構struct
1)聲明:

type struName struct{     var1 T1     var2 T2}

2)調用建構函式 struName{var1,var2....}

3)訪問方式 .成員變數

type Vertex struct {    x int    y int}func main() {    stru := Vertex{1 ,2}    fm.Println(stru)            #輸出:{1,2}    fmt.Println(stru.x, stru.y) #輸出:1 2    p := &stru     fm.Println(*p)              #輸出:{1,2}    fmt.Println(p.x, p.y)       #輸出:1 2}

18、數組

var a [2]stringa[0] = "hello"a[1] = "world"

19、slice

19.1 一個slice 會指向一個有序列的值,並且包含長度資訊。形如: []T

ss := [][]string{        []string{"hello0","world0"},        []string{"hello1","world1"},        []string{"hello2","world2"},    }    for i := 0; i< len(ss); i++ {         fmt.Println(ss[i][0],ss[i][1])    }

結果

#./testhello0 world0hello1 world1hello2 world2

19.2 對slice切片

slice可以重新切片,建立一個新的slice值指向相同的數組。形如:s[lo:hi],表示從lo到hi-1的slice元素,含前端,不包含後端。s[lo, lo] 是空值,s[lo,lo+1]有1個元素

19.3 make 函數

make:分配一個全是零值的數組並且返回一個slice指向這個數組。形如:s := make([]string , 3)

注意slice有長度和容量 ,長度:len(s),容量:cap(s)

s := make([]string, 0 , 5)

len(s) :返回0

cap(s) ::返回5

19.4 slice的零值為nil

20 range

for 迴圈的range 格式可以對slice 或者map 進行迭代,當使用for迴圈遍曆一個slice時,每次迭代range 將返回兩個值:下標和值

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)}}

輸出

# ./test2**0 = 12**1 = 22**2 = 42**3 = 82**4 = 162**5 = 322**6 = 642**7 = 128

for range 的簡略寫法

func main() {pow := make([]int, 10)        //只需要索引,去掉", value"for i := range pow {pow[i] = 1 << uint(i)}        //只需要治,賦值給_忽略序號for _, value := range pow {fmt.Printf("%d\n", value)}}

21 map--映射值到鍵

map在使用之前必須使用make來建立,否則為空白map,值為nil,不能對其賦值

var m map[string]intfunc main() {    m = make(map[string]int)    m["Bell"] = 12   //插入一個元素    fmt.Println("Bell' age is %d", m["Bell"])  //擷取一個元素    m["Bell"] = 15   //修改一個元素    m2 := map[string]int {        "Alice":13,    }    elem , ok  := m2["Alice"]   //使用雙賦值檢測某個鍵存在,存在 ok為true,否則為false,並且elem是map元素類型的零值    if ok {      fmt.Println("Alice' age is %d", elem)    }        delete(m2, "Alice")  //刪除一個元素    elem, ok = m2["Alice"]    if ok {      fmt.Println("Alice' age is %d", elem)    }    

22 函數值--函數作為函數參數傳遞或者作為傳回值

func compute(fn func(float64, float64) float64) float64 {        return fn(float64(3), float64(4))  //調用參數 -fn}func add(x ,y float64) float64 {    return x + y}func getfunc() func(float64, float64) float64 {    hypot := func(x, y float64) float64 {                return math.Sqrt(x*x + y*y)    }    return hypot  //返回函數}func main() {        hypot := getfunc()        fmt.Println(compute(hypot))     //hypot是參數        fmt.Println(compute(math.Pow)) //math.Pow是參數        fmt.Println(compute(add)) // add 是參數}

23 函數閉包

Go函數可以是一個閉包。

func adder() func(int) int {sum := 0          //fun 是一個閉包,它引用了函數體之外(本身fn之外)的變數        fn := func(x int) int {sum += xreturn sum}return fn }func main() {pos, neg := adder(), adder() //pos.neg是一個閉包,有各自的綁定的sum變數for i := 0; i < 10; i++ {fmt.Println(pos(i),neg(-2*i),)}}

 

24 在結構類型上定義方法

type Vertex struct {    X, Y float64}//方法 Sqrt被 v接收,v出現在 func 關鍵字和 方法Sqrt名 之間func (v *Vertex) Sqrt() float64 {    return math.Sqrt(v.X * v.X + v.Y*v.Y)}func main() {   p := &Vertex{3, 4}   fmt.Println(p.Sqrt())}

其實,可以在保內的任何類型定義任意方法,基礎類型和其他包的類型除外。

type myfloat float64//如果唯讀,使用值作為接收者,函數內部是調用者的副本func (f myfloat) Abs() float64 {    if f < 0 {        return float64(-f)    }    return float64(f)}//如果是可寫,使用指標作為接收者func (f *myfloat) Abs2() float64 {    if *f < 0 {        *f = -*f        return float64(-*f)    }    return float64(*f)}func main() {   fmt.Println((myfloat(-5.5)).Abs() )   f := myfloat(-5.5)   (&f).Abs2()}

25 介面

type myfloat float64type Iface interface {    Abs() float64}func (f myfloat) Abs() float64 {    if f < 0 {        return -float64(f)    }    return float64(f)}func main() {   var a Iface   f := myfloat(-5.5)   a = f;   fmt.Println(a.Abs())}

26 Web伺服器 包http 通過實現了http.Handler的介面來響應HTTP請求

type Hello struct{}func (h Hello) ServeHTTP(w http.ResponseWriter,r *http.Request) {fmt.Fprint(w, "Hello!")}func main() {var h Helloerr := http.ListenAndServe("localhost:4000", h)if err != nil {log.Fatal(err)}}

27 goroutine

goroute 是由go 運行時環境管理的輕量級線程 。文法:go f(x, y, x)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.