Go學習筆記(七)

(文章持續更新中...有志同道合的人能夠一塊兒探討下。整個系列(1~8)準備重寫,不過都是很基礎的入門筆記,想學到很深刻的東西則不建議閱讀...)bash

接口是雙方約定的一種合做協議。每一個接口類型由數個方法組成併發

type 接口類型名 interface{
    方法名1( 參數列表1 ) 返回值列表1
    方法名2( 參數列表2 ) 返回值列表2
    …
}

type Writer interface {
    Write(p []byte) (n int, err error)
}
複製代碼
  • 接口的方法與實現接口的類型方法格式一致.實現接口類型中的方法的名稱、參數列表、返回參數列表中的任意一項與接口要實現的方法不一致,那麼接口的這個方法就不會被實現。
  • 接口中全部方法均被實現.當一個接口中有多個方法時,只有這些方法都被實現了,接口才能被正確編譯並使用

Go 語言的源碼複用創建在包(package)基礎之上.Go 語言的入口 main() 函數所在的包(package)叫 main,main 包想要引用別的代碼,必須一樣以包的方式進行引用,Go 語言的包與文件夾一一對應,全部與包相關的操做,必須依賴於工做目錄(GOPATH)函數

GOPATH 絕對路徑提供項目的工做目錄ui

goroutine 的概念相似於線程,但 goroutine 由 Go 程序運行時的調度和管理。Go 程序會智能地將 goroutine 中的任務合理地分配給每一個 CPUspa

Go 程序中使用 go 關鍵字爲一個函數建立一個 goroutine。一個函數能夠被建立多個 goroutine,一個 goroutine 一定對應一個函數命令行

// 爲普通函數建立goroutine 的格式
go 函數名( 參數列表 )
複製代碼

若是須要在 goroutine 中返回數, 用通道(channel)把數據從 goroutine 中做爲返回值傳出線程

package main

import (
    "fmt"
    "time"
)

func running() {
    var times int
    for {
        times++
        fmt.Println("tick", times)
        time.Sleep(time.Second)
    }
}

func main() {
    // 併發執行程序
    go running()
    // 接受命令行輸入, 不作任何事情
    var input string
    fmt.Scanln(&input)
}

複製代碼

通常狀況下,可使用 runtime.NumCPU() 查詢 CPU 數量,並使用 runtime.GOMAXPROCS() 函數進行設置指針

runtime.GOMAXPROCS(runtime.NumCPU())
複製代碼

併發和並行的概念code

併發:任務在不一樣的時間點在處理器進行處理。在同一時間點,任務並不會同時運行 並行:每個任務分配給每個處理器獨立完成。在同一時間點,任務必定是同時運行接口

Go語言通道

單純地將函數併發執行是沒有意義的。函數與函數間須要交換數據才能體現併發執行函數的意義

任什麼時候候,同時只能有一個 goroutine 訪問通道(channel Go語言中一種特殊類型)進行發送和獲取數據。(相似隊列,先進先出

// 申明通道類型
var 通道變量 chan 通道類型(通道內的數據類型)
複製代碼

chan 類型的空值是 nil,聲明後須要配合 make 後才能使用

通道是引用類型,須要使用 make 進行建立

通道實例 := make(chan 數據類型)

ch1 := make(chan int)                 // 建立一個整型類型的通道
ch2 := make(chan interface{})         // 建立一個空接口類型的通道, 能夠存聽任意格式
type Equip struct{ /* 一些字段 */ }
ch2 := make(chan *Equip)             // 建立Equip指針類型的通道, 能夠存放*Equip
複製代碼

通道建立後,就可使用通道進行發送和接收操做

通道的發送使用特殊的操做符<-

// 數據經過通道發送數據格式
通道變量 <- 值(值的類型必須與ch通道的元素類型一致)

// 建立一個空接口通道
ch := make(chan interface{})
// 將0放入通道中
ch <- 0
// 將hello字符串放入通道中
ch <- "hello"

複製代碼

發送將持續阻塞直到數據被接收

把數據往通道中發送時,若是接收方一直都沒有接收,那麼發送操做將持續阻塞。Go 程序運行時能智能地發現一些永遠沒法發送成功的語句並作出提示,代碼以下:

package main
func main() {
    // 建立一個整型通道
    ch := make(chan int)
    // 嘗試將0經過通道發送
    ch <- 0
}
複製代碼

通道接收一樣使用<-操做符

通道的收發操做在不一樣的兩個 goroutine 間進行

接收將持續阻塞直到發送方發送數據

通道一次只能接收一個數據元素

阻塞模式接收數據時,將接收變量做爲<-操做符的左值,執行該語句時將會阻塞,直到接收到數據並賦值給 data 變量

// 阻塞式接收值
data := <-ch

// 非阻塞式
data, ok := <-ch
data 表示接收到的數據
ok   表示是否接收到數據

非阻塞的通道接收方法可能形成高的 CPU 佔用,所以使用很是少

// 忽略從通道返回的數據
<-ch
複製代碼

Go 的通道能夠在聲明時約束其操做方向,如只發送或是隻接收。這種被約束方向的通道被稱作單向通道

只能發送的通道類型爲chan<-,只能接收的通道類型爲<-chan

var 通道實例(聲明的通道變量) chan<- 元素類型    // 只能發送
var 通道實例(聲明的通道變量) <-chan 元素類型    // 只能接收
複製代碼

使用 close() 來關閉一個通道.給被關閉通道發送數據將會觸發panic

close(ch)
複製代碼

互斥鎖是一種經常使用的控制共享資源訪問的方法,它可以保證同時只有一個 goroutine 能夠訪問共享資源

Lock()

UnLock()

相關文章
相關標籤/搜索