go語言開發入門

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

go語言開發入門

每個Go程式包含一個名為main的包以及其main函數,在初始化後,程式從main開始執行,避免引入不使用的包(編譯不通過)

基礎文法

基礎資料型別 (Elementary Data Type)

bool, byteint,int8,int16,int32,int64uint8,uint16,uint32,uint64 float32,float64(沒有float類型)string

變數賦值

var aa = 12a := 12a,b :=12,23

常量賦值

const(  a = iota  b)

迴圈只有 for

for i:=0;i<10;i++{   do Something...}for{   //相當於while(true){}}for _,v:= range list{   //range用法返回list數組或者列表的k,v兩個值(k數組索引從0開始,v值)   fmt.Print("%s", v)}

選擇 ifswitch

a := 1b := 1if a+b > 2 {   // 註:if(條件不帶括弧,且左大括弧與if保持同行)}
  • 學習一門語言學會迴圈

完整demo 大白加大白等於白胖胖.求大,白,胖各是數字多少?

package mainimport (  "fmt"  "strconv")/* 大白加大白等於白胖胖.求大,白,胖各是數字多少? */func main() {    for d := 1; d < 10; d++ {        for b := 1; b < 10; b++ {            for p := 1; p < 10; p++ {                daBai, _ := strconv.Atoi(strconv.Itoa(d) + strconv.Itoa(b))                // fmt.Println("大白", daBai)                baiPangPang, _ := strconv.Atoi(strconv.Itoa(b) + strconv.Itoa(p) + strconv.Itoa(p))                // fmt.Println("白胖胖", baiPangPang)                if daBai+daBai == baiPangPang {                    fmt.Println("-------------------大 白 胖--------------------")                    fmt.Printf("大 = %d, 白 = %d, 胖 = %d\n", d, b, p)                    fmt.Println("白胖胖: ", baiPangPang)                }            }        }    }}

資料(array)與切片(slice)

數組聲明:ArrayType = "[" ArrayLength "]" ElementType .

var a [32] intvar b [3][5] int

(1)數組是實值型別。將一個數組賦值給另一個,會拷貝所有的元素.

(2) 如果你給函數傳遞一個數組,其將收到一個數組的拷貝,而不是它的指標.

(3)數組的大小是其類型的一部分,類型[10]int和[20]int是不同的。數組長度在聲明後,就不可更改.

切片聲明:SliceType = "[" "]" ElementType .

var a []int

(1)沒有初始化的slice為nil.

(2)切片(slice)對數組進行封裝,實際上,切片可以看成大小可以動態變化的數組.

(3)Go中大多數的數組編程都是通過切片完成,而不是簡單數組.

一般來說,有兩種方式來初始化切片:

//通過數組方式var myArray [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}var mySlice []int = myArray[:5]//make方式make([]T, length, capacity)

Channel

  • Goroutine和channel是Go在“並發”方面兩個核心feature。

  • Channel是goroutine之間進行通訊的一種方式,go所提倡的"應該以通訊作為手段來共用記憶體"的最直接體現。

Channel聲明:
ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .
var ch chan int
var ch1 chan<- int //ch1隻能寫
var ch2 <-chan int //ch2隻能讀
//make初始化
putnamechan := make(chan string, 100) //帶緩衝

Goroutine

關鍵字go,啟用Goroutine的唯一途徑

//同時向五個人打招呼func main(){   names := []string{"Eric","Tom","Jack","Jim"}   for _,name:= range names{       go func(){           fmt.Printf("Hello,%s.\n",name)       }()   }   runtime.Gosched()}

調度模型

  • Go的調度器內部有三個重要的結構:M,P,S

  • M:代表真正的核心OS線程,真正幹活的人
  • G:代表一個goroutine,它有自己的棧,instruction pointer和其他資訊(正在等待的channel等等),用於調度。
  • P:代表調度的上下文,可以把它看做一個局部的調度器,使go代碼在一個線程上跑,它是實現從N:1到N:M映射的關鍵。

圖中看,有2個物理線程M,每一個M都擁有一個context(P),每一個也都有一個正在啟動並執行goroutine。
P的數量可以通過GOMAXPROCS()來設定,它其實也就代表了真正的並發度,即有多少個goroutine可以同時運行。
圖中灰色的那些goroutine並沒有運行,而是出於ready的就緒態,正在等待被調度。P維護著這個隊列(稱之為runqueue),
Go語言裡,啟動一個goroutine很容易:go function 就行,所以每有一個go語句被執行,runqueue隊列就在其末尾加入一個
goroutine,在下一個調度點,就從runqueue中取出一個goroutine執行。

其他

  • defer語句:調用一個被 defer 的函數時在函數剛要返回之前順延強制
  • panic/recover 異常處理語句

缺陷

  • 編譯產生的可執行檔尺寸非常大
  • 代碼可讀性差(x,y,z int, a []*struct)
  • go的濫用導致不可預見bug(注goroutine的使用應該是保守型的)

有兩種思維邏輯會想到使用goroutine

  • 商務邏輯需要並發

比如一個伺服器,接收請求,阻塞式的方法是一個請求處理完成後,才開始第二個請求的處理。其實在設計的時候我們一定不會這麼做,我們會在一開始就已經想到使用並發來處理這個情境,每個請求啟動一個goroutine為它服務,這樣就達到了並行的效果。這種goroutine直接按照思維的邏輯來使用goroutine

  • 效能最佳化需要並發

一個情境是這樣:需要給一批使用者發送訊息,正常邏輯會使用

for _, user := range users {    sendMessage(user)}//但是在考慮到效能問題的時候,我們就不會這樣做,如果users的個數很大,比如有1000萬個使用者?我們就沒必要將1000萬個使用者放在一個routine中運行處理,考慮將1000萬使用者分成1000份,    //每份開一個goroutine,一個goroutine分發1萬個使用者,這樣在效率上會提升很多。這種是效能最佳化上對goroutine的需求

執行個體httpmq

http協議實現的訊息佇列,資料持久化levelDb

//httpmq    mux := http.NewServeMux()mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {}  //net/http包起路由做攔截處理(put,get,status,view)//接收name\data參數//起四個channelputnamechan := make(chan string, 100) //入隊name管道putposchan := make(chan string, 100)  //入隊資料索引管道getnamechan := make(chan string, 100) //出隊name管道getposchan := make(chan string, 100)  //出隊資料索引管道//兩個Goroutine做訊息管道流入隊出隊操作go func(chan string, chan string) {    for {        name := <-putnamechan  //        putpos := httpmq_now_putpos(name)        putposchan <- putpos    }}(putnamechan, putposchan)go func(chan string, chan string) {    for {        name := <-getnamechan        getpos := httpmq_now_getpos(name)        getposchan <- getpos    }}(getnamechan, getposchan)//put入隊操作putnamechan <- nameputpos := <-putposchanqueue_name := name + putposif data != "" {   db.Put([]byte(queue_name), []byte(data), nil)         } else if len(buf) > 0 {   db.Put([]byte(queue_name), buf, nil)}//get出隊操作getnamechan <- namegetpos := <-getposchanif getpos == "0" {   w.Write([]byte("HTTPMQ_GET_END"))} else {   queue_name := name + getpos   v, err := db.Get([]byte(queue_name), nil)   if err == nil {        w.Header().Set("Pos", getpos)        w.Write(v)    } else {        w.Write([]byte("HTTPMQ_GET_ERROR"))    }}

put操作

name --> putnameChannel --> 產生putPos --> putposChannel --> name+pos產生key持久化data

get操作

name --> getnameChannel --> 產生getPos --> getposChannel --> name+pos產生key getData

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.