文章目錄
一、常量和變量
1、常量
const identifier [type] = value
2、變量
2.1 局部變量
identifier: = value <==> var identifier [type] = value
2.2 全局變量
var identifier [type] = value
2.3 匿名變量
" _"
二、基本數據類型
1、整型
int、uint
2、浮點
float32、float64
3、布爾型
bool
4、複數
complex32
complex64
5、字符串
string
6、字符串處理(strings 包)
6.1 包含判斷
HasPrefix、HasSuffix、Contains、ContainsAny (返回值都是 bool )
6.2 索引
Index、LastIndex、IndexRune (返回值都是 int )
6.3 替換
Replace (返回一個新的 string)
6.4 統計
Count、utf8.RuneCountInString (返回值都是 int )
6.5 大小寫轉化
ToLower、ToUpper (返回一個新的 string)
6.6 修剪
Trim (返回一個新的 string)
6.7 分割
Splite (返回一個 slice (切片))
6.8 字符串轉化成字符串切片
Fields (返回一個 []string 切片)
6.9 插入
Join
7、字符傳與其他類型轉換(strconv包)
7.1 數字轉化成字符串
Itoa、FormatFloat、FormatBool
7.2 數值字符串轉化成對應數值類型
Atoi、ParseFloat、ParseBool
7.3 自定義類型轉化成字符串
Stringer
三、基本數據類型擴展
1、強制類型轉換
type_name(expression)
2、自定義類型
type name struct { }
3、類型別名
type
4、指針
4.1 聲明 var name *type
4.2 nil 指針
4.3 指針的指針 **ptr
4.4 指針數組 var ptr []*type
4.5 傳遞給函數
四、流程控制語句
1、條件語句
if、if-else、if-else if- else
2、選擇語句
switch
3、循環語句
for、range
4、延遲語句
defer
5、標籤語句
break、continue、goto
一、常量和變量
1、常量
在GO語言中,常量是指編譯期間就已知,且在執行過程中不會改變的固定值。
const identifier[type] = value ,其中 type 可省略
批量定義常量
const a,b,c = 1,2,3
const (
x int = 1
y float64 = 2.0
z = true
)
fmt.Println(a,b,c,x,y,z)
用於實現枚舉
func enum() {
const(
a = iota
b
c
d
)
fmt.Println(a,b,c,d) //0、1、2、3 iota有遞增效果,常用於 枚舉
}
常量沒指定類型可以是任意類型。例如: a 可以是浮點也可以是整型。
2、變量
var identifier type
GO 與其他語言最大的不同在於: 聲明變量時,變量類型放在變量名後面。
批量定義變量
var a,b,c = "string",1,true
var(
x,y int
str string
)
2.1 局部變量
func main() {
a := 1 //等價於 var a = 1
var b = 1
fmt.Println(a,b)
}
備註: a := 1
這種定義變量的方式只能用於函數體內。局部變量定義了必須使用,否則會報錯。
2.2 全局變量
var z = true
func main() {
fmt.Println(z)
}
備註: 全局變量定義不限制位置。允許聲明但不使用。
2.3 匿名變量
GO 語言中,函數允許多個返回值。在日常處理中,我們可能會忽略部分返回值的情況,那麼用"_"替代。
二、基本數據類型
1、整型
無符號 uint
有符號 int
整型的運算與主流的編程語言並不差異。這裏不做過多介紹。
2、浮點型
float32 精確到小數點後 7 位
float64 精確到小數點後 15 位
備註: GO語言中沒有 float 這種類型。在運算中推薦使用 float64
3、布爾型
布爾型( bool )的值只可以是 ture 或者 false
支持一元運算符 : !
支持二元運算符 : && 、|| 、==
格式化輸出: %t
4、複數
規定 i = 根號-1,也就是 i^2 = 1
複數 a + bi 的模 = a^2 + b ^2 的算術平方根,其中 a 爲實部位,b 爲虛部
複數支持常規數據運算,實部和虛部都是浮點型
在運算中推薦使用complex64
操作複數的方法在cmath
包中
func complexValue() {
a := 3.2 + 5i
b := complex(3.2,5) // b := 3.2 + 5i
fmt.Printf("複數 a 的實部 = %f, 複數 b 的實部 = %f\n",real(a),real(b))
fmt.Printf("複數 a 的虛部 = %f, 複數 b 的虛部 = %f\n",imag(a),imag(b))
fmt.Printf("複數 a 的模 = %f",cmplx.Abs(a))
}
著名歐拉公式 :e^(i+pi) +1 = 0
fmt.Println(cmplx.Pow(math.E,1i*math.Pi)+1)
fmt.Println(cmplx.Exp(1i*math.Pi)+1)
fmt.Printf("%.3f\n",cmplx.Exp(1i*math.Pi)+1)
5、字符串
在 GO 語言中,字符串是一個不可變的 UTF-8 字符序列。一個 ASCII 碼佔用一個字節,其他字符根據需要佔用 2 ~ 4 字節。字符串是一個定長的字節數組。GO 語言默認就是採用 UTF-8 編碼格式進行文件存儲。
5.1 定義一個字符串
var test string = "abc.txt"
str := "abc 中國"
5.2 獲取字符串字節數目和字符數目
str := "cherish中國"
r := []rune(str)
fmt.Printf("字符串 str 的字節數 = %d ,字符數 = %d \n",len(str),len(r)) // 13、9
5.3 訪問字符串中某個字節、某個字符
str := "aA 你 2"
for index := 0; index < len(str); index++{
fmt.Println(str[index])
}
str[index]返回第 index 個字節的字節值, 0 <= index < len[str]
輸出:
97 //a
65 //A
32 //空格
228 //你
189 //你
160 //你
32 //空格
50 //2
str := "cherish中國"
for index,value := range str{
fmt.Printf("index = %d ,value = %c \n",index,value)
}
輸出
index = 0 ,value = c
index = 1 ,value = h
index = 2 ,value = e
index = 3 ,value = r
index = 4 ,value = i
index = 5 ,value = s
index = 6 ,value = h
index = 7 ,value = 中
index = 10 ,value = 國
5.4 解釋字符串和非解釋字符串
解釋字符串: 使用 ""
括起來,不能換行,並且能解析轉義字符
非解釋字符串 : 使用 反單引號 括起來,支持換行,反單引號內所有內容直接輸出
5.5 字符串拼接
字符串可以拼接,用 " + " 拼接字符串,但原字符串不會改變
str := "你好"
t := str
str += "golang"
fmt.Printf("str = %s,t = %s",str,t) //str = 你好golang,t = 你好
5.6 字符串之間的比較
在 GO 語言中,字符串是可以使用 “==” 和 “<” 等符號進行比較的,通過比較逐字節的編碼獲得結果。
s := "你"
t := "好"
if s < t {
fmt.Println(s[0],t[0]) //228 229
fmt.Println(s[1],t[1]) //189 165
fmt.Println(s[2],t[2]) //160 189
}
a := "a"
b := "b"
if a < b {
fmt.Println(a[0],"小於",b[0]) //97 小於 98
}
test := "你好"
test1 := "你好"
if test == test1{
fmt.Println("兩字符串相等")
}
5.7 字符串修改
在 GO 語言中,字符串內容不能修改,也就不能使用 s[i] 這種方式修改字符串中的 UTF-8 編碼。如果確實要修改,那麼可以將字符串的內容複製到另一個可寫變量中,然後再進行修改。
如果要對字符串中的字節進行修改,則轉換成 []byte 格式
如果要對字符串中的字符進行修改,則轉換成 []rune 格式
轉換過程中,會自動複製數據。
s := "Hello Word!"
b := []byte(s) //轉換爲 []byte,自動複製數據
b[5] = ',' // 修改 []byte
fmt.Printf("修改字符串中的字節: s = %s \n b = %s\n",s,b)
//輸出
修改字符串中的字節: s = Hello Word!
b = Hello,Word!
s1 := "Hello 中國!"
r := []rune(s1) //轉化成 []run,自動複製數據
r[6] = '世' //修改 []run
r[7] = '界' //修改 []run
fmt.Printf("修改字符串中的字符: s = %s \n b = %s\n",s1,string(r))
//轉化成字符串,又一次複製數據
//輸出
修改字符串中的字符: s = Hello 中國!
r = Hello 世界!
備註 : 如果字符串是純 ASCII 字符串,兩種是等價的。
5.8 字符串截取
在日常開發中,我們經常會遇到字符串截取的需求。如果優雅在進行字符串截取呢,這裏涉及到部分 slice 內容。建議初學者後面學到 slice 再往這裏看。
** 5.8.1 字節截取**
test := "你好hello word"
substr := test[3:7]
fmt.Println(substr) // 好h => 截取 區間 [3,7) 之前的字節
5.8.2 字符截取
str := "你好hello word"
r := []rune(str)
fmt.Println(string(r[1:5])) //好hel => 截取區間 [1,5)之間的字符
fmt.Println(string(r[1:])) //好hello word => 截取 index = 1 後面的全部字符
fmt.Println(string(r[:2])) //你好 =>截取 [0,2) 前的全部字符,不包含 index = 2
6、字符串處理(strings包)
對於基本類型來說,字符串所需要執行的操作比較複雜,所以一般語言都會額外封裝一些方法用於處理字符串,GO 語言標準庫中也存在這樣一個名爲 strings
的庫。
6.1 包含判斷
HasPrefix
(包含前綴)
HasSuffix
(包含後綴)
Contains
(包含子串)
ContainsAny
(匹配更廣泛的內容,甚至可以匹配 Unicode 字符)
func stringsContain(){
str := "This is an example of a string"
fmt.Printf("Does the string \"%s\" have prefix %s ?\n",str,"Th") //true
fmt.Printf("%t\n",strings.HasPrefix(str,"Th"))
fmt.Printf("Does the string \"%s\" have suffix %s ?\n",str,"string")
fmt.Printf("%t\n",strings.HasSuffix(str,"string")) //true
fmt.Printf("Does the string \"%s\" have contain %s ?\n",str,"example")
fmt.Printf("%t\n",strings.Contains(str,"string")) //true
}
Contains
和 ContainsAny
的區別
func stringContainsAndContainsAny() {
fmt.Println(strings.Contains("team","i")) //false
fmt.Println(strings.Contains("team"," a & o")) //false
fmt.Println(strings.Contains("team","")) //true
fmt.Println(strings.Contains("","")) //true
fmt.Println()
fmt.Println(strings.ContainsAny("team","i")) //false
fmt.Println(strings.ContainsAny("team"," a & o")) //true
fmt.Println(strings.ContainsAny("team","")) //false
fmt.Println(strings.ContainsAny("","")) //false
}
備註 :
Contains
底層實現是Index
ContainsAny
底層實現是 IndexAny
6.2 索引
Index
:指定字符/串的第一次出現的第一個字符的索引值,如果不存在相應字符串則返回-1
LastIndex
:指定字符串最後一次出現位置的第一個字符索引,-1表示不包含特定字符串
IndexRune
:如果是非 ASCII 編碼的字符,用此函數對字符進行定位。也是第一次出現第一個字符的索引值。不存在返回-1
func searchStrIndex() {
indexstr := "你好hello goland好"
fmt.Println(strings.Index(indexstr,"好")) // => 3,str[3],中文 "你" 佔 3個字節。
//和 Index 一個意思,都是檢查第一次出現
fmt.Println(strings.IndexRune(indexstr,/*[]rune(indexstr)[1]*/'好')) // =>3
// 和 Index 相反,檢查最後一次出現
lastIndexStr := "hello word"
fmt.Println(strings.LastIndex(lastIndexStr,"o")) // =>7
}
6.3 替換
func Replace(s, old, new string, n int) string
第一個參數 : 原字符串
第二個參數 : 源字符串中需要被替換的字符串
第三個參數:替換內容
第4個參數:n 表示匹配到第幾個 old,如果 n = -1,表示匹配所有
func stringReplace() {
str := "你好世界,這個世界真好。"
var newStr string = strings.Replace(str,"世界","地球",1)
fmt.Println(newStr) //你好地球,這個世界真好。
}
6.4 統計
Count
: 統計指定字符串出現的頻數
utf8.RuneCountInString
: 統計指定字符串的字符數量
func stringStatistics() {
str := "Golang is cool,right?"
var many string = "o"
fmt.Printf("指定字符 \"%s\" 在 字符串 \"%s\"中 出現的頻數爲:%d \n",many,str,strings.Count(str,many)) // 3
fmt.Printf("字符串 \"%s\"的字符數爲 %d \n",str,len([]rune(str))) //21
fmt.Printf("字符串 \"%s\"的字符數爲 %d \n",str,utf8.RuneCountInString(str)) //21
}
6.5 大小寫轉化
ToLower
: 將輸入字符串轉化成小寫輸出
ToUpper
:將輸入字符串轉化成大寫輸出
func stringToUpperOrToLower() {
str := "Hello Golang"
var lower string = strings.ToLower(str)
var upper string = strings.ToUpper(str)
fmt.Printf("\"%s\" lower is \"%s\" and upper is \"%s\"",str,lower,upper)
}
6.6 修剪
Trim
這個函數修剪的是字符串開頭或者結尾的字符,也就是不匹配中間的字符,而且 Trim
函數第二個參數雖然類型是 stirng
,但實際上替換時是把字符串轉換成 rune
後來操作的。
func stringTrim() {
str := "今天天氣真好"
fmt.Println(strings.Trim(str,"今")) //天天氣真好
fmt.Println(strings.Trim(str,"天")) //今天天氣真好
fmt.Println(strings.Trim(str,"今天")) //氣真好
}
第一句的確裁剪了"今"字,但是第二句的"天"並非字符串首尾,所以不會裁剪,重點在於第三句,可以看到後面的"天"全部被裁剪了,這是因爲Trim
函數把第二個參數轉化成了rune
類型,進行了逐一匹配–換句話說,實際上"今天"是被分爲兩個字符分別匹配裁剪的,所以只返回了"氣真好"。
6.7 分割
Splite
: 返回一個切片(slice)
func stringSplit() {
fmt.Println(strings.Split("a,b,c",",")) //[a b c]
fmt.Printf("%q\n",strings.Split("a,b,c",",")) //["a" "b" "c"]
fmt.Printf("%q\n",strings.Split("a b c"," ")) //["a" "b" "c"]
fmt.Printf("%q\n",strings.Split("a b c "," ")) //["a" "b" "c" ""]
}
6.8 ~ 6.9 字符串轉化成字符串切片(Fields)、字符串切片拼接成字符串(Join)
Fields
:以連續的空白字符爲分隔符,將 string 切分成多個子串,結果中不包含空白字符本身,空白字符有:\t, \n, \v, \f, \r, ' '
Join
:將元素類型爲 string
的slice
使用分隔符好拼接成一個字符串
func stringInsert() {
str := "Hello 世\n界!\tHe\vl\flo!"
var slice []string = strings.Fields(str)
fmt.Printf("%q\n",slice)
var result string = strings.Join(slice,"")
fmt.Println(result)
}
輸出:
["Hello" "世" "界!" "He" "l" "lo!"]
Hello世界!Hello!
7、字符串和其他類型轉換(strconv包)
一般來說,幾乎所有類型都可以被轉化成字符串,單反過來要把字符串轉換成其他類型就不一定能夠成功。前面有講到rune
和 string
類型的轉換。下面看下數字和字符串之間的轉換。
7.1 數字轉化成字符串
Itoa
整型、FormatFloat
浮點型、FormatBool
布爾型 轉化成字符串
//1.整型數字到字符串
convint := strconv.Itoa(10)
fmt.Println(convint,reflect.TypeOf(convint)) // 10 string
//2.浮點性數字到字符串
convfloat := strconv.FormatFloat(3.23,'g',3,64)
fmt.Println(convfloat,reflect.TypeOf(convfloat)) //3.23 string
//3.布爾型到字符串
convbool := strconv.FormatBool(true)
fmt.Println(convbool,reflect.TypeOf(convbool)) // true string
7.2 字符串轉化成數字
Atoi
整型、ParseFloat
浮點型、ParseBool
布爾型 字符串轉化成對應基本數據類型
//4.整型字符串到整型
if result,err := strconv.Atoi("10");err != nil{
fmt.Println(err)
}else {
fmt.Println(result,reflect.TypeOf(result)) //10 int
}
//5.布爾類型字符串到布爾類型
if result,err := strconv.ParseBool("1");err != nil{
fmt.Println(err)
}else {
fmt.Println(result,reflect.TypeOf(result)) //true bool
}
//6.浮點類型字符串到浮點類型
if result,err := strconv.ParseFloat("3.24",64);err != nil{
fmt.Println(err)
}else {
fmt.Println(result,reflect.TypeOf(result)) //3.24 float64
}
備註 : 上面的reflect.TypeOf
是個反射api。返回對應數據類型。
7.3 自定義類型轉化成字符串
實現 Stringer
接口,實現 String() string
方法 即可.
type Student struct {
Name string
}
func (s Student) String() string {
return "name is " + s.Name
}
func cusTypeConvString() {
jack := new(Student)
jack.Name = "jack"
fmt.Println(jack.String()) // name is jack
}
三、基本數據類型擴展
3.1 強制類型轉換
類型轉換用於將一種數據類型的變量轉化成良一中類型的變量。GO 語言的類型轉化基本格式: type_name(expression)
在做強制類型轉換時,需要注意數據長度被截短而發生的數據精度丟失(比如浮點轉化成整數) 和 值溢出 (值超過轉換的目標類型的值範圍時) 問題。
func typeExpression() {
sum := 11
count := 3
mean := float32(sum) / float32(count)
mean1 := sum / count
fmt.Printf("mean = %.2f \n",mean) //mean = 3.67
fmt.Printf("mean1 = %d \n",mean1) //mean1 = 3
}
3.2 自定義類型
在 GO 語言中,自定義類型實際上與結構體有關。這裏暫不介紹關於結構體過多內容的說明。上面已經有一個 Student
結構體。
type name struct { //TO DO }
3.3 類型別名
type
給已知的數據類型取另外一個名字。
func typeAlternativeName() {
type 字符串 string
var b 字符串
b = "這是中文。"
fmt.Println(b) // 這是中文。
a := "這也是一箇中文"
//fmt.Println(a+b)
fmt.Println(string(b)+a) //這是中文。這也是一箇中文
}
注意 : 上面例子中,注意註釋的那一句,在編譯器中這種寫法是錯誤的,因爲類型別名與原有類型是兩種類型,不能直接操作,需要進行類型轉換。
3.4 指針
3.4.1 聲明
指針變量都是指向一個內存位置,每個內存位置都有其定義的地址,可以使用 &
運算符來訪問它,這個運算符表示內存中的地址。
指針是一個變量,其值是另外一個變量的地址,即存儲器位置的直接地址。類似變量和常量一樣,必須先聲明一個指針,然後才能使用它來存儲任何變量地址。指針的變量聲明一般格式爲: var name *type
所有指針的值的實際數據類型都是相同的,他表示內存地址的長十六進制數。
使用指針基本上是三個步驟:
1. 定義一個指針變量
2. 將一個變量的地址賦值給一個指針
3. 最後訪問指針變量中可用地址的值
GO 語言中通過使用一元運算符*
來取得指向指針存儲的內存地址所對應的值(指針的格式化標識符爲 %p)。GO語言指針不支持指針運算,不支持 -> 運算符。
func pointer() {
a := 20
pointer := &a
fmt.Printf("a 的地址: %x \n",&a) //a 的地址: c0000b4008
fmt.Printf("pointer 的地址: %x \n",pointer) //pointer 的地址: c0000b4008
fmt.Printf("pointer 的值: %d\n",*pointer) //pointer 的值: 20
}
3.4.2 nil 指針
GO 語言編譯器爲指針變量分配一個 nil
值,以防指針沒有確切的地址分配,這是在變量聲明的時候完成的。指定爲 nil
值 的指針稱爲 nil 指針,nil 指針 是在幾個標準庫中定義的值爲 0 的常量。在大多數操作系統中,程序不允許訪問地址 0 處的內存,因爲改內存是由操作系統保留的。然而,存儲器地址 0 具有特殊意義,他表示指針不打算指向可訪問的存儲器的位置。如果指針包含 nil 值,則假設他不指向任何對象。要檢查是否爲 nil 指針,可以使用 if 語句
if(ptr != nil)
if(ptr == nil)
對於一個空指針的反向引用是不合法的,並且會使程序 crash
var ptr *int = nil
*ptr = 10
3.4.3 指針的指針
直接上兩個例子說明下就好理解
func pointerOfThePointer() {
var a *int
ap := &a
if a == nil {
fmt.Println("a 爲 nil 指針")
}
fmt.Printf("a --> nil : %x\n",a) //0
fmt.Printf("ap --> a : %x \n",ap)
fmt.Printf("ap -> a --> nil(指針 ap 指向的指針 a 的內存地址):%x \n",*ap) //0
fmt.Printf("&ap --> ap(表示 ap 在內存中的地址):%x\n",&ap)
}
func doublePointer() {
a := 10
ap := &a
app := &ap
fmt.Printf("a = %d \n",a) //10
fmt.Printf("ap = %x \n",ap) //10在存儲器位置上直接地址
fmt.Printf("*ap = %d \n",*ap) // 10
fmt.Printf("app = %x \n",app) // 變量 ap 在存儲器位置上的直接地址
fmt.Printf("*app = %x \n",*app) // 10 在存儲器上的直接地址
fmt.Printf("**ap = %d \n",**app) //10
}
輸出如下:
a = 10
ap = c000016050
*ap = 10
app = c00000e028
*app = c000016050
**ap = 10
3.4.5 指針數組
雖然我們還未介紹到 GO 數組,但是並不妨礙理解指針數組的概念。
func pointerArrays() {
a := [3]int{10,20,30}
var ptr [3]*int
for index := 0; index < 3;index++ {
ptr[index] = &a[index]
fmt.Printf("a[%d]的地址:%x\n",index,ptr[index])
}
for index := 0 ;index < 3;index++ {
fmt.Printf("a[%d]的值爲:%d\n",index,*ptr[index])
}
}
輸出結果:
a[0]的地址:c00001c0e0
a[1]的地址:c00001c0e8
a[2]的地址:c00001c0f0
a[0]的值爲:10
a[1]的值爲:20
a[2]的值爲:30
3.4.5傳遞給函數
GO 語言允許傳遞指針到函數中,只需要將函數參數聲明爲指針類型。
func swap(a *int,b *int) {
temp := *a
*a = *b
*b = temp
}
func paramsPointer() {
a := 100
b := 200
swap(&a,&b)
fmt.Printf("a = %d,b = %d \n",a,b) //a = 200,b = 100
}
四、流程控制語句
1、條件語句
if、if-else、if-else if- else
跟大多數語言一樣,我們要說的就是 GO 語言特有的點: if 語句可以有一個子語句,子語句只能有一個表達式。if 後面的括號可以省略。
func conditionStatement() {
if a := 10; a < 20 {
fmt.Println("a 小於 20")
}else{
fmt.Printf("%d 大於或等於 20 \n",a)
}
if a,b := 10,20; a< b {
fmt.Println("a < b")
}else {
fmt.Println("a >= b")
}
/* 編譯錯誤。初始化子語句只能有一個表達式
if a := 10; b := 10; a < b {
fmt.Println("a < b")
}else{
fmt.Println("a >= b")
}*/
}
2、選擇語句
switch
跟大多數語言一樣,這裏還是講特殊點: break可省略,fallthrough 關鍵字可以把當前case控制權移交給下一個case語句判斷。switch同樣和if一樣擁有初始化子語句。
表達式 switch : switch 後面可以沒有表達式,case 後可以跟表達式。
var x interface{}
func switchStatement() {
//1.表達式switch: switch後面沒有語句;case可以多個語句,語句之間用","分割,跟 fallthrough 意思一致
marks := 95
switch {
case marks >= 90:
fmt.Println("優秀")
case marks >= 80,marks >= 70:
fmt.Println("良好")
default:
fmt.Println("一般")
}
//2.類型switch: 跟主流編程語言一致。但是 break 可以省略不寫。
x = 10
switch dataType := x.(type){
case int:
fmt.Printf("int 類型 %T \n",dataType)
case float64:
fmt.Printf("flaot64 類型 %T \n",dataType)
case bool:
fmt.Printf("bool 類型 %T \n",dataType)
case string:
fmt.Printf("string 類型 %T \n",dataType)
case nil:
fmt.Printf("nil 類型 %T \n",dataType)
default:
fmt.Println("未知類型")
}
}
3、循環語句
for、range
for 語句跟主流編程語言保持一致,只不過 for 後面的語句括號省略
這裏主要是 range: 這貨非常強大,其作用類似於迭代器,用於輪詢數組或者切片的每一個元素,也可以用於輪詢字符串中的每一個字符,以及字典中的每一個鍵值對,甚至還可以持續讀取一個通道類型值中的元素
func rangeStatement() {
//1. 字符串
fmt.Println("range 字符串")
str := "I Love 中國"
for index,char := range str{
fmt.Printf("str[%d] = %c\n",index,char)
}
fmt.Println()
fmt.Println("range 數組或切片")
//2.數組或切片
arrays := [5]int{1,2,3,4,5}
for index,value := range arrays{
fmt.Printf("arrays[%d] = %d\n",index,value)
}
fmt.Println()
fmt.Println("range 字典")
//3.字典(映射)
dictionary := map[string]string{"name":"jack","country":"china"}
for key,value := range dictionary{
fmt.Printf("dictionray[%s] = %s \n",key,value)
}
}
輸出結果
range 字符串
str[0] = I
str[1] =
str[2] = L
str[3] = o
str[4] = v
str[5] = e
str[6] =
str[7] = 中
str[10] = 國
range 數組或切片
arrays[0] = 1
arrays[1] = 2
arrays[2] = 3
arrays[3] = 4
arrays[4] = 5
range 字典
dictionray[name] = jack
dictionray[country] = china
備註: GO 沒有 三目運算符,沒有 do-while 。
4、延遲語句
defer: 用於延遲調用指定函數,defer
關鍵字只能出現在函數內部
兩大特點
4.1 只有當 defer
語句全部執行,defer
所在函數纔算真正結束
4.2 當函數中 有 defer
語句時,需要等待所有 defer
語句執行完畢,纔會執行 return
語句
defer 一般用於回收資源,清理收尾等工作
defer 其實是一個棧,遵循先入後出(後進先出),簡單來說,當一個函數內部出現多個 defer
語句時,最後面的 defer
語句最先執行
func deferStatement() {
for index := 0;index < 5;index++ {
defer printStatement(index)
}
}
func printStatement(i int) {
fmt.Println(i)
}
輸出結果:
4
3
2
1
0
5、標籤語句
GO 語言中,可以給 for、switch 等流程控制代碼打上一個標籤,配置標籤標識符可以方便跳轉到某一個地方繼續執行,有助於提高編程效率。標籤名字區分大小寫,爲了提高閱讀性,建議標籤使用大寫字母和數字組合。標籤可以標記任何語句,未使用的標籤會引發錯誤。
break
(跳出for循環)、continue
(僅能用於for循環)、goto
(只能在同一個函數中跳轉)
下面列舉三個方法簡單解釋下三個標籤語句
5.1 break
func breakTagStatement() {
LOOP1:
for {
x := 1
switch {
case x > 0:
fmt.Println("A")
break LOOP1
case x == 1:
fmt.Println("B")
default:
fmt.Println("C")
}
}
}
輸出結果:
A
5.2 contiune
func contiuneTagStatement() {
LOOP1:
for index := 0; index <= 5;index++ {
switch {
case index > 0:
fmt.Println("A")
continue LOOP1
case index == 1:
fmt.Println("B")
default:
fmt.Println("C")
}
fmt.Printf("index = %d \n",index)
}
}
輸出結果:
C
index = 0
A
A
A
A
A
5.3 goto
func gotoTagStatement() {
var i int
for {
fmt.Println(i)
i++
if i > 2 {
goto BREAK
}
}
BREAK:
fmt.Println("break")
}
輸出結果:
0
1
2
break