<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          入門教程:花 5 分鐘學習 Go 語言

          共 1135字,需瀏覽 3分鐘

           ·

          2021-01-19 09:00

          這是一篇外文,號稱五分鐘入門 Go 語言。在周刊中推薦了這篇文章,今天看到 Seekload 翻譯了,推薦給新手!



          via:
          https://gist.github.com/prologic/5f6afe9c1b98016ca278f4d507e65510
          作者:prologic

          四哥水平有限,如有翻譯或理解錯誤,煩請幫忙指出,感謝!

          上周五的分享預告點贊已破百,成功解鎖了今天的文章。

          前幾天看到優(yōu)質文章推送,注意到這篇文章(主要是標題吸引了我),文章非常簡潔,讓我們一起來回顧下相關的基礎知識。

          原文如下:


          基本

          作為經典的 “Hello World”,你的第一個 Go 程序非常簡單:

          先為我們的項目創(chuàng)建 workspace:

          $?mkdir?hello
          $?cd?hello

          接著創(chuàng)建并初始化 Go module:

          $?go?mod?init?hello

          使用你最喜歡的編輯器創(chuàng)建 main.go 文件,輸入如下代碼,并將文件保存在上面創(chuàng)建的 hello 目錄下。

          package?main

          import?"fmt"

          func?main()?{
          ??fmt.Println("Hello?World!")
          }

          最后編譯產生一個二進制文件:

          $?go?build

          在 workspace 下會生成一個名為 hello 的二進制可執(zhí)行文件,運行它會輸出:

          $?./hello
          Hello?World!

          變量

          在 Go 語言里,你可以使用下面兩種方法創(chuàng)建變量:

          var?x?int

          其他類型,包括 int、int32、int64、float32、float64、bool和 string 等,還有帶 u 前綴的無符號整型類型,例如:uint8 與 byte 是同一種類型(ps:可以認為 type 是 uint8 的別稱,見源碼 type byte = uint8)

          或者創(chuàng)建變量時直接賦值,Go 編譯器能自動推導變量類型:

          x?:=?42

          通過操作符 = 賦值:

          x?=?1

          注意: 大部分時候你都不需要使用 var 關鍵字,除非創(chuàng)建變量之后再賦值或者需要使用變量的零值。

          函數

          使用關鍵字 func 聲明函數:

          func?hello(name?string)?string?{
          ??return?fmt.Sprintf("Hello?%s",?name)
          }

          函數如果有返回值,必須顯示地指明返回值類型。

          函數可以有多個返回值(一般返回錯誤和值):

          func?isEven(n?int)?(bool,?error)?{
          ??if?n?<=?0?{
          ????return?false,?fmt.Errorf("error:?n?must?be?>?0")
          ??}
          ??return?n?%?2?==?0,?nil
          }

          函數是 Go 語言的“一等公民”,因此支持很多函數式編程的很多特性,包括閉包、將函數作為參數傳遞或者返回等,例如:

          func?AddN(n?int)?func(x?int)?int?{
          ??return?func(x?int)?int?{
          ????return?x?+?n
          ??}
          }

          結構體

          由于 Go 是一種多范式語言,因此它還通過結構體實現“面向對象”編程,使用關鍵字 struct 定義結構體:

          type?Account?struct?{
          ??Id??????int
          ??Balance?float64
          }

          結構體字段的定義與變量定義類似,使用操作符 . 訪問字段:

          account?:=?Account{}
          fmt.Printf("Balance:?$%0.2f",?account.Balance)

          方法

          結構體可以擁有自己的方法。不像其他語言,Go 語言不支持繼承也沒有類(我們可以通過結構體嵌套實現“繼承”)。

          type?Account?struct?{
          ??id??int
          ??bal?float64
          }

          func?(a?*Account)?String()?string?{
          ??return?fmt.Sprintf("Account[%d]:?$0.2f",?a.id,?a.bal)
          }

          func?(a?*Account)?Deposit(amt?flaot64)?float64?{
          ??a.bal?+=?amt
          ??return?a.bal
          }

          func?(a?*Account)?Withdraw(amt?float64)?float64?{
          ??a.bal?-=?amt
          ??return?a.bal
          }

          func?(a?*Account)?Balance()?float64?{
          ??return?a.bal
          }

          這些方法稱為指針接收者方法,因為第一個參數是指向 Account 結構體的指針。

          你還可以像下面這樣定義方法:

          type?Circle?struct?{
          ??Radius?float64
          }

          func?(c?Circle)?Area()?float64?{
          ??return?3.14?*?c.Radius?*?c.Radius
          }

          剛剛定義的是值接收者方法,在方法中對結構體修改不會影響到原結構體,是一份拷貝。

          關于結構體、指針接收者方法和值接收者方法可以查看文末推薦閱讀了解更多。

          數組和 Slice

          與其他語言類似,Go 支持數組,不同的是 Go 語言數組是固定長度的(聲明長度之后不支持動態(tài)變化),與 C 語言數組類似。

          可以指定大小和類型創(chuàng)建數組:

          xs?:=?[4]int{1,?2,?3,?4}

          大多數場景你會更喜歡使用 slice,有點類似其他語言(比如 Python)中的 list,支持自動擴容。

          創(chuàng)建 slice 時可以不用指定大小:

          xs?:=?[]int{1,?2,?3,?4}

          slice 也可以通過 append() 函數創(chuàng)建:

          xs?:=?[]int{}
          xs?=?append(xs,?1)
          xs?=?append(xs,?2)
          xs?=?append(xs,?3)

          可以通過索引范圍 slice:

          xs[1]??//?2

          你還可以通過“切片”操作獲取數組或者 slice 的子集:

          ys?:=?xs[1:]?//?[2,?3]

          可以使用 range 關鍵字迭代 數組或者 slice:

          for?i,?x?:=?range?xs?{
          ??fmt.Printf("xs[%d]?=?%d\n",?i,?x)
          }

          map

          Go 語言里存儲鍵值對的內置數據結構稱為 map(類似其他語言的 hash table、hash map、字典或者關聯數組)。

          可以通過關鍵字 map 創(chuàng)建 map,需要分別定義鍵值的類型,比如定義鍵類型為 string、值類型為 int 的 map:

          var?counts?map[string]int

          也可以像下面這樣創(chuàng)建 map:

          counts?:=?map[string]int{
          ??"Apples":?4,
          ??"Oranges":?7,
          }

          類似數組和 slice,也可以通過鍵訪問值:

          counts["Apples"]??//?4

          像數組和 slice 一樣,迭代 map:

          for?key,?value?:=?range?counts?{
          ??fmt.Printf("%s:?%d\n",?key,?value)
          }

          唯一需要注意的是,map 使用之前需要先初始化,操作 nil map 將會導致 error 和 panic:

          var?counts?map[string]int
          counts["Apples"]?=?7??//?This?will?cause?an?error?and?panic!

          使用之前必須使用 make() 函數初始化:

          counts?:=?make(map[string]int)
          counts["Apples"]?=?7

          關于數組、slice 和 map 更詳細的用法可以查看文末推薦閱讀掌握。

          流控制

          for

          Go 語言里面只有一種循環(huán)結構,在之前的章節(jié)里或許你也看到了:

          sum?:=?0
          for?i?:=?0;?i?10;?i++?{
          ??sum?+=?i
          }

          for 循環(huán)語句由三部分組成:

          • 初始化語句:第一次迭代之前執(zhí)行;

          • 條件表達式:每次迭代之前都會執(zhí)行;

          • post 語句:每次迭代之后都會執(zhí)行;

          如果忽略循環(huán)條件,得到的是無限循環(huán):

          for?{
          }
          //?This?line?is?never?reached!

          if-else

          Go 語言支持 if-else 語句:

          N?:=?42
          func?Guess(n?int)?string?{
          ??if?n?==?42?{
          ????return?"You?got?it!"
          ??}?else?if?n?????return?"Too?low!?Try?again..."
          ??}?else?{
          ????return?"Too?high!?Try?again..."
          ??}
          }????????

          注意:可以忽略最后一個 else,直接像這樣返回 return "Too high~ Try again…",兩者是等價的。

          switch

          Go 語言提供的 switch 語句可以代替 if-else,比如:

          func?FizzBuzz(n?int)?string?{
          ??switch?n?{
          ??case?n?%?15?==?0:
          ????return?"FizzBuzz"
          ??case?n?%?3?==?0:
          ????return?"Fizz"
          ??case?n?%?5?==?0:
          ????return?"Buzz"
          ??default:
          ????return?fmt.Sprintf("%d",?n)
          ??}
          }

          defer

          關鍵字 defer 可以定義延遲函數,在調用函數返回之前調用,通常在調用函數執(zhí)行結束之前自動關閉資源(比如文件句柄、數據庫連接等),像下面這樣:

          package?main

          import?(
          ??"os"
          ??"fmt"
          )

          func?Goodbye(name?string)?{
          ??fmt.Printf("Goodbye?%s",?name)
          }

          func?Hello(name?string)?{
          ??defer?Goodbye(name)
          ??fmt.Printf("Hello?%s",?name)
          }

          func?main()?{
          ??user?:=?os.Getenv("User")
          ??Hello(user)
          }

          執(zhí)行會輸出:

          $?./hello
          Hello?prologic
          Goodbye?prologic

          關于?defer 語句的詳細使用方法可以閱讀文末推薦閱讀掌握。

          錯誤處理

          Go 語言里 Errors 代表的是值,比如,使用 os.Open 打開一個文件,如果成功的話會返回一個指向文件的指針和 nil;否則返回 nil 指針和具體的錯誤。

          f,?err?:=?os.Open("/path/to/file")

          類似其他值類型一樣檢查錯誤:

          f,?err?:=?os.Open("/path/to/file")
          if?err?==?nil?{
          ??//?do?something?with?f
          }

          Go 語言里,通常的做法是檢查函數是否返回非 nil 錯誤,是的話就直接返回,比如:

          func?AppendFile(fn,?text?string)?error?{
          ??f,?err?:=?os.OpenFile(fn,?os.O_CREATE|os.O_APPEND|os.WR_ONLY,?0644)
          ??if?err?!=?nil?{
          ????return?fmt.Errorf("error?opening?file?for?writing:?%w",?err)
          ??}
          ??defer?f.Close()

          ??if?_,?err?:=?f.Write([]byte(text));?err?!=?nil?{
          ????return?fmt.Errorf("error?writing?text?to?fiel:?%w",?err)
          ??}

          ??return?nil
          }

          創(chuàng)建和導入包

          Go 支持 module(包管理),允許你創(chuàng)建并導入相關包,在剛開始的基本章節(jié)中,我們已經知道如何在啟動新項目時使用 go mod init 創(chuàng)建模塊。

          Go 的包僅僅是一個包含源代碼目錄:

          創(chuàng)建 Go 包的第一步是創(chuàng)建一個目錄,就像下面這樣:

          $?mkdir?shapes

          使用命令 go mod init 初始化:

          $?cd?shapes
          $?go?mod?init?github.com/prologic/shapes

          現在讓我們一起使用你最喜歡的編輯器創(chuàng)建一個 circle.go 模塊:

          package?shapes

          type?Circle?struct?{
          ??Radius?float64
          }

          func?(c?Circle)?String()?string?{
          ??return?fmt.Sprintf("Circle(%0.2f)",?c.Radius)
          }

          func?(c?Circle)?Area()?float64?{
          ??return?3.14?*?c.Radius?*?c.Radius
          }

          需要特別注意的是,包里的函數、結構體、變量和常量的首字母必須是大寫才是可導出的;否則即使你導入了相關包也無法訪問。

          現在,在 Git 上創(chuàng)建名為 shapes 的倉庫并 push 你的包代碼:

          $?git?init
          $?git?commit?-a?-m?"Initial?Commit"
          [email protected]:prologic/shapes.git
          $?git?push?-u?origin?master

          這樣的話,你就可以使用全路徑 github.com/prologic/shapes 導入 shapes 包,編譯時會根據路徑自動拉取并構建包。

          例如:

          我們使用 github.com/prologic/shapes 包做一個例子:

          $?mkdir?hello
          $?go?mod?init?hello

          編寫 main.go:

          package?main

          import?(
          ??"fmt"

          ??"github.com/prologic/shapes"
          )

          func?main()?{
          ??c?:=?shapes.Circle{Radius:?5}
          ??fmt.Printf("Area?of?%s:?%0.2f\n",?c,?c.Area())
          }

          編譯:

          $?go?build

          運行二進制文件:

          $?./hello
          Area?of?Circle(5.00):?78.50

          Congratulations!

          Now you're a Gopher!

          ps: 看原文評論,作者反饋接下來還會繼續(xù)更新原文,我們拭目以待,如果更新的話第一時間給大家分享。



          推薦閱讀


          福利

          我為大家整理了一份從入門到進階的Go學習資料禮包,包含學習建議:入門看什么,進階看什么。關注公眾號 「polarisxu」,回復?ebook?獲取;還可以回復「進群」,和數萬 Gopher 交流學習。

          瀏覽 38
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人片无码免费 | 欧美操逼视频大全 | 玩弄大荫蒂视频 | 91影院理论推荐手机在线观看 | 日本久久一区 |