Go 語言官方教程-學習指南-快速入門
bilibili事件發生後,忽然意識到這麼高大上的bilibili竟然是用Go(golang)語言寫的。忍不住我也要開始學這門有趣的語言。
其實Go官方是有非常好的中文版官方教程的,尊重版權[1](Golang Doc)。
這裡我與大家分享出來一些文件的重點,首先是基礎篇的內容,學完就能正式入門Go了,希望大家能happy。(我邊學邊更新~)
包
每個 Go 程式都是由包構成的。
程式從main
包開始執行。
本程式通過匯入路徑"fmt"
和"math/rand"
來使用這兩個包。
按照約定,包名與匯入路徑的最後一個元素一致。例如,"math/rand"
包中的原始碼均以package rand
語句開始。
*注意:* 此程式的執行環境是固定的,因此rand.Intn
總是會返回相同的數字。 (要得到不同的數字,需為生成器提供不同的種子數,參見rand.Seed
。 練習場中的時間為常量,因此你需要用其它的值作為種子數。)
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println("My favorite number is", rand.Intn(10))
}
匯入
此程式碼用圓括號組合了匯入,這是“分組”形式的匯入語句。
當然你也可以編寫多個匯入語句,例如:
import "fmt" import "math"
不過使用分組匯入語句是更好的形式。
package main
import (
"fmt"
"math"
)
func main() {
fmt.Printf("Now you have %g problems.\n", math.Sqrt(7))
}
匯出名
在 Go 中,如果一個名字以大寫字母開頭,那麼它就是已匯出的。例如,Pizza
就是個已匯出名,Pi
也同樣,它匯出自math
包。
pizza
和pi
並未以大寫字母開頭,所以它們是未匯出的。
在匯入一個包時,你只能引用其中已匯出的名字。任何“未匯出”的名字在該包外均無法訪問。
執行程式碼,觀察錯誤輸出。
然後將math.pi
math.Pi
再試著執行一次。
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(math.Pi)
}
函式
函式可以沒有引數或接受多個引數。
在本例中,add
接受兩個int
型別的引數。
注意型別在變數名之後。
(參考這篇關於 Go 語法宣告的文章瞭解這種型別宣告形式出現的原因。)
package main
import "fmt"
func add(x int, y int) int {
return x + y
}
func main() {
fmt.Println(add(1, 2))
}
函式(續)
當連續兩個或多個函式的已命名形參型別相同時,除最後一個型別以外,其它都可以省略。
在本例中,
x int, y int
被縮寫為
x, y int
package main
import "fmt"
func add(x, y double) int {
return x + y
}
func main() {
fmt.Println(add(42, 13))
}
多值返回
函式可以返回任意數量的返回值。
swap
函式返回了兩個字串。
package main
import "fmt"
func swap(x, y string) (string, string) {
return y, x
}
func main() {
a, b := swap("hello", "world")
fmt.Println(a, b)
}
命名返回值
Go 的返回值可被命名,它們會被視作定義在函式頂部的變數。
返回值的名稱應當具有一定的意義,它可以作為文件使用。
沒有引數的return
語句返回已命名的返回值。也就是直接
返回。
直接返回語句應當僅用在下面這樣的短函式中。在長的函式中它們會影響程式碼的可讀性。
package main
import "fmt"
func split(sum int) (x int) {
x = sum * 4 / 9
y = sum - x
return
}
func main() {
fmt.Println(split(17))
}
變數
var
語句用於宣告一個變數列表,跟函式的引數列表一樣,型別在最後。
就像在這個例子中看到的一樣,var
語句可以出現在包或函式級別。
package main
import "fmt"
var c, python, java bool
func main() {
var i int
fmt.Println(i, c, python, java)
}
變數的初始化
變數宣告可以包含初始值,每個變數對應一個。
如果初始化值已存在,則可以省略型別;變數會從初始值中獲得型別。
package main
import "fmt"
var i, j int = 1, 2
func main() {
var c, python, java = true, false, "no!"
fmt.Println(i, j, c, python, java)
}
短變數宣告
在函式中,簡潔賦值語句:=
可在型別明確的地方代替var
宣告。
函式外的每個語句都必須以關鍵字開始(var
,func
等等),因此:=
結構不能在手機遊戲賬號交易地圖函式外使用。
package main
import "fmt"
func main() {
var i, j int = 1, 2
var p bool
k := 1.1
c, python, java := true, false, "no!"
fmt.Println(i, j, p,k, c, python, java)
}
基本型別
Go 的基本型別有
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // uint8 的別名
rune // int32 的別名
// 表示一個 Unicode 碼點
float32 float64
complex64 complex128
本例展示了幾種型別的變數。 同匯入語句一樣,變數宣告也可以“分組”成一個語法塊。
int
,uint
和uintptr
在 32 位系統上通常為 32 位寬,在 64 位系統上則為 64 位寬。 當你需要一個整數值時應使用int
型別,除非你有特殊的理由使用固定大小或無符號的整數型別。
package main
import (
"fmt"
"math/cmplx"
)
var (
ToBe bool = false
MaxInt uint64 = 1<<64 - 1
z complex128 = cmplx.Sqrt(-5 + 12i)
)
func main() {
fmt.Printf("Type: %T Value: %v\n", ToBe, ToBe)
fmt.Printf("Type: %T Value: %v\n", MaxInt, MaxInt)
fmt.Printf("Type: %T Value: %v\n", z, z)
}
零值
沒有明確初始值的變數宣告會被賦予它們的零值。
零值是:
- 數值型別為
,
- 布林型別為
false
, - 字串為
""
(空字串)。
package main
import "fmt"
func main() {
var i int
var f float64
var b bool
var s string
fmt.Printf("%v %v %v %q\n", i, f, b, s)
}
型別轉換
表示式T(v)
將值v
轉換為型別T
。
一些關於數值的轉換:
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
或者,更加簡單的形式:
i := 42
f := float64(i)
u := uint(f)
與 C 不同的是,Go 在不同型別的項之間賦值時需要顯式轉換。試著移除例子中float64
或uint
的轉換看看會發生什麼。
package main
import (
"fmt"
"math"
)
func main() {
var x, y int = 3, 4
var f float64 = math.Sqrt(float64(x*x + y*y))
var z int = int(f)
fmt.Println(x, y, z)
}
型別推導
在宣告一個變數而不指定其型別時(即使用不帶型別的:=
語法或var =
表示式語法),變數的型別由右值推導得出。
當右值聲明瞭型別時,新變數的型別與其相同:
var i int
j := i // j 也是一個 int
不過當右邊包含未指明型別的數值常量時,新變數的型別就可能是int
,float64
或complex128
了,這取決於常量的精度:
i := 42 // int
f := 3.142 // float64
g := 0.867 + 0.5i // complex128
嘗試修改示例程式碼中v
的初始值,並觀察它是如何影響型別的。
package main
import "fmt"
func main() {
v := 42.00000000000001 // 修改這裡!
fmt.Printf("v is of type %T\n", v)
}
常量
常量的宣告與變數類似,只不過是使用const
關鍵字。
常量可以是字元、字串、布林值或數值。
常量不能用:=
語法宣告。
package main
import "fmt"
const Pi = 3.14
func main() {
const World = "世界"
fmt.Println("Hello", World)
fmt.Println("Happy", Pi, "Day")
const Truth = true
fmt.Println("Go rules?", Truth)
}
數值常量
數值常量是高精度的值。
一個未指定型別的常量由上下文來決定其型別。
再嘗試一下輸出needInt(Big)
吧。
(int
型別最大可以儲存一個 64 位的整數,有時會更小。)
(int
可以存放最大64位的整數,根據平臺不同有時會更少。)
package main
import "fmt"
const (
// 將 1 左移 100 位來建立一個非常大的數字
// 即這個數的二進位制是 1 後面跟著 100 個 0
Big = 1 << 100
// 再往右移 99 位,即 Small = 1 << 1,或者說 Small = 2
Small = Big >> 99
)
func needInt(x int) int { return x*10 + 1 }
func needFloat(x float64) float64 {
return x * 0.1
}
func main() {
fmt.Println(needInt(Small))
fmt.Println(needFloat(Small))
fmt.Println(needFloat(Big))
}