新人作者求點(diǎn)贊 ^^
bilibili事件發(fā)生后,忽然意識到這么高大上的bilibili竟然是用Go(golang)語言寫的橙喘。忍不住我也要開始學(xué)這門有趣的語言时鸵。
其實(shí)Go官方是有非常好的中文版官方教程的,尊重版權(quán)[1] Golang Doc 厅瞎。
這里我與大家分享出來一些文檔的重點(diǎn)饰潜,首先是基礎(chǔ)篇的內(nèi)容,學(xué)完就能正式入門Go了和簸,希望大家能happy彭雾。(我邊學(xué)邊更新~)
包
每個(gè) Go 程序都是由包構(gòu)成的。
程序從 main
包開始運(yùn)行锁保。
本程序通過導(dǎo)入路徑 "fmt"
和 "math/rand"
來使用這兩個(gè)包薯酝。
按照約定半沽,包名與導(dǎo)入路徑的最后一個(gè)元素一致。例如吴菠,"math/rand"
包中的源碼均以 package rand
語句開始者填。
注意: 此程序的運(yùn)行環(huán)境是固定的,因此 rand.Intn
總是會(huì)返回相同的數(shù)字做葵。 (要得到不同的數(shù)字占哟,需為生成器提供不同的種子數(shù),參見 rand.Seed酿矢。 練習(xí)場中的時(shí)間為常量榨乎,因此你需要用其它的值作為種子數(shù)。)
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println("My favorite number is", rand.Intn(10))
}
導(dǎo)入
此代碼用圓括號組合了導(dǎo)入瘫筐,這是“分組”形式的導(dǎo)入語句蜜暑。
當(dāng)然你也可以編寫多個(gè)導(dǎo)入語句,例如:
import "fmt"
import "math"
不過使用分組導(dǎo)入語句是更好的形式严肪。
package main
import (
"fmt"
"math"
)
func main() {
fmt.Printf("Now you have %g problems.\n", math.Sqrt(7))
}
導(dǎo)出名
在 Go 中史煎,如果一個(gè)名字以大寫字母開頭,那么它就是已導(dǎo)出的驳糯。例如,Pizza
就是個(gè)已導(dǎo)出名氢橙,Pi
也同樣酝枢,它導(dǎo)出自 math
包。
pizza
和 pi
并未以大寫字母開頭悍手,所以它們是未導(dǎo)出的帘睦。
在導(dǎo)入一個(gè)包時(shí),你只能引用其中已導(dǎo)出的名字坦康。任何“未導(dǎo)出”的名字在該包外均無法訪問竣付。
執(zhí)行代碼,觀察錯(cuò)誤輸出滞欠。
然后將 math.pi
改名為 math.Pi
再試著執(zhí)行一次古胆。
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(math.Pi)
}
函數(shù)
函數(shù)可以沒有參數(shù)或接受多個(gè)參數(shù)。
在本例中筛璧,add
接受兩個(gè) int
類型的參數(shù)。
注意類型在變量名 之后夭谤。
(參考 這篇關(guān)于 Go 語法聲明的文章了解這種類型聲明形式出現(xiàn)的原因棺牧。)
package main
import "fmt"
func add(x int, y int) int {
return x + y
}
func main() {
fmt.Println(add(1, 2))
}
函數(shù)(續(xù))
當(dāng)連續(xù)兩個(gè)或多個(gè)函數(shù)的已命名形參類型相同時(shí)朗儒,除最后一個(gè)類型以外参淹,其它都可以省略。
在本例中乏悄,
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))
}
多值返回
函數(shù)可以返回任意數(shù)量的返回值浙值。
swap
函數(shù)返回了兩個(gè)字符串。
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 的返回值可被命名纲爸,它們會(huì)被視作定義在函數(shù)頂部的變量亥鸠。
返回值的名稱應(yīng)當(dāng)具有一定的意義,它可以作為文檔使用识啦。
沒有參數(shù)的 return
語句返回已命名的返回值负蚊。也就是 直接
返回。
直接返回語句應(yīng)當(dāng)僅用在下面這樣的短函數(shù)中颓哮。在長的函數(shù)中它們會(huì)影響代碼的可讀性家妆。
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
語句用于聲明一個(gè)變量列表,跟函數(shù)的參數(shù)列表一樣冕茅,類型在最后伤极。
就像在這個(gè)例子中看到的一樣,var
語句可以出現(xiàn)在包或函數(shù)級別姨伤。
package main
import "fmt"
var c, python, java bool
func main() {
var i int
fmt.Println(i, c, python, java)
}
變量的初始化
變量聲明可以包含初始值哨坪,每個(gè)變量對應(yīng)一個(gè)。
如果初始化值已存在乍楚,則可以省略類型当编;變量會(huì)從初始值中獲得類型。
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)
}
短變量聲明
在函數(shù)中徒溪,簡潔賦值語句 :=
可在類型明確的地方代替 var
聲明忿偷。
函數(shù)外的每個(gè)語句都必須以關(guān)鍵字開始(var
, func
等等),因此 :=
結(jié)構(gòu)不能在函數(shù)外使用臊泌。
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 的別名
// 表示一個(gè) Unicode 碼點(diǎn)
float32 float64
complex64 complex128
本例展示了幾種類型的變量鲤桥。 同導(dǎo)入語句一樣,變量聲明也可以“分組”成一個(gè)語法塊渠概。
int
, uint
和 uintptr
在 32 位系統(tǒng)上通常為 32 位寬茶凳,在 64 位系統(tǒng)上則為 64 位寬。 當(dāng)你需要一個(gè)整數(shù)值時(shí)應(yīng)使用 int
類型高氮,除非你有特殊的理由使用固定大小或無符號的整數(shù)類型慧妄。
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)
}
零值
沒有明確初始值的變量聲明會(huì)被賦予它們的 零值。
零值是:
- 數(shù)值類型為
0
剪芍, - 布爾類型為
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)
}
類型轉(zhuǎn)換
表達(dá)式 T(v)
將值 v
轉(zhuǎn)換為類型 T
纹笼。
一些關(guān)于數(shù)值的轉(zhuǎn)換:
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
或者,更加簡單的形式:
i := 42
f := float64(i)
u := uint(f)
與 C 不同的是运挫,Go 在不同類型的項(xiàng)之間賦值時(shí)需要顯式轉(zhuǎn)換。試著移除例子中 float64
或 uint
的轉(zhuǎn)換看看會(huì)發(fā)生什么套耕。
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)
}
類型推導(dǎo)
在聲明一個(gè)變量而不指定其類型時(shí)(即使用不帶類型的 :=
語法或 var =
表達(dá)式語法)谁帕,變量的類型由右值推導(dǎo)得出冯袍。
當(dāng)右值聲明了類型時(shí),新變量的類型與其相同:
var i int
j := i // j 也是一個(gè) int
不過當(dāng)右邊包含未指明類型的數(shù)值常量時(shí)康愤,新變量的類型就可能是 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
關(guān)鍵字叔收。
常量可以是字符、字符串缤灵、布爾值或數(shù)值。
常量不能用 :=
語法聲明。
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)
}
數(shù)值常量
數(shù)值常量是高精度的 值帖鸦。
一個(gè)未指定類型的常量由上下文來決定其類型。
再嘗試一下輸出 needInt(Big)
吧作儿。
(int
類型最大可以存儲(chǔ)一個(gè) 64 位的整數(shù),有時(shí)會(huì)更小攻锰。)
(int
可以存放最大64位的整數(shù),根據(jù)平臺(tái)不同有時(shí)會(huì)更少娶吞。)
package main
import "fmt"
const (
// 將 1 左移 100 位來創(chuàng)建一個(gè)非常大的數(shù)字
// 即這個(gè)數(shù)的二進(jìn)制是 1 后面跟著 100 個(gè) 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))
}