Golang最最最基礎文法

來源:互聯網
上載者:User

這一節看下Golang的基礎文法...嘛...如果懶得看的話,記得以下兩點就好:
1 Golang的變數、函數參數等等涉及到類型的聲明,都是變數名寫在前,類型寫在後的(和正統C系文法剛好相反)
2 迴圈語句for通吃所有
然後,就開始啦~

Go語言基本文法

package mainimport (    "fmt")func main() {    fmt.Println("Hello Azen٩(●˙▿˙●)۶…⋆ฺ")}

作用:使用fmt這個庫運行輸出

定義變數

var 關鍵字

func variableZeroValueDefine() {    var a int    var s string    fmt.Printf("%d %q\n", a, s)}

知識點:

  1. 變數名寫在前面,變數類型寫在後面
    原因:在定義變數的時候,往往是先想到名字,再想到變數類型
  2. 定義完變數後,變數都是有預設初值的。
    2.1. int類型的初值為0
    2.2. string類型的初始為空白串 - 使用%q可列印空串,展示結果為→ ""

同時定義變數並賦初值

注意:變數定義後,一定要用到,否則編譯器報錯。

func varibaleInitial() {    var a, b int = 1, 2    var s string = "猜猜我是誰"    fmt.Println(a, b, s)}

此例中,int 和 string是多餘的,編譯器可以做類型推斷 - Type Deduction

類型推斷

func varibaleTypeDeduction() {    var a, b, c, s = 1, 2, true, "ㄟ..."    b = 666    fmt.Println(a, b, c, s)}

:=定義並賦初值

更推薦用這種方式定義並初始設定變數

func varibaleShortcut() {    a, b := 233, 666    s := "老鐵蛤蛤蛤"    fmt.Println(a, b, s)}

在函數外定義變數

var a, b intvar ss = "總想搞個大新聞"

在函數外面定義的變數,不是全域變數,而是包內變數
Go語言木有全域變數的說法。

注意:在函數外定義變數不能用:=的方式,一定要被var關鍵字修飾

使用()定義多個包內變數

可以把變數定義在括弧中,以減少var關鍵字的使用數量

var (    s string    a, b int    // a, b := 666, 233 // 全域變數不能用:=定義)var ss = "總想搞個大新聞"

內建變數類型

  • bool,string
  • (u)int, (u)int8, (u)int16, (u)int32, (u)int64, uintptr
    • 沒跟長度,則長度按作業系統位元而定
    • uintptr是個指標
  • 字元型
    • byte
    • rune
      • 不是char,char只有1個位元組
      • rune的長度為32位,4位元組,為應對全球化的字元
  • 浮點數
    • float32,float64
    • complex64,complex128
      • 複數,有實部和虛部
      • complex64的實部和虛部為32位
      • complex128的實部和虛部為64位
      • 把複數直接作為內建變數的類型

強制類型轉換

Golang只有強制類型轉換,沒有隱式類型轉換
樣本:計算斜邊的長度
a = 3 b = 4 求斜邊c

func triangle() {    var a, b = 3, 4    var c int    c = int(math.Sqrt(float64(a * a + b * b)))    fmt.Println(c)}

math.Sqrt函數的入參和出參都是float64,所以需要強制轉換。

常量的定義

關鍵字:const
常量類型可規定也可不規定

  • 如果不規定類型,常量會像「文本替換」功能一樣(類似宏定義),到使用它的地方再決定類型

Golang中不會把常量全部大寫,因為首字母大寫在golang中代表範圍為public

func consts() {    const (        filename = "abc.txt"        a, b     = 3, 4    )    var c int    c = int(math.Sqrt(a * a + b * b))    fmt.Println(filename, c)}

*註:上面的a*a就不用強制轉為float64,因為被當成類似「宏替換」了

枚舉類型

基本定義:就定義成一組const就好

func enums() {    const (        azen  = 0        daker = 1        buran = 2    )    fmt.Println(azen, daker, buran)}

iota自增值

定義枚舉

func enums() {    const (        azen  = iota        daker        _        buran    )    fmt.Println(azen, daker, buran)}

iota參與運算

const (    b = 1 << (10 * iota)    kb    mb    gb    tb    pb)

條件陳述式

if語句

func bounded(v int) int {    if v > 100 {        return 100    } else if v < 0 {        return 0    } else {        return v    }}

特點:if條件不需要用括弧包裹
樣本:

func ReadFile(filename string) ([]byte, error)

返回兩個值:

  • [ ]byte 是讀取到的檔案內容數組 - 使用%s列印內容
  • error 是出錯資訊
func fileRead() {    const filename = "abc.txt"    contents, err := ioutil.ReadFile(filename)    if err != nil {        fmt.Println(contents)    } else {        fmt.Println(err)    }}

使用;簡化條件

func fileRead() {    const filename = "abc.txt"    if contents, err := ioutil.ReadFile(filename); err != nil {        fmt.Println(contents)    } else {        fmt.Println(err)    }}

在條件中可以用:=做聲明和賦值
出了if的範圍就不能訪問如上定義的content和err了

switch語句

基本用法

func eval(a, b int, op string) int {    var result int    switch op {    case "+":        result = a + b    case "-":        result = a - b    case "*":        result = a * b    case "/":        result = a / b    default:        panic("不支援的操作類型")    }    return result}

特點:

  • 不需要加break,預設都有break.
  • 如果不需要break,手動加fallthrough - 這一點和swift一樣

panic

拋出一個錯誤 - 類似於NSError的raise

switch後不接運算式

在case中加入條件即可

func grade(score int) string {    var g string    switch {    case score < 0 || score > 100:        panic(fmt.Sprintf("Wrong score: %d", score))    case score < 60:        g = "F"    case score < 80:        g = "B"    case score < 90:        g = "A"    case score <= 100:        g = "SSR"    }    return g}

迴圈語句

for語句

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

栗子:轉二進位

轉二進位的思路:不斷模數,獲得的數字往前加

func convertToBin(number int) string {    result := ""    for ; number > 0; number /= 2 {        lsb := number % 2        result = strconv.Itoa(lsb) + result    }    return result}

strconv.Itoa → 將int轉為string

for的while用法(只有結束條件)

func pintFile(filename string) {    file, err := os.Open(filename)    if err != nil {        panic(err)    }     scanner := bufio.NewScanner(file)    //  func (s *Scanner) Scan() bool - 在讀完或報錯的時候,會返回false    for scanner.Scan() {             }}

當for 語句中,省略其實條件、遞增條件,只有結束條件的時候,類似於while

for省略所有運算式 - 死迴圈

func forever() {    for {        fmt.Println("Bilibili")    }}

Golang中經常要用到死迴圈,goroutine的肚子裡就是死迴圈。好多死迴圈的goroutine在互相進行通訊。 - 這和iOS開發中的runloop是一樣一樣的

函數定義

func eval(a, b int, op string) int

函數名在前,類型在後。和變數定義思路一致

基本樣本

func convertToBin(number int) string {    result := ""    for ; number > 0; number /= 2 {        lsb := number % 2        result = strconv.Itoa(lsb) + result    }    return result}

函數返回多個值樣本

帶餘除法

func div(a, b int) (int, int) {    return a / b, a % b}

給傳回值起名字

好處是可讀性更強,函數調用者可以很方便的知道傳回值是啥...

func div(a, b int) (q, r int) {    return a / b, a % b}

如下寫法也可以正確返回q和r,但是可讀性不強,不建議這樣寫

func divNoRecommend(a, b int) (q, r int) {    q = a / b    r = a % b    return}

多傳回值只使用一個

result, _ := div(10, 7)

多值返回的習慣用法

第一個值返回正常值,第二個值返回error

函數和函數式編程

函數在Golang中是一等公民,函數可以作為參數、傳回值

函數作為參數

func apply(op func(a, b int) int, a, b int) (result int)  {    return op(a, b)}

列印下op看看它是誰

  • 拿函數名
    • 需要用reflect.ValueOf(op).Pointer()拿到這個函數的指標
    • 使用runtime擷取函數名runtime.FuncForPC(p).Name()
func apply(op func(a, b int) int, a, b int) (result int)  {    p := reflect.ValueOf(op).Pointer()    opName := runtime.FuncForPC(p).Name()    fmt.Println(opName)    return op(a, b)}

匿名函數作為函數參數

fmt.Println(    apply(func (a, b int) int {        return a + b    }, 10, 20),)

Golang沒有花哨的lambda運算式

函數其他說明

可變參數列表

可變參數列表的使用方法,可以和數組一樣用

func sum(numbers ...int) int {    result := 0    for i := range numbers {        result += numbers[i]    }    return result}

沒有預設參數、選擇性參數概念

指標

func pointerDefine() {    var a = 0    var pa *int = &a    *pa = 0x66CCFF    fmt.Println(a)}

特點

  • 指標不能運算
    • C可以拿到指標的頭指標做加法運算 - 步長由指標類型決定

函數參數傳遞

C、C++、OC可以值傳,也可以引用傳
Java和Python基本上都是引用傳遞

Golang只有值傳遞一種方式

凡調函數,參數都會拷貝一份 - 和指標配合,實現相當引用傳遞的效果

舉例:交換兩個變數的值

func swap(a, b *int) {    *a, *b = *b, *a}
相關文章

聯繫我們

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