Go基礎概述

源碼文件使用UTF-8編碼,對Unicode支持良好。
每個源文件都屬於包的一部分,在文件頭部用package聲明所屬的包名稱
package man

func man() {
    println("hello, world!")
}
以".go"作爲文件擴展名,語句結束分號默認省略,支持C樣式註釋
入口函數main沒有參數,必須放在main包中
用import導入標準庫或第三方包
import "fmt"  //請刪除未使用的導入,否則編譯器會將其當作錯誤

1. 變量

使用var定義變量,支持類型推斷。 基礎數據類型劃分清晰明確, 有助於編寫跨平臺應用。編譯器確保變量總是被初始化爲零值。
在函數內部,可省略var關鍵字,使用更簡單的定義模式
package main

func main() {
    x := 100
    println(x)
}

2. 表達式

Go僅有三種流控制語句。
// if
func main() {
    x := 100
    if x > 0 {
        println("x")
    } else if x < 0 {
        println("-x")
    } else {
        println("0")
    }
}

//switch
func main() {
    x := 100
    switch{
        case x > 0:
            println("x")
        case x < 0:
            println("-x")
        default:
            println("0")
    }
}

#for
func main() {
    for i := 0; i<5; i++ {
        println(i)
    }
    for i:=4;i>=0; i-- {
        println(i)
    }
}
func main() {
    x := []int{100, 101, 102}
    //for...range 除元素外,還可返回索引
    for k, v := range x {
        println(x, ":", v)
    }
}

3 函數

package main

import (
    "errors"
    "fmt"
)

//函數可以定義多個返回值,甚至對其命名
func div(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a/b, nil
}
func main() {
    a, b := 10, 2   //定義多個變量
    c, err := div(a, b) //接收多返回值
    fmt.Println(c, err)
}
函數是第一類型,可以作爲參數或返回值
func test(x int) func() {   //返回函數類型
    return func() {         //匿名函數
        println(x)          //閉包
    }
}
func main() {
    x := 100
    f := test(x)
    f()
}
用defer定義延遲調用,無論函數是否出錯,它都確保結束前被調用
package main

func test(a, b int) {
    defer println("dispose...") //常用來釋放資源,解除鎖定,或執行一些清理操作
                                //可定義多個defer, 按FILO順序執行
    println(a /b)
}
func main() {
    test(10, 0)
}

4. 數據

切片(slice)可實現類似動態數組的功能
package main

import "fmt"

func main() {
    x := make([]int, 0, 5) //創建容量爲5的切片
    for i:=0;i<8;i++ {
        x = append(x, i)    //追加數據,當超出容量限制時,自動分配更大的存儲空間
    }
    fmt.Println(x)
}
//輸出
//[0 1 2 3 4 5 6 7]
將字典(map)類型內置,可直接從運行時層面獲取性能優化.
package main

import "fmt"

func main() {
    m := make(map[string]int)   //創建字典類型對象
    m["a"] = 1 //添加或設置
    x, ok := m["b"] //使用ok-idiom獲取值,可知道key/value是否存在
    fmt.Println(x, ok)
    
    delete(m, "a")  //刪除
}
/**
所謂ok-idiom模式,是指在多返回值中用一個名爲ok的布爾值來標示操作是否成功。因爲很多操作默認返回零值,所以必須額外說明
**/
結構體(struct)可欺匿名嵌入其他類型
package main

import "fmt"

type user struct {
    name string
    age byte
}

type manager struct {
    user                //匿名嵌入其他類型
    title string
}

func main() {
    var m manager
    
    m.name = "Tom"  //直接訪問匿名字段的成員
    m.age = 29
    m.title = "CTO"
    
    fmt.Println(m)
}
/**
輸出:
{{Tom 29} CTO}
**/

5. 方法

可以爲當前包內的任意類型定義方法
package main

type X int
func (x *X) inc() { //名稱前的參數稱作receiver,作用類似python self
    *x++
}
func main() {
    var x X
    x.inc()
    println(x)
}
還可直接調用匿名字段的方法,這種方式可實現與繼承類似的功能
package main
import "fmt"
type user struct {
    name string
    age byte
}

func (u user)ToString() string {
    return fmt.Sprintf("%+v", u)
}

type manager struct {
    user
    title string
}
func main() {
    var m manager
    m.name = "Tom"
    m.age = 29
    println(m.ToString()) //調用user.ToString()
}

6. 接口

接口採用了duck type方式,也就是說無須在實現類型上添加顯式聲明。
package main
import "fmt"
type user struct {
    name string
    age byte
}
func (u user)Print() {
    fmt.Printf("%+v", u)
}
type Printer interface {    //接口類型
    Print()
}
func main() {
    var u user
    u.name = "Tom"
    u.age = 29
    var p Printer = u //只要包含接口所需的全部方法,即表示實現了該接口
    p.Print()
}
//另有空接口類型interface{}, 用途類似OOP裏的system.Object, 可接收任意類型對象

7 併發

整個運行時完全併發化設置,幾乎都在以goroutine方式運行。能輕鬆創建和運行成千上萬的併發任務
package main

import (
    "fmt"
    "time"
)

func task(id int) {
    for i:=0; i<5; i++ {
        fmt.Printf("%d: %d\n", id, i)
        time.Sleep(time.Second)
    }
}
func main() {
    go task(1)
    go task(2)
    time.Sleep(time.Second*6)
}
通道(channel)與goroutine搭配,實現用通信代替內存共享的CSP模型
package main
//消費者
func consumer(data chan int, done chan bool) {
    for x:= range data { //接收數據,直到通道被關閉
        println("recv:", x)
    }
    done <- true    //通知main,消費結束
}
//生產者
func producer(data chan int) {
    for i:=0;i<4;i++ {
        data <- i   //發送數據
    }
    close(data) //生產結束,關閉通道
}
func main() {
    done := make(chan bool) //用於接收消費結束信號
    data := make(chan int)  //數據管道
    
    go consumer(data, done) //啓動消費者
    go producer(data)   //啓動生產者
    
    <-done //阻塞,直到消費者發回結束信號
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章