【1-1 Golang】Go語言快速入門—基本語法

語言: CN / TW / HK

  Go語言是Google開發的一種靜態強型別、編譯型、併發型,並具有垃圾回收功能的程式語言。Go語言做到了在不損失應用程式效能的情況下降低程式碼的複雜性。

  Go語言語法簡單,只有25個關鍵字,不需要耗費時間去學習記憶;資料型別包括布林型,數字型別(整型、浮點型、複數),字串,切片(陣列),字典map,管道chan等,用起來還是比較順暢的。

  Go語言天然具備併發特性,基於go關鍵字就能很方便的建立協程去執行一些併發任務,而其基於協程-管道的CSP併發程式設計模型,相比於傳統複雜的多執行緒同步方案,可以說簡單太多了。

  Go語言還具備垃圾回收能力,避免了應用層還需要關注記憶體的分配與釋放,要知道在C/C++語言,記憶體管理可是可是讓人非常頭疼的。

  Go語言還提供了比較完善的標準庫,比如我們只需要幾行程式碼就能建立並啟動一個HTTP服務。

  從本篇文章開始,將帶領大家進入Go語言的世界。

環境搭建

  我們可以選擇下載原始碼編譯安裝,下載安裝包安裝,下載編譯好的可執行檔案,下載地址為:https://golang.google.cn/dl/

  筆者本地安裝的是go1.18.darwin-amd64.tar.gz,這是編譯好的可執行檔案,只需要解壓即可,解壓到目錄 $HOME/Documents/go1.18。最後再配置下環境變數:

export GOROOT=$HOME/Documents/go1.18
export PATH=$PATH:$GOROOT/bin
export GOPATH=$HOME/Documents/gopath

  $GOROOT是Go的安裝目錄;$PATH是為了讓我們可以在任意目錄執行go命令;$GOPATH工作目錄,通過go get命令下載的依賴包等就放在$GOPATH目錄,基於gomod管理的依賴檔案也會放在該目錄下。

  安裝配置完成後,執行go version驗證是否安裝成功。

  Go專案開發還少不了合適的編輯器,推薦使用Goland,下載地址為:https://www.jetbrains.com/go/。 安裝完成後,開啟Goland新建專案,新建main.go檔案,編寫經典的hello world:

package main

import "fmt"

func main() {
  fmt.Println("hello world")
}

  Go語言所有檔案都必須指定其所在的包,如上"package main",我們稱之為main包,當然包名也可以命名為其他名稱(一般包名與當前所在目錄/資料夾名稱保持一致),而main包裡的main函式為程式的入口函式。

  我們的程式碼肯定會依然其他檔案,怎麼引入呢?通過"import 包名"引入,引入後才能訪問該包內函式/變數。如上面程式碼所示,fmt包是Go語言底層提供的格式化/IO包,Println函式列印變數到標準輸出。

資料型別

  Go語言資料型別包括布林型,數字型別(整型、浮點型、複數),字串,切片(陣列),字典map,管道chan等,各型別變數的宣告以及簡單使用如下:

package main

import "fmt"

func main() {
  //變數宣告
  var a int = 1 //var 宣告並初始化變數, 型別int可以省略
  b := 1 //:= 宣告+初始化變數
  b = 3 //=只能針對已有變數重新賦值
  fmt.Println(a, b)

  //字串
  str1 := "hello "
  str2 := "world"
  fmt.Println(len(str1), str1 + str2)  //可以 +;len返回字串長度

  //陣列,容量固定
  arr := [5]int{1,2,3,4,5}
  arr[1] = 100 //陣列元素訪問
  fmt.Println(len(arr), arr) //len返回陣列長度

  //切片,容量可以擴充,相當於動態陣列
  slice := []int{1,2,3}
  slice[1] = 100 //切片元素訪問
  slice = append(slice, 4, 5, 6) //append自動擴容
  fmt.Println(len(slice),cap(slice), slice) //len返回切片長度,cap返回切片容量

  //map,key-value結構
  score := map[string]int{
    "zhangsan":100,
    "lisi":99,
    "wangwu":98,
  }
  score["who"] = 90 //map賦值
  s, ok := score["who"] //map訪問,s對應value值,ok標識該key是否存在(不存在返回空值)
  delete(score, "lisi") //刪除map元素
  fmt.Println(s, ok, score)
}

  這裡並沒有給出管道chan的事例,這將在第二章併發模型詳細介紹。當然除了Go語言提供的這些基本型別,我們也可以自定義型別,如介面,結構體等,這些也將在後面章節介紹。

分支結構

  與其他語言類似,Go語言同樣支援if/switch分支結構,for迴圈結構,如下面所示:

package main

import "fmt"

func main() {
  //if分支
  condition := true
  if condition {
    fmt.Println("true")
  }else{
    fmt.Println("false")
  }

  //wsith分支
  expr := "zhangsan"
  switch expr {
  case "zhangsan":
    fmt.Println("zhangsan")
  case "lisi":
    fmt.Println("lisi")
  default: //沒有匹配到,預設執行
    fmt.Println("who")
  }

  //for迴圈
  for i := 0; i < 100; i ++ {
    if i /2 == 0 {
      fmt.Println("偶數")
    }
  }

  //無條件迴圈,死迴圈
  i := 0
  for {
    i ++
    fmt.Println("loop")
    if i > 100 { //檢測條件,提前break退出迴圈
      break
    }
  }
}

函式

  函式的定義,如名稱,入參,返回值等基本概念這裡就不做過多介紹了,Go語言與其他語言不同的地方在於,其支援多返回值(大部分語言只能返回一個值),以及可變引數(大部分語言其實也支援),另外Go語言還支援閉包(匿名函式),例項如下:

package main

import "fmt"

func main() {
  add, sub := addSub(4, 3)
  fmt.Println(add, sub)

  sum(1, 2, 3)
  
  nums := []int{1, 2, 3, 4}
  sum(nums...) //切片轉可變引數,通過...實現

  //變數f為函式型別
  f := func (in string) {
    fmt.Println(in)
  }
  f("hello world") //執行函式

  //宣告匿名函式,注意與上面卻別,加括號直接執行該匿名函式
  func (in string) {
    fmt.Println(in)
  }("hello world")
}

//返回兩個int值
func addSub(a, b int) (int, int){
  return a + b, a - b
}

//...表示引數數目可變
func sum(nums ...int) {
  total := 0
  //nums其實是切片型別([]int),for + range 可遍歷切片元素
  for _, num := range nums {
    total += num
  }
  fmt.Println(total)
}

協程併發

  Go語言天然具備併發特性,基於go關鍵字就能很方便的建立協程去執行一些併發任務。下面程式建立10個協程併發執行任務,主協程等待各子協程執行結束後,也自動退出:

package main

import (
  "fmt"
  "sync"
)

func main() {
  //WaitGroup用於協程併發控制
  wg := sync.WaitGroup{}
  //啟動10個協程併發執行任務
  for i := 0; i < 10; i ++ {
    //標記任務開始
    wg.Add(1)
    go func(a int) {
      fmt.Println(fmt.Sprintf("work %d exec", a))
      //標記任務結束
      wg.Done()
    }(i)
  }
  //主協程等待任務結束
  wg.Wait()
  fmt.Println("main end")
}

總結

  本篇作為深入理解Go語言系列第一篇,簡單介紹了Go語言的基本語法,包括基本資料型別,分支結構,函式等基本概念,旨在讓你對Go語言能有初步認識,從下一篇開始,我們將開始Go語言的全面探索。