GO語言的進階之路-Golang高級數據結構定義
作者:尹正傑
版權聲明:原創作品,謝絕轉載!否則將追究法律責任。
我們之前學習過Golang的基本數據類型,字符串和byte,以及rune也有所了解,但是說起高級點的數據類型,可能我們還是不太清楚,那么今天就跟着我腳步一起學習一下這些高級數據類型數據吧。相信有部分人可能學習過Python,那么我這篇博客基本上不用看了,因為對你來說會覺得so easy。因為太多的相似之處了,只是寫法不同。本章主要介紹數組(array),切片(scice),字典(map),結構體(struct)等等。
一.數組
有可能你學習過shell或是python,其實從輸出的角度上來說,兩者區別不大,但是Golang的數組那是別有一番風味啊,首先在學習數組之前,你要了解數組的兩個參數重要參數,一個是數組的長度,一個是數組的容量。只要你明白了golang語言中數組這兩個性質,那么在定義的數組時你就會跳過一些坑。比如說你想把容量為3的數組賦值給容量為10的數組,是不可行的,因為容量為三的數組,其長度是3,容量為10的數組,其長度是10,(如果你想把一個數組賦值給另一個數組,首先要讓數組的長度相等,其次兩邊的類型要一致)數組的長度是類型的一部分,所以容量為3的數組是無法賦值給容量為10的數組,就是因為其長度不同,當然你也可以說是類型不同導致。
最后我要強調的是在Golang定義一個數組后,這個數組的容量是沒法改變的。
1.定義一個數組並循環看其初值;
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 func main() { 13 var num [3]int //表示定義一個容量為3的數組,如果沒有賦初值的話默認就是"0". 14 fmt.Printf("該數組的第一個數字是:%d\n",num[0]) 15 fmt.Printf("該數組的最后一個數字是:%d\n",num[len(num)-1]) 16 for i,v := range num { 17 fmt.Printf("數組的下標是:%d,數組的下標對應的初值是: %d\n",i,v) 18 } 19 for _,v := range num { 20 fmt.Printf("數組的初值是:%d\n",v) 21 } 22 } 23 24 25 26 #以上代碼執行結果如下: 27 該數組的第一個數字是:0 28 該數組的最后一個數字是:0 29 數組的下標是:0,數組的下標對應的初值是: 0 30 數組的下標是:1,數組的下標對應的初值是: 0 31 數組的下標是:2,數組的下標對應的初值是: 0 32 數組的初值是:0 33 數組的初值是:0 34 數組的初值是:0
2.數組的花式定義和賦值
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 func main() { 13 var num [5]int //先定義一個容量為5的數組num。 14 num = [5]int{1,3,5,7,9} //給這num數組賦值 15 fmt.Printf("num數組的元素是:%d\n\n",num) 16 17 var a [3]int = [3]int{1,2,3} //將一個容量為三長度也為3的數組賦值給另一個容量為三的數組. 18 fmt.Printf("a數組的元素是:%d\n",a) 19 fmt.Printf("a[1]所對應的值是:%d\n",a[1]) //表示取a數組下標對應是1的value. 20 fmt.Printf("a數組的容量是:%d,該容量的長度是:%d,還可以存取%d個成員\n\n",cap(a),len(a),(cap(a)-len(a))) //cap函數用於計算數組的容量,len函數用於計算數組的長度. 21 22 23 b := [...]int{1,2,3,4} //這種定義方式其實就是不寫具體的容量參數,那么容量的值就和長度是相等的。 24 fmt.Printf("b數組的元素是:%d\n",b) 25 fmt.Printf("該數組的容量是:%d,該容量的長度是:%d,還可以存取%d個成員\n\n",cap(b),len(b),(cap(b)-len(b))) 26 27 c := [...]int{4:20,7:-1} //定義下標為4的值為20,下標為7的值為-1。給指定數組下標賦初值,數組的長度為最大下標的加1,如果一個數組沒有寫明容量的話,會根據其下標最大的元素來定義其容量和長度。 28 fmt.Printf("c數組的元素是:%d\n",c) 29 fmt.Printf("該數組的容量是:%d,該容量的長度是:%d,還可以存取%d個成員\n\n",cap(c),len(c),(cap(c)-len(c))) 30 } 31 32 33 #以上代碼執行結果如下: 34 num數組的元素是:[1 3 5 7 9] 35 36 a數組的元素是:[1 2 3] 37 a[1]所對應的值是:2 38 a數組的容量是:3,該容量的長度是:3,還可以存取0個成員 39 40 b數組的元素是:[1 2 3 4] 41 該數組的容量是:4,該容量的長度是:4,還可以存取0個成員 42 43 c數組的元素是:[0 0 0 0 20 0 0 -1] 44 該數組的容量是:8,該容量的長度是:8,還可以存取0個成員
3.數組的內存大小以及內存地址的查看;
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import ( 11 "fmt" 12 "unsafe" 13 ) 14 15 func main() { 16 array1 := [4]int{1,2,3} //定義array2這個數組,開辟了一款內存。 17 fmt.Printf("array1的元素是:%d\n",array1) 18 fmt.Printf("array1數組所占內存是:%d bytes\n",unsafe.Sizeof(array1)) //一個數組占有8個字節,容量為4的數組其內存是就是32字節 19 var array2 [4]int //定義一個 20 array2 = array1 21 fmt.Printf("array1的地址是:%d\narray2的地址是:%d\n",&array1[0],&array2[0]) 22 23 var n1,n2 int 24 n1 = 100 25 n2 = n1 //定義的n1和n2都是單獨的容器,他們的內存地址是不一樣的喲! 26 fmt.Printf("n1的內存地址是:%d\nn2的內存地址是:%d\n",&n1,&n2) //打印n1和n2的內存地址 27 28 fmt.Println(n2) 29 fmt.Println(n1 == n2) //這是判斷兩個變量對應的值是否相同!如果是就為真(true),是否不是九尾假(false) 30 } 31 32 33 #以上代碼輸出結果如下: 34 array1的元素是:[1 2 3 0] 35 array1數組所占內存是:32 bytes 36 array1的地址是:825741296640 37 array2的地址是:825741296768 38 n1的內存地址是:825741271528 39 n2的內存地址是:825741271536 40 100 41 false
4.字節數組
其實我們在之前就用過關於數組的東西,比如字節數組“[]byte”,其實它就是一個數組
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import ( 11 "crypto/md5" 12 "fmt" 13 ) 14 15 func main() { 16 data := []byte("yinzhengjie") //定義一個byte數組. 17 md5sum := md5.Sum(data) //調用Golang的md5算法將字節數組換算成一個唯一的md5值用於文件校驗。 18 fmt.Printf("%x\n",md5sum) //打印其的md5值 19 fmt.Printf("%x\n",255) //一個十六進制的數字的取之范圍是"00-FF",所以2個16進制表示一個字符。md5就是由十六進制的數字組成的。 20 } 21 22 23 24 #以上代碼執行結果如下: 25 a1424987f80af77e96f540ccda1e68e5 26 ff
5.數組的應用
1 [root@yinzhengjie ~]# more md5.go 2 /* 3 #!/usr/bin/env gorun 4 @author :yinzhengjie 5 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 6 EMAIL:y1053419035@qq.com 7 */ 8 9 10 11 package main 12 13 import ( 14 "io/ioutil" 15 "fmt" 16 "os" 17 "crypto/md5" 18 ) 19 20 func main() { 21 var s string 22 for i := 1; i < len(os.Args); i++ { 23 s = os.Args[i] 24 printFile(s) 25 } 26 } 27 28 func printFile(name string) { 29 buf, err := ioutil.ReadFile(name) //讀取文件的內容傳給buf,當然它接受到的數據時仍然是字節,即[]uint8. 30 if err != nil { 31 fmt.Println(err) 32 return 33 } 34 md5sum := md5.Sum(buf) //把字節buf的值用md5算法算出其md5值。 35 fmt.Printf("經計算,文件'%v'的MD5值是:%x\n",os.Args[1],md5sum) 36 } 37 [root@yinzhengjie ~]# 38 [root@yinzhengjie ~]# go run md5.go startup.cfg 39 經計算,文件'startup.cfg'的MD5值是:c577d25cb647991e2b44e12c67649fcc 40 [root@yinzhengjie ~]#
二.切片
Golang的切片長得和數組很像,我們可以對一個數組做切片。要注意的是:當我們對一個數組做切片的時候,如果我們修改了切片下標所對應的值,那么被切片的數組的值也會跟着改變,因為他們都指向了同一塊內存地址。
1.對數組做切片操作;
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import ( 11 "fmt" 12 ) 13 14 func main() { 15 primes := [8]int{2,3,5,7,9,11,13,15,} //定義一個數組 16 fmt.Printf("`primes`數組的值:%d\n",primes) 17 var sum []int = primes[1:4] //定義一個切片 18 fmt.Printf("`sum`切片的值:%d\n",sum) 19 fmt.Printf("`sum[0]`所對應的內存地址是:%x\n",&sum[0]) 20 fmt.Printf("`primes[1]`所對應的內存地址是:%x\n",&primes[1]) 21 var s1 []int 22 s1 = sum 23 fmt.Printf("`s1`切片對應的值為:%d\n",s1) 24 fmt.Printf("s1[0] == sum[0]為:%v\n",&s1[0] == &sum[0]) 25 } 26 27 28 29 #以上代碼輸出結果如下: 30 `primes`數組的值:[2 3 5 7 9 11 13 15] 31 `sum`切片的值:[3 5 7] 32 `sum[0]`所對應的內存地址是:c042046088 33 `primes[1]`所對應的內存地址是:c042046088 34 `s1`切片對應的值為:[3 5 7] 35 s1[0] == sum[0]為:true
2.切片的原理;
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 func main() { 13 names := [4]string{ //定義了一個字符串數組 14 "尹正傑", 15 "百度", 16 "谷歌", 17 "翻牆", 18 } 19 fmt.Println(names) 20 21 a := names[0:2] 22 b := names[1:3] 23 fmt.Println(a,b) 24 25 b[0] = "xxx" //修改b的元素,會將names的對應的地址做相應的修改。 26 fmt.Println(a,b) 27 fmt.Println(names) 28 } 29 30 31 #以上代碼輸出結果如下: 32 [尹正傑 百度 谷歌 翻牆] 33 [尹正傑 百度] [百度 谷歌] 34 [尹正傑 xxx] [xxx 谷歌] 35 [尹正傑 xxx 谷歌 翻牆]
3.切片的字面量
嗨,可能你有可能聽不懂“字面量”,好吧,其實它就是對切片做初始化賦值,僅此而已!
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 func main() { 13 num := []int{100,200,300,400,500} //切片的初始化方法,專業術語叫做切片字面量。 14 fmt.Println(num) 15 16 r := []bool{true,false,true,true} 17 fmt.Println(r) 18 } 19 20 21 22 #以上代碼輸出結果如下: 23 [100 200 300 400 500] 24 [true false true true]
4.切片的花式玩法;
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 func main() { 13 num := []int{2,3,5,7,9,11,13} //定義一個切片 14 fmt.Println(num) 15 num = num[1:4] //第一次對切片做切片操作,取值結果為:[3 5 7] 16 fmt.Println(num) 17 num = num[:2] //第二次切了又切,取值結果為[3 5] 18 fmt.Println(num) 19 num = num[1:] //第三次是在第二次切片操作后又一次切片操作,取值結果為[5] 20 fmt.Println(num) 21 } 22 23 24 25 #以上操作結果如下: 26 [2 3 5 7 9 11 13] 27 [3 5 7] 28 [3 5] 29 [5]
5.空切片;
切片包括2個屬性,即長度和容量.因此我們不能看兩個切片的長度為0就說這2個變量是相等的。
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 func main() { 13 num := []int{1,2,3} //定義一個切片 14 var s []int //定義一個空切片 15 fmt.Printf("`s`的值為:%v;長度為:%d;容量為%d\n",s,len(s),cap(s)) 16 if s == nil { 17 fmt.Printf("s為空\n") 18 } 19 s1 := num[:0] //將切片num的值賦值給s1. 20 fmt.Printf("`s1`的值為:%v;長度為:%d;容量為%d\n",s1,len(s1),cap(s1)) 21 fmt.Println(s1 == nil) //雖然s1的值為[],長度為0,但是容量為3,因此該切片不是空切片!切片包括2個屬性,即長度和容量。 22 } 23 24 25 26 #以上代碼輸出結果如下: 27 `s`的值為:[];長度為:0;容量為0 28 s為空 29 `s1`的值為:[];長度為:0;容量為3 30 false
6.切片的追加操作
切片和數組不同,數組沒有網容器里添加元素的方法,但是切片可以的。也就是說,只要切片的容量固定,我們可以根據容量大小往里添加數據相應的元素。
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 func main() { 13 var s []int //定義一個空切片s. 14 s = []int{1,2,3} //給這個空切片s賦值. 15 slice_attribute(s) 16 s = append(s,0) //往切片s追加一個"0"元素。 17 slice_attribute(s) 18 s = append(s,2,3,4) //繼續往切片s追加“2,3,4”等元素。 19 slice_attribute(s) 20 21 } 22 23 func slice_attribute(s []int) { 24 fmt.Printf("len=%d cap=%d %v\n",len(s),cap(s),s) //打印切片的長度,容量以及對應的value. 25 } 26 27 28 29 30 #以上代碼輸出結果如下: 31 len=3 cap=3 [1 2 3] 32 len=4 cap=6 [1 2 3 0] 33 len=7 cap=12 [1 2 3 0 2 3 4]
7.用make函數定義一個切片;
make函數不僅僅可以定義一個切片,還可以定義一個map(你可以理解成字典)。
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 func main() { 13 slice1 := make([]int,5) //表示定義一個長度為5的切片 14 my_slice("slice1",slice1) 15 slice2 := make([]int,0,5) //表示定義一個長度為0,容量為5的切片 16 my_slice("slice2",slice2) 17 slice3 := slice2[:2] 18 my_slice("slice3",slice3) 19 slice4 := slice3[2:5] 20 my_slice("slice4",slice4) 21 } 22 23 func my_slice(s string ,x []int) { 24 fmt.Printf("`%s`切片長度為:%d 切片容量為:%d 切片中的元素是:%v\n",s,len(x),cap(x),x) 25 } 26 27 28 #以上代碼執行結果如下: 29 `slice1`切片長度為:5 切片容量為:5 切片中的元素是:[0 0 0 0 0] 30 `slice2`切片長度為:0 切片容量為:5 切片中的元素是:[] 31 `slice3`切片長度為:2 切片容量為:5 切片中的元素是:[0 0] 32 `slice4`切片長度為:3 切片容量為:3 切片中的元素是:[0 0 0]
8.小試牛刀;
好了,關於切片的基本上這些就夠用了,我們可以來小試牛刀一下啦~看看你掌握了多少;
A.反轉切片的值;
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 func main() { 13 var num []int 14 num = []int{1,3,5,7} 15 fmt.Printf("切片反轉之前的順序是:%d\n",num) 16 my_rerversal(num) 17 fmt.Printf("切片反轉之后的順序是:%d\n",num) 18 } 19 20 func my_rerversal(s []int) { //該函數用於反轉 21 for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 22 s[i], s[j] = s[j], s[i] 23 } 24 } 25 26 27 #以上代碼執行結果如下: 28 切片反轉之前的順序是:[1 3 5 7] 29 切片反轉之后的順序是:[7 5 3 1]
B.隨機反轉切片的值;
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 9 package main 10 11 import ( 12 "bufio" 13 "os" 14 "fmt" 15 16 "strconv" 17 ) 18 19 var ( 20 s string 21 line string 22 ) 23 func main() { 24 f := bufio.NewReader(os.Stdin) 25 num := []int{100,200,300,400,500,600,700,800} 26 fmt.Printf("現有一些數字:·\033[32;1m%v\033[0m·\n",num) 27 for { 28 fmt.Print("請您想要反轉下標的起始的位置>") 29 line,_ = f.ReadString('\n') 30 if len(line) == 1 { 31 continue //過濾掉空格; 32 } 33 fmt.Sscan(line,&s) 34 if s == "stop" { 35 break //定義停止程序的鍵值; 36 } 37 index,err := strconv.Atoi(s) 38 if err != nil { 39 fmt.Println("對不起,您必須輸入一個數字") 40 } 41 num1 := num[:index] 42 num2 := num[index:] 43 i := 0 44 for { 45 46 num2=append(num2, num1[i]) 47 i = i + 1 48 if i >= len(num1) { 49 break 50 } 51 } 52 fmt.Printf("反轉后的內容是·\033[31;1m%v\033[0m·\n",num2) 53 } 54 } 55 56 57 58 #以上代碼輸出結果如下: 59 現有一些數字:·[100 200 300 400 500 600 700 800]· 60 請您想要反轉下標的起始的位置>1 61 反轉后的內容是·[200 300 400 500 600 700 800 100]· 62 請您想要反轉下標的起始的位置>3 63 反轉后的內容是·[400 500 600 700 800 100 200 300]· 64 請您想要反轉下標的起始的位置>5 65 反轉后的內容是·[600 700 800 100 200 300 400 500]· 66 請您想要反轉下標的起始的位置>7 67 反轉后的內容是·[800 100 200 300 400 500 600 700]· 68 請您想要反轉下標的起始的位置> 69 請您想要反轉下標的起始的位置> 70 請您想要反轉下標的起始的位置>2 71 反轉后的內容是·[300 400 500 600 700 800 100 200]· 72 請您想要反轉下標的起始的位置>4 73 反轉后的內容是·[500 600 700 800 100 200 300 400]· 74 請您想要反轉下標的起始的位置>6 75 反轉后的內容是·[700 800 100 200 300 400 500 600]· 76 請您想要反轉下標的起始的位置>8 77 反轉后的內容是·[100 200 300 400 500 600 700 800]· 78 請您想要反轉下標的起始的位置> 79 請您想要反轉下標的起始的位置>
C.單詞反轉;
想要實現單詞反轉,有個package你必須虛得了解,那就是strings包。只要你知道這個packge基本上就能搞定這個事情啦!

hello world Golang! 尹正傑
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import ( 11 "io/ioutil" 12 "log" 13 "fmt" 14 "strings" 15 ) 16 17 func main() { 18 buf, err := ioutil.ReadFile("D:\\Golang環境\\Golang Program\\Golang lesson\\Day4\\你好.txt") 19 if err != nil { 20 log.Fatal(err) 21 } 22 fmt.Println(string(buf)) 23 str := strings.Fields(string(buf)) 24 my_rerversal(str) 25 26 } 27 28 29 func my_rerversal(s []string) { 30 for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 31 s[i], s[j] = s[j], s[i] 32 } 33 str1 := strings.Join(s," ") //把切片轉換成字符串。 34 str1 = str1 35 fmt.Println(str1) 36 } 37 38 39 40 #以上代碼執行結果如下: 41 hello world Golang! 尹正傑 42 尹正傑 Golang! world hello
三.map(你可以理解為字典。)
可能大家剛剛接觸Golang的小伙伴都會跟我一樣,這個map是干嘛的,是函數嗎?學過python的小伙伴可能會想到map這個函數。其實它就是Golang中的字典。下面跟我一起看看它的特性吧。
A.hash方式的;
B.無序的;
C.0(1)的訪問時間;
擴充: (n):存n個元素就需要轉n圈目的數據;
0(n^2):存n個元素就需要n的平方圈目的數據;
0(2^n):存n個元素就需要2的n次方圈才能訪問到目的數據;
0(1):不管存多少個元素,只轉一圈就能找到(其實就是類似與python中的字典,有專用的key綁定一個value值。);
0(logn):排序查找,比入10000個元素中我們想要查數字10,那么可能只要查10次就查出來來;
1.定義一個map;
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 func main() { 13 info := make(map[string]int) //定義一個空字典,其key的數據類型是字符串,其value對應的數據是數字 14 info["age"] = 25 //往空字典中傳值 15 info["size"] = 18 16 fmt.Println(info["age"]) //查看key所對應的value. 17 info["age"] = info["size"] + 100 //其實是數字相加運算 18 fmt.Println(info["age"]) 19 info2 := map[string]string{ 20 "name" : "尹正傑", 21 "age" : "25", 22 } 23 24 c,ok := info2["c"] //判斷key是否在info2中 25 if ok { 26 fmt.Println(c) 27 }else { 28 fmt.Println("真不好意思,你所說的key在我的字典里壓根不存在!") 29 } 30 fmt.Println(info2) 31 32 if hight,ok := info["d"];ok { //判斷key是否在info中 33 fmt.Println(hight) 34 }else { 35 info["hight"] = 111 36 } 37 fmt.Println(info) 38 } 39 40 41 42 #以上代碼執行結果如下: 43 25 44 118 45 真不好意思,你所說的key在我的字典里壓根不存在! 46 map[name:尹正傑 age:25] 47 map[age:118 size:18 hight:111]
2.刪除一個map;
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 func main() { 13 dict:= map[string]int{ 14 "a" :1, 15 } 16 fmt.Println(dict) 17 delete(dict,"a") //刪除map中key所對應的value. 18 fmt.Println(dict) 19 20 var dict_1 map[string]int 21 fmt.Println(dict_1 == nil) //定義了一個空字典,內容為空 22 fmt.Println(dict_1) 23 dict_1 = make(map[string]int) //如果m1等於空(nil),需要重新m1才能用m1,不能直接對其賦值 24 dict_1["c"]=100 25 fmt.Println(dict_1) 26 } 27 28 29 30 #以上代碼執行結果如下: 31 map[a:1] 32 map[] 33 true 34 map[] 35 map[c:100]
3.遍歷map;
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 func main() { 13 ages := map[string]string{ 14 "姓名":"尹正傑", 15 "年齡":"25", 16 } 17 for i,j := range ages { //遍歷key和value。 18 fmt.Println("key=",i,"value=",j) 19 } 20 21 for i := range ages { //只遍歷key. 22 fmt.Println(i) 23 } 24 } 25 26 27 #以上代碼執行結果如下: 28 key= 姓名 value= 尹正傑 29 key= 年齡 value= 25 30 姓名 31 年齡
4.小試牛刀;
A.定義一個集合的思想;
學過Python的同學,可能聽說過集合,但是我要告訴你一個好消息和一個壞消息,你想先聽哪一個?
壞消息就是Golang沒有集合這個概念;好消息是我們可以用Golang的make函數來實現集合的思想,下面跟我一起看個例子吧!
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 func main() { 13 set := make(map[string]bool) //定義一個map 14 set["a"] = true //給已經存在的變量定義為真 15 if set["a"] { 16 fmt.Println("已經存在該變量") 17 18 } else { 19 fmt.Println("該變量不存在!") 20 } 21 22 if set["b"] { 23 fmt.Println("已經存在該變量") 24 25 } else { 26 fmt.Println("該變量不存在!") 27 28 } 29 } 30 31 32 33 #以上代碼執行結果如下: 34 已經存在該變量 35 該變量不存在!
B.統計單詞出現的頻率;

Scanner provides a convenient interface for reading data such as a file of newline-delimited lines of text Successive
calls to the Scan method will step through the tokens of a file skipping the bytes between the tokens The specification
of a token is defined by a split function of type SplitFunc the default split function breaks the input into lines with
line termination stripped Split functions are defined in this package for scanning a file into lines bytes UTF-8-encoded
runes and space-delimited words The client may instead provide a custom split function
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import ( 11 "fmt" 12 "io/ioutil" 13 "log" 14 "strings" 15 ) 16 17 func main() { 18 buf,err := ioutil.ReadFile("D:\\Golang環境\\Golang Program\\Golang lesson\\Day4\\單詞.txt") 19 if err != nil { 20 log.Fatal(err) 21 } 22 statistic_times := make(map[string]int) 23 words_length := strings.Fields(string(buf)) 24 25 for counts,word := range words_length { 26 word,ok :=statistic_times[word] //判斷key是否存在,這個word是字符串,這個counts是統計的word的次數。 27 if ok{ 28 word = word //我這里是重新賦值,因為上面定義了,下面必須用這個變量,不然就報錯,有大神可以幫忙優化一下這里。 29 statistic_times[words_length[counts]] = statistic_times[words_length[counts]] + 1 30 }else { 31 statistic_times[words_length[counts]] = 1 32 } 33 } 34 for word,counts := range statistic_times { 35 fmt.Println(word,counts) 36 } 37 } 38 39 40 41 #以上代碼輸出結果如下: 42 43 lines 3 44 method 1 45 functions 1 46 in 1 47 words 1 48 may 1 49 newline-delimited 1 50 the 6 51 package 1 52 provides 1 53 will 1 54 step 1 55 through 1 56 skipping 1 57 stripped 1 58 Scanner 1 59 as 1 60 tokens 2 61 specification 1 62 space-delimited 1 63 client 1 64 function 3 65 instead 1 66 for 2 67 of 5 68 by 1 69 termination 1 70 interface 1 71 between 1 72 breaks 1 73 with 1 74 line 1 75 runes 1 76 Successive 1 77 SplitFunc 1 78 into 2 79 Split 1 80 reading 1 81 defined 2 82 type 1 83 default 1 84 input 1 85 custom 1 86 text 1 87 to 1 88 Scan 1 89 bytes 2 90 is 1 91 such 1 92 token 1 93 are 1 94 file 3 95 The 2 96 split 3 97 UTF-8-encoded 1 98 and 1 99 provide 1 100 a 7 101 convenient 1 102 data 1 103 calls 1 104 this 1 105 scanning 1
四.struct(結構體);
說道結構體,大家可能會懵逼,不知道是個啥東西,其實我覺得Golang起的結構體這個名字還是蠻接地氣的,不是嗎?從字面意思就可以理解為一個數據的結構體系。基本上一聽這個名字就大致知道是干嘛的,它就好似一個模板,讓我們看清楚了她的各個主要分支結構。其實,在Python中,我們叫它實例,說白了,當初學習Python實例的和實例化的時候讓我很懵逼,隨着時間的推移我才明白什么是實例,什么是實例化。相信學習過Python的同學應該都知道class。其實結構體,我們就可以理解成Python中的定義一個實例,而用這個結構體的時候,我們就可以理解是在實例化這個對象。
1.定義一個結構體以及實例化結構體的兩種方式;
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 type Student struct { //定義一個結構體,類似與python定義的一個實例 13 ID int 14 Name string 15 } 16 17 func main() { 18 var s Student //引用結構體,方式一。【可以理解為實例化】 19 s.ID = 100 20 s.Name = "yinzhengjie" 21 fmt.Println(s) 22 23 s1 := Student{ //引用結構體,方式二 24 ID:200, 25 Name:"餅干", 26 } 27 fmt.Println(s1) 28 } 29 30 31 #以上代碼輸出結果如下: 32 {100 yinzhengjie} 33 {200 餅干}
2.結構體的指針;
在Golang的全局變量中,我們聲明一個變量的同時,還需要制定其數據類型,可以是int,string,byte,也可以是[]int,[]string,[]byte,還可以是我們自定義的結構體等等。
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 type Student struct { //定義一個結構體 13 ID int 14 Name string 15 } 16 17 func main() { 18 19 s1 := Student{ //引用(實例化)結構體 20 ID:100, 21 Name:"尹正傑", 22 } 23 fmt.Println(s1) 24 25 var p *Student //定義p為我們自定義的結構體類型 26 p = &s1 //將實例化的內存地址傳給p 27 p.ID = 200 //修改結構體里面的ID參數為200,由於p是指針類型,故會修改s1的ID的值。 28 fmt.Println(s1) 29 30 var p1 *int 31 p1 = &s1.ID //我們也可以直接取到我們自定義的結構體重的參數的內存地址,然后給其賦值,也能達到修改參數的效果。 32 *p1 = 300 33 fmt.Println(s1) 34 } 35 36 37 #以上代碼輸出結果如下: 38 {100 尹正傑} 39 {200 尹正傑} 40 {300 尹正傑}
五.交互模式
一般用Golang寫的運維工具都是自己把功能跑完,不需要每次手動執行一些命令才能完成工作。但是在這幾道一些安全性信息的時候就不得不要求用戶交互了,比如你登錄QQ,登錄你的愛奇藝會員,騰訊會員以及樂視會員等等。都需要你手動輸入一些字符串。那么問題來了,Golang是如何實現這功能的呢?跟着我一起實驗吧!
1.初探交互模式;
我們寫一個交互程序,讓用戶輸入什么就打印出來什么。
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import "fmt" 11 12 13 var cmd string 14 15 func main() { 16 for { //循環輸入 17 fmt.Print("input>>") //輸入的內容都是字符串類型。 18 fmt.Scan(&cmd) //獲取用命令行中第一字符串傳給cmd。 19 if cmd == "stop" { //定義結束循環的關鍵字 20 break 21 } 22 fmt.Println(cmd) //將輸入的字符串cmd變量打印出來 23 } 24 } 25 26 27 #以上代碼執行結果如下: 28 input>>尹正傑 29 尹正傑 30 input>>yinzhengjie 31 yinzhengjie 32 input>>您好 33 您好 34 input>>hello 35 hello 36 input>>world 37 world 38 input>>
2.獲取一整行內容;
獲取通過第一個交互模式你也體會到了,存在很多坑,比如不能把輸出空格或者回車就會卡在那里不動了,無法獲取完整的一行內容並打印,只能講命令行的第一個位置參數給打印出來,那么如果將一整行的內容都打印出來呢?這個時候我們就需要對bufio這個package需要一定的掌握。
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 9 package main 10 11 import ( 12 "bufio" 13 "os" 14 "fmt" 15 "strings" 16 ) 17 18 var ( 19 s string 20 n int 21 line string 22 ) 23 func main() { 24 f := bufio.NewReader(os.Stdin) //讀取輸入的內容 25 for { 26 fmt.Print("請輸入一些字符串>") 27 line,_ = f.ReadString('\n') //定義一行輸入的內容分隔符。 28 if len(line) == 1 { 29 continue //如果用戶輸入的是一個空行就讓用戶繼續輸入。 30 } 31 line = strings.Replace(line,"\n"," ",-1) //利用string的修改操作,將換行符脫掉。 32 // 要注意的是它是需要單獨占用內存的。其實這行沒必要寫,因為只需要把下一行的“\n”去掉就好使啦 33 // 即:fmt.Printf("您輸入的是:%s",line),因為我剛剛學的時候踩了個坑,所以在這里記錄下。 34 fmt.Printf("您輸入的是:%s\n",line) 35 fmt.Sscan(line,&s,&n) //將s和n的值傳給line,如果不傳值的話就 36 if s == "stop" { 37 break 38 } 39 fmt.Printf("您輸入的第一個參數是:·\033[31;1m%v\033[0m·,輸入的第二個參數是··\033[31;1m%v\033[0m·.\n",s,n) 40 } 41 } 42 43 44 45 #意思代碼輸出結果如下: 46 請輸入一些字符串> 47 請輸入一些字符串> 48 請輸入一些字符串>GOLANG 123 49 您輸入的是:GOLANG 123 50 您輸入的第一個參數是:·GOLANG·,輸入的第二個參數是··123·. 51 請輸入一些字符串>
六.序列化和反序列化(json)
說直白點,序列化就是講數據寫入硬盤,反序列化就是講數據從硬盤讀取出來。而存取方式又是用戶選取的一個難題,每種語言都有自己的存取數據的方式,不過很多種語言都一款通用的存取方式,那就是json。也就是說很多語言都支持這種存儲,說的在直白點就是你用Golang將數據用json存取,我可以用JAVA語言打卡這個文件內容,並獲取到文件的內容做相應的處理。
1.序列化案例;
執行之前的“a.txt”文件內容

http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/

http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ {"ID":1,"Name":"yinzhengjie"}
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import ( 11 "encoding/json" 12 "log" 13 "fmt" 14 "os" 15 ) 16 17 type Student struct { 18 ID int 19 Name string 20 } 21 22 func main() { 23 s := Student{ 24 ID:1, 25 Name:"yinzhengjie", 26 } 27 buf,err := json.Marshal(s) //序列化一個結構體, 28 if err != nil { 29 log.Fatal("序列化報錯是:%s",err) 30 } 31 f,err := os.OpenFile("D:\\Golang環境\\Golang Program\\Golang lesson\\Day4\\a.txt",os.O_APPEND|os.O_CREATE|os.O_RDWR,0644) 32 if err != nil { 33 log.Fatal(err) 34 } 35 f.WriteString(string(buf)) 36 f.WriteString("\n") 37 f.Close() 38 fmt.Println("寫入成功") 39 } 40 41 42 43 #以上代碼執行結果如下: 44 寫入成功
2.反序列化之前的內容;
文件“b.txt”內容如下:

{100 yinzhengjie}
1 /* 2 #!/usr/bin/env gorun 3 @author :yinzhengjie 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 5 EMAIL:y1053419035@qq.com 6 */ 7 8 package main 9 10 import ( 11 "encoding/json" 12 "log" 13 "fmt" 14 "io/ioutil" 15 ) 16 17 type Student struct { 18 ID int 19 Name string 20 } 21 22 func main() { 23 buf,err := ioutil.ReadFile("D:\\Golang環境\\Golang Program\\Golang lesson\\Day4\\b.txt") 24 if err != nil { 25 fmt.Println("你愁啥?文件打開錯誤了!") 26 return 27 } 28 var str Student 29 err1 := json.Unmarshal(buf,&str) 30 if err1 != nil { 31 log.Fatal("反序列化報錯啦:%s",err1) 32 } 33 fmt.Println(str) 34 } 35 36 37 #以上代碼執行結果如下: 38 {100 yinzhengjie}
3.小試牛刀;
寫一個簡單的交互學生管理系統,需要運用的知識點有:map,文件處理,序列化,字符串處理,結構體等等,以下僅是初稿,暫時提供的一個思路。
1 [root@yinzhengjie tmp]# more student.go 2 /* 3 #!/usr/bin/env gorun 4 @author :yinzhengjie 5 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 6 EMAIL:y1053419035@qq.com 7 */ 8 9 package main 10 11 import ( 12 "bufio" 13 "fmt" 14 "os" 15 "log" 16 "io" 17 "encoding/json" 18 "strings" 19 ) 20 21 var ( 22 cmd string 23 name string 24 id int 25 line string 26 file_name string 27 ) 28 29 type Student struct { 30 ID int 31 Name string 32 } 33 34 func main() { 35 f := bufio.NewReader(os.Stdin) 36 for { 37 fmt.Print(" 請輸入>>> ") 38 line, _ = f.ReadString('\n') 39 fmt.Sscan(line, &cmd) 40 if len(line) == 1 { 41 continue 42 } 43 switch cmd { 44 case "list": 45 list() 46 case "add": 47 add() 48 case "save": 49 save() 50 case "load": 51 load() 52 case "stop": 53 os.Exit(0) 54 default: 55 fmt.Println("您輸出的命令無效") 56 } 57 } 58 } 59 60 func list() { 61 f,err := os.Open("student_info.json") //打開一個文件,如果這個文件不存在的話就會報錯。 62 if err != nil { 63 log.Fatal(err) 64 } 65 r := bufio.NewReader(f) //取出文件的內容 66 for { 67 line,err := r.ReadString('\n') 68 if err == io.EOF{ 69 break 70 } 71 fmt.Print(line) 72 } 73 f.Close() 74 } 75 76 77 func add() { 78 fmt.Sscan(line, &cmd, &id, &name) 79 f, err := os.Open("student_info.json") //打開一個文件,如果這個文件不存在的話就會報錯。 80 if err != nil { 81 log.Fatal(err) 82 } 83 r := bufio.NewReader(f) //取出文件的內容 84 flag := 0 //定義一個標志位,當輸入的ID和name相同時,就將其的值改為1. 85 for { 86 line, err := r.ReadString('\n') 87 if err == io.EOF { 88 break 89 } 90 s := Student{ 91 ID: id, 92 Name: name, 93 } 94 buf, err := json.Marshal(s) 95 if err != nil { 96 log.Fatal("序列化報錯是:%s", err) 97 } 98 line = strings.Replace(line,"\n","",-1) //將換行符替換為空,你可以理解是刪除了換行符。 99 if line == string(buf) { 100 fmt.Println("對不起,您輸入的用戶或者ID已經存在了,請重新輸入!") 101 flag = 1 102 break 103 104 } 105 } 106 if flag == 0 { 107 s := Student{ 108 ID:id, 109 Name:name, 110 } 111 buf,err := json.Marshal(s) //序列化一個結構體, 112 if err != nil { 113 log.Fatal("序列化報錯是:%s",err) 114 } 115 fmt.Println(string(buf)) 116 f,err := os.OpenFile("student_info.json",os.O_APPEND|os.O_CREATE|os.O_RDWR,0644) 117 if err != nil { 118 log.Fatal(err) 119 } 120 f.WriteString(string(buf)) 121 f.WriteString("\n") 122 f.Close() 123 fmt.Println("寫入成功") 124 125 } 126 } 127 func save() { 128 fmt.Sscan(line, &cmd,&file_name) 129 f,err := os.Open("student_info.json") //打開一個文件,如果這個文件不存在的話就會報錯。 130 if err != nil { 131 log.Fatal(err) 132 } 133 r := bufio.NewReader(f) //取出文件的內容 134 f2,err := os.OpenFile(file_name,os.O_APPEND|os.O_CREATE|os.O_RDWR,0644) //打開一個新文件 135 if err != nil { 136 log.Fatal(err) 137 } 138 for { 139 line,err := r.ReadString('\n') 140 if err == io.EOF{ 141 break 142 } 143 f2.WriteString(line) //將student_info.json內容寫到指定的文件中去。 144 } 145 f2.Close() 146 f.Close() 147 } 148 149 func load() { 150 fmt.Sscan(line, &cmd,&file_name) 151 f,err := os.Open(file_name) //打開一個文件,如果這個文件不存在的話就會報錯。 152 if err != nil { 153 fmt.Println("對不起!系統沒用找到該文件!") 154 return 155 } 156 r := bufio.NewReader(f) //取出文件的內容 157 for { 158 line,err := r.ReadString('\n') 159 if err == io.EOF{ 160 break 161 } 162 fmt.Print(line) 163 } 164 f.Close() 165 } 166 [root@yinzhengjie tmp]# 167 [root@yinzhengjie tmp]# 168 [root@yinzhengjie tmp]# 169 [root@yinzhengjie tmp]# 170 [root@yinzhengjie tmp]# go run student.go 171 請輸入>>> 172 請輸入>>> 173 請輸入>>> list 174 {"ID":1,"Name":"bingan"} 175 {"ID":2,"Name":"yinzhengjie"} 176 {"ID":3,"Name":"jie"} 177 {"ID":5,"Name":"Golang"} 178 {"ID":4,"Name":"reboot"} 179 {"ID":10,"Name":"jie"} 180 {"ID":100,"Name":"dev"} 181 {"ID":200,"Name":"jay"} 182 請輸入>>> 183 請輸入>>> 184 請輸入>>> add 300 GOOD 185 {"ID":300,"Name":"GOOD"} 186 寫入成功 187 請輸入>>> list 188 {"ID":1,"Name":"bingan"} 189 {"ID":2,"Name":"yinzhengjie"} 190 {"ID":3,"Name":"jie"} 191 {"ID":5,"Name":"Golang"} 192 {"ID":4,"Name":"reboot"} 193 {"ID":10,"Name":"jie"} 194 {"ID":100,"Name":"dev"} 195 {"ID":200,"Name":"jay"} 196 {"ID":300,"Name":"GOOD"} 197 請輸入>>> 198 請輸入>>> save 6666 199 請輸入>>> 200 請輸入>>> load 6666 201 {"ID":1,"Name":"bingan"} 202 {"ID":2,"Name":"yinzhengjie"} 203 {"ID":3,"Name":"jie"} 204 {"ID":5,"Name":"Golang"} 205 {"ID":4,"Name":"reboot"} 206 {"ID":10,"Name":"jie"} 207 {"ID":100,"Name":"dev"} 208 {"ID":200,"Name":"jay"} 209 {"ID":300,"Name":"GOOD"} 210 請輸入>>> 211 請輸入>>> stop 212 You have new mail in /var/spool/mail/root 213 [root@yinzhengjie tmp]#