go語言中關鍵字有25個,分別有:break(退出迴圈)、default(選擇結構預設項)、func(定義函數)、interface(定義介面)、case(選擇結構標籤)、const(定義常數)、continue、select、chan、continue(跳過本次迴圈)、defer(延遲執行內容)、go、map、struct、else、goto、package、switch等。
本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。
關鍵字(也稱為保留字)是被程式語言保留而不讓程式設計人員作為識別符號使用的字元序列。
關鍵字即是被Go語言賦予了特殊含義的單詞,也可以稱為保留字。
Go語言中的關鍵字一共有 25 個,之所以刻意地將Go語言中的關鍵字保持的這麼少,是為了簡化在編譯過程中的程式碼解析。和其它語言一樣,關鍵字不能夠作識別符號使用。
保留關鍵字 | 說明 |
---|---|
break | 退出迴圈 |
default | 選擇結構預設項(switch、select) |
func | 定義函數 |
interface | 定義介面 |
select | channel |
case | 選擇結構標籤 |
chan | 定義 channel |
const | 常數 |
continue | 跳過本次迴圈 |
defer | 延遲執行內容(收尾工作) |
go | 並行執行 |
map | map 型別 |
struct | 定義結構體 |
else | 選擇結構 |
goto | 跳轉語句 |
package | 包 |
switch | 選擇結構 |
fallthrough | 流程控制 |
if | 選擇結構 |
range | 從 slice、map 等結構中取元素 |
type | 定義型別 |
for | 迴圈 |
import | 匯入包 |
return | 返回 |
var | 定義變數 |
Go的25個關鍵字按照作用可以分為3類,分別為包管理、程式實體宣告與定義與程式流程控制。
類別 | 關鍵字 |
---|---|
程式宣告 | import, package |
程式實體宣告和定義 | chan, const, func, interface, map, struct, type, var |
程式控制流程 | go, select, break, case, continue, default, defer, else, fallthrough, for, goto, if, range, return, switch |
說明:
在Go語言中,程式實體的宣告和定義是建立在其資料型別的體系之上的。例如關鍵字chan、func、interface、map和struct,分別於Go語言的複合資料型別Channel(通道)、Function(函數)、Interface(介面)、Map(字典)和Struct(結構體)相對應。
程式控制流程的關鍵字,一共15個。其中go和select,這兩個主要用於Go語言並行程式設計。
2.1 import
import 用於匯入包,這樣就可以使用包中被匯出的識別符號。匯入格式如下:
import _ "package path"
import . "package path"
import alias "package path"
import (
_ "package path"
. "package path"
alias "package path"
)
登入後複製
其中包路徑前面可以有三中修飾符中的某一個。下劃線即空白識別符號,表示不使用包中的識別符號,只需要包的副作用,即計算包級變數的初始化表示式和執行匯入包的init初始化函數。點號代替包的別名, 表示存取包中的匯出識別符號無需使用包名。alias則表示包的別名。
匯入範例如下:
匯入宣告 Sin的本地名
import "lib/math" math.Sin
import m "lib/math" m.Sin
import . "lib/math" Sin
登入後複製
2.2 package
package用於宣告包的名稱,需放在go檔案所有程式碼的最前面。一個包由一個或多個go原始檔組成,需放在同一個目錄下,且同一個目錄下的這些go檔案的package的名字只能有一個。申明格式如下:
package <packagename>
登入後複製
packagename不能為空白識別符號_。
3.1 chan
chan用於宣告channel(通道)。通道提供一種機制使兩個並行執行的函數實現同步,並通過傳遞具體元素型別的值來通訊。未初始化的通道值為 nil。宣告格式如下:
chan T // 可以被用來傳送和接收型別T的值
chan<- T // 只能被用來傳送浮點數
<-chan T // 只能被用來接收整數
登入後複製
其中<-操作符指定通道的方向,傳送或接收。若沒有給定方向,那麼該通道就是雙向的。通道可通過型別轉換或賦值被強制為只傳送或只接收。
通道的初始化可以通過 make 函數來實現,其結果值充當了對底層資料結構的參照。初始化時可以為通道設定緩衝區大小,預設值是零,表示不帶緩衝的或同步的通道。
ci := make(chan int) // 整數型別的無緩衝通道
cj := make(chan int, 0) // 整數型別的無緩衝通道
cp := make(chan *os.File, 100) // 指向檔案指標的帶緩衝通道
登入後複製
3.2 const
const 用於定義常數,一旦建立,不可賦值修改。const可以出現在任何關鍵字 var 可以出現的地方,宣告常數方式與 var 宣告變數方式相同,格式如下:
const name = value
const name T = value
const (
name = value
name T = value
)
登入後複製
注意,Golang 中的 const 不支援像 C/C++ 中修飾函數的引數和返回值,即下面的語句是非法的。
func test(const name *string)
func test(name *string) const *string
登入後複製
3.3 func
func 用於定義函數。Go函數支援變參且返回值支援多個,但不支援預設引數。如果函數存在多個返回值形參則需要使用小括號括起來,定義格式如下:
func funcName(){} //無參無返回值
func funcName(t T) T {} //有參有返回值
func funcName(t T, list ...T) (T1,T1) {} //有變參有多個返回值
登入後複製
程式碼格式上需要注意的是,函數體的第一個大括號必須函數名同行。這個是Go對程式碼格式的強制要求,在其它的語句中也是如此,比如if else語句、for語句、switch語句、select語句等。
3.4 interface
interface 用於定義介面。一個介面是一個方法集,如果一個型別實現了一個介面中的所有方法集,那麼說明該型別實現此介面。介面型別變數可以儲存任何實現了該介面的型別的值。特別的,interface{}表示空介面型別,預設地,所有型別均實現了空介面,所以interface{}可以接收任意型別值。範例如下:
//空介面
interface{}
//一個簡單的File介面
type File interface {
Read(b Buffer) bool
Write(b Buffer) bool
Close()
}
登入後複製
3.5 map
map 用於宣告對映變數。對映屬容器類型別,是一個同種型別元素的無序組,通過唯一的鍵可以獲取對應的值。可以使用 make 建立 map 變數,未初始化的對映值為 nil。建立map變數主要有如下幾種方式:
//建立0容量的map
var myMap = make(map[T1] T2)
//建立指定容量的map
var myMap = make(map[T]T2, cap)
//建立並初始化map
var myMap = map[string]int {
"dable" : 27,
"cat" : 28,
}
登入後複製
使用範例:
package main
import "fmt"
func main() {
nameAge := make(map[string]int)
nameAge["bob"] = 18 //增
nameAge["tom"] = 16 //增
delete(nameAge, "bob") //刪
nameAge["tom"] = 19 //改
v := nameAge["tom"] //查
fmt.Println("v=",v)
v, ok := nameAge["tom"] //查,推薦用法
if ok {
fmt.Println("v=",v,"ok=",ok)
}
for k, v :=range nameAge { //遍歷
fmt.Println(k, v)
}
}
登入後複製
輸出結果:
v= 19
v= 19 ok= true
tom 19
登入後複製
3.6 struct
struct 用於定義結構體。結構體屬容器類型別,是多個相同或不同型別值的集合。
package main
import "fmt"
type Vertex struct {
X, Y int
}
var (
v1 = Vertex{1, 2} // 型別為 Vertex
v2 = Vertex{X: 1} // Y:0 被省略
v3 = Vertex{} // X:0 和 Y:0
p = &Vertex{1, 2} // 型別為 *Vertex
)
func main() {
fmt.Printf("%#v %#v %#v %#v\n", v1, v2, v3, p)
}
登入後複製
輸出結果:
main.Vertex{X:1, Y:2} main.Vertex{X:1, Y:0} main.Vertex{X:0, Y:0} &main.Vertex{X:1, Y:2}
登入後複製
3.7 type
type 用於定義型別,比如定義struct、interface與等價型別。
//定義struct
type Person struct { name string }
//定義介面
type Person interface {
speak(word string)
}
//定義等價型別,rune等價於int32
type rune int32
登入後複製
3.8 var
var 用於定義變數,語法格式主要有:
var name T //name預設為型別T的零值
var name = value //根據值value推斷變數name的型別
var name T = value //賦初始值時指明型別
var name1, name2 T //同時定義多個同型別變數
//同時定義多個不同型別的變數
var (
name string ="dable"
age int = 18
)
登入後複製
定義變數可以使用:=來替代var,但是:=運運算元只能用於函數體內。
4.1 for range break continue
(1)for 與 range for是Go中唯一用於迴圈結構的關鍵詞。有三個使用方式,分別是單個迴圈條件,經典的初始化/條件/後續形式,還有和range關鍵詞結合使用來遍歷容器類物件(陣列、切片、對映)。
//單條件
i := 1
for i <= 3 {
fmt.Println(i)
i = i + 1
}
//初始化/條件/後續形式
//注意Go中沒有前置自增與自減運運算元,即++i是非法的
for i:=0; i < 3; i++ {
fmt.Println(i)
}
//for range形式遍歷陣列
array :=[...]int{0,1,2,3,4,5}
for i, v :=range array{
fmt.Println(i,v)
}
登入後複製
(2)break break用於終止最內層的"for"、「switch"或"select"語句的執行。break可以攜帶標籤,用於跳出多層。如果存在標籤,則標籤必須放在"for」、"switch"或"select"語句開始處。
//終止for
L:
for i < n {
switch i {
case 5:
break L
}
}
登入後複製
(3)continue continue通常用於結束當前迴圈,提前進入下一輪迴圈。也可以像break一樣攜帶標籤,此時程式的執行流跳轉到標籤的指定位置,可用於跳出多層"for"、「switch"或"select」,提前進入下一輪的執行。範例如下:
//提前進入下一輪迴圈
for i:=0; i < 3; i++ {
if i == 1 {
continue
}
fmt.Println(i)
}
//輸出結果
0
2
//提前進入標籤處for的下一輪迴圈
L:
for i:=0; i < 2; i++ {
for j:=0; j < 3; j++{
if j == 1 {
continue L
}
fmt.Println(i, j)
}
}
//輸出結果
0 0
1 0
登入後複製
4.2 goto
goto用於將程式的執行轉移到與其標籤相應的語句。可以使用goto退出多層"for"、「switch"或"select」,功能類似於break攜帶標籤。
//終止for
L:
for i < n {
switch i {
case 5:
goto L
}
}
登入後複製
注意事項: (1)執行"goto"不能在跳轉過程中跳過變數的定義,不然會報編譯錯誤。例如:
goto L //編譯報錯
v := 3
L:
fmt.Println(v)
登入後複製
(2)在塊外的goto語句不能跳轉至該塊中的標籤。例如:
if n%2 == 1 {
goto L1
}
for n > 0 {
f()
n--
L1:
f()
n--
}
登入後複製
是錯誤的,因為標籤 L1 在"for"語句的塊中而 goto 則不在。 (3)程式設計時,應儘量避免使用goto語句,因為程式執行流的隨意跳轉會破壞結構化設計風格,導致程式碼可讀性下降。
4.3 switch case default fallthrough
這四個關鍵詞是結合使用的。switch語句提供多路執行,表示式或型別說明符與switch中的case相比較從而決定執行哪一分支。default用於給出預設分支,即所有的case分支都不滿足時執行default分支。Go中的switch語句在執行完某個case子句後,不會再順序地執行後面的case子句,而是結束當前switch語句。使用fallthrough可以繼續執行後面的case與default子句。
下面分別以表示式選擇或型別選擇為例演示switch case default fallthrough的用法。
//表示式選擇
switch tag {
default: s3() //default子句可以出現在switch語句中的任意位置,不一定是最後一個
case 0, 1, 2, 3: s1() //case表示式可以提供多個待匹配的值,使用逗號分隔
case 4, 5, 6, 7: s2()
}
switch x := f(); {
case x < 0: return -x //case表示式無需為常數
default: return x
}
switch { //缺失的switch表示式意為"true"
case x < y: f1()
fallthrough //強制執行下一個case子句
case x < z: f2()
//此處沒有fallthrough,switch執行流在此終止
case x == 4: f3()
}
//型別選擇
switch i := x.(type) {
case int:
printInt(i) // i 的型別為 int
case float64:
printFloat64(i) // i 的型別為 float64
case func(int) float64:
printFunction(i) // i 的型別為 func(int) float64
case bool, string:
printString("type is bool or string") // i 的型別為 bool or string
default:
printString("don't know the type") // i 的型別未知
}
登入後複製
4.4 if else
if與else實現條件控制,與C有許多相似之處,但也有其不同之處。變化主要有三點: (1)可省略條件表示式的括號; (2)支援初始化語句,可定義程式碼塊區域性變數; (3)if與else塊中只有一條語句也需要新增大括號; (4)起始大括號必須與if與else同行。
if err := file.Chmod(0664); err != nil {
log.Print(err)
return err
}
登入後複製
4.5 return defer
(1)return return用於函數執行的終止並可選地提供一個或多個返回值。 任何在函數F中被推遲的函數會在F 返回給其呼叫者前執行。函數可以通過return返回多個值。如果返回值在函數返回形參中指定了名字,那麼return時可不帶返回值列表。
//無返回值
func noResult() {
return
}
//單返回值
func simpleF() int {
return 2
}
//多返回值
func complexF2() (float64, float64) {
re = 7.0
im = 4.0
return re, im
}
//返回值已具名
unc complexF3() (re float64, im float64) {
re = 7.0
im = 4.0
return
}
登入後複製
(2)defer defer語句用於預設一個函數呼叫,即推遲函數的執行。 該函數會在執行 defer 的函數返回之前立即執行。它顯得非比尋常, 但卻是處理一些事情的有效方式,例如無論以何種路徑返回,都必須釋放資源的函數。 典型的例子就是解鎖互斥和關閉檔案。
//將檔案的內容作為字串返回。
func Contents(filename string) (string, error) {
f, err := os.Open(filename)
if err != nil {
return "", err
}
defer f.Close() // f.Close 會在函數結束後執行
var result []byte
buf := make([]byte, 100)
for {
n, err := f.Read(buf[0:])
result = append(result, buf[0:n]...)
if err != nil {
if err == io.EOF {
break
}
return "", err // 我們在這裡返回後,f 就會被關閉
}
}
return string(result), nil // 我們在這裡返回後,f 就會被關閉
}
登入後複製
推遲諸如 Close 之類的函數呼叫有兩點好處:第一, 它能確保你不會忘記關閉檔案。如果你以後又為該函數新增了新的返回路徑時, 這種情況往往就會發生。第二,它意味著「關閉」離「開啟」很近, 這總比將它放在函數結尾處要清晰明瞭。
使用defer時,需要注意兩點: (a)被推遲函數的實參(如果該函數為方法則還包括接收者)在推遲執行時就會求值,而不是在呼叫執行時才求值。這樣不僅無需擔心變數值在函數執行時被改變, 同時還意味著可以給被推遲的函數傳遞不同引數。下面是個簡單的例子。
for i := 0; i < 5; i++ {
defer fmt.Printf("%d ", i)
}
登入後複製
(b)被推遲的函數按照後進先出(LIFO)的順序執行,因此以上程式碼在函數返回時會列印 4 3 2 1 0。
4.6 go
go用於建立Go程(goroutine),實現並行程式設計。Go程是與其它Go程並行執行在同一地址空間的函數,相比於執行緒與程序,它是輕量級的。Go程在多執行緒作業系統上可實現多路複用,因此若一個執行緒阻塞,比如說等待I/O,那麼其它的執行緒就會執行。Go程的設計隱藏了執行緒建立和管理的諸多複雜性。
在函數或方法前新增 go 關鍵字能夠在新的Go程中呼叫它。當呼叫完成後,該Go程也會安靜地退出。效果有點像Unix Shell中的 & 符號,它能讓命令在後臺執行。
package main
import (
"fmt"
"time"
)
func main() {
go func(){
fmt.Println("in first goroutine")
}()
go func(){
fmt.Println("in second goroutine")
}()
fmt.Println("main thread start sleep, and other goroutine start execute")
time.Sleep(10*time.Second)
}
登入後複製
輸出結果:
main thread start sleep, and other goroutine start execute
in second goroutine
in first goroutine
登入後複製
注意,從輸出結果可以看出,go程的執行順序和建立的順序是沒有關係的,也就是說存在多個go程時,其執行的順序是隨機的。
4.7 select
select語句用來選擇哪個case中的傳送或接收操作可以被立即執行。它類似於switch語句,但是它的case涉及channel有關的I/O操作。也就是說select就是用來監聽和channel有關的IO操作,它與select, poll, epoll相似,當IO操作發生時,觸發相應的動作,實現IO多路複用。
package main
import "fmt"
func main(){
ch1 := make(chan int, 1)
ch2 := make(chan int, 1)
ch1 <- 3
ch2 <- 5
select {
case <- ch1:
fmt.Println("ch1 selected.")
case <- ch2:
fmt.Println("ch2 selected.")
default:
//如果ch1與ch2沒有資料到來,則進入default處理流程。如果沒有default子句,則select一直阻塞等待ch1與ch2的資料到來
fmt.Println("default")
}
}
登入後複製
輸出結果:
ch1 selected.
//或者
ch2 selected.
登入後複製
從輸出結果可以看出,當存在多個case滿足條件,即有多個channel存在資料時,會隨機的選擇一個執行。
【相關推薦:Go視訊教學、】
以上就是go語言中關鍵字有多少個的詳細內容,更多請關注TW511.COM其它相關文章!