1. 程式人生 > >Go語言基礎介紹

Go語言基礎介紹

unit plain inter mage popu 函數返回 int cto 可選

Go是一個開源的編程語言。Go語言被設計成一門應用於搭載Web服務器,存儲集群或類似用途的巨型中央服務器的系統編程語言。目前,Go最新發布版本為1.10.

Go語言可以運行在Linux、FreeBSD、Mac OS X和Windows系統上。

1. 結構:Go語言的基礎組成有以下幾個部分:包聲明、引入包、函數、變量、語句&表達式、註釋。

(1)、必須在源文件中非註釋的第一行指明這個文件屬於哪個包,如:package main

(2)、註釋與C++相同,有單行註釋即”//”和多行註釋即”/* … */”兩種。

(3)、當標識符(包括常量、變量、類型、函數名、結構字段等等)以一個大寫字母開頭,那麽使用這種形式的標識符的對象就可以被外部包的代碼所使用(客戶端程序需要先導入這個包),這被稱為導出;標識符如果以小寫字母開頭,則對包外是不可見的,但是它們在整個包的內部是可見並且可用的。

2. 基礎語法:

(1)、Go標記:Go程序可以由多個標記組成,可以是關鍵字、標識符、常量、字符串、字符。

(2)、行分隔符:在Go程序中,一行代表一個語句結束。每個語句不需要像C++語言一樣以分號”;”結尾,因為這些工作都將由Go編譯器自動完成。如果你打算將多個語句寫在同一行,它們必須使用”;”為區分,但在實際開發中我們並不鼓勵這種做法。

(3)、註釋:註釋不會被編譯,每一個包應該有相關註釋。單行註釋以”//”開頭,多行註釋以”/*”開頭,以”*/”結尾,與C++相同。

(4)、標識符:用來命名變量、類型等程序實體。一個標識符實際上就是一個或是多個字母(A~Z和a~z)、數字(0~9)、下劃線”_”組成的序列,但是第一個字符必須是字母或下劃線而不能是數字。標識符不能是Go語言的關鍵字。

(5)、關鍵字:25個關鍵字:break、default、func、interface、select、case、defer、go、map、struct、chan、else、goto、package、switch、const、fallthrough、if、range、type、continue、for、import、return、var。36個預定義標識符:append、bool、type、cap、close、complex、complex64、complex128、uint16、copy、false、float32、float64、image、int、int8、int16、uint32、int32、int64、iota、len、make、new、nil、panic、unit64、print、println、real、recover、string、true、uint、uint8、uintptr。

程序一般由關鍵字、常量、變量、運算符、類型和函數組成。程序中可能會使用到這些分隔符:()、[]、{}。程序中可能會使用到這些標點符號:.、,、;、:和…。

3. 數據類型:在Go編程語言中,數據類型用於聲明函數和變量:布爾型(true、false);數字類型(整型、浮點型、復數);字符串類型(一串固定長度的字符連接起來的字符序列);派生類型(指針類型、數組類型、結構化類型、Channel類型、函數類型、切片類型、接口類型、Map類型)。

4. 變量:聲明變量的一般形式是使用var關鍵字。也可多變量聲明。

變量聲明方式:(1)、指定變量類型,聲明後若不賦值,使用默認值;(2)、根據值自行判定變量類型;(3)、省略var,註意:=左側的變量不應該是已經聲明過的,否則會導致編譯錯誤。

值類型和引用類型:所有像int、float、bool和string這些基本類型都屬於值類型,使用這些類型的變量直接指向存在內存中的值。你可以通過&i來獲取變量i的內存地址。值類型的變量的值存儲在棧中。內存地址會根據機器的不同而有所不同,甚至相同的程序在不同的機器上執行後也會有不同的內存地址。因為每臺機器可能有不同的存儲器布局,並且位置分配也可能不同。更復雜的數據通常會需要使用多個字,這些數據一般使用引用類型保存。一個引用類型的變量r1存儲的是r1的值所在的內存地址(數字),或內存地址中第一個字所在的位置。這個內存地址稱之為指針,這個指針實際上也被存在另外的某一個字中。同一個引用類型的指針指向的多個字可以是連續的內存地址中(內存布局是連續的),也可以將這些字分散存放在內存中,每個字都指示了下一個字所在的內存地址。

簡短形式,使用:=賦值操作符:我們知道可以在變量的初始化時省略變量的類型而由系統自動推斷,聲明語句寫上var關鍵字其實是顯得多余了,因此我們可以將它們簡寫為:a:= 5 或b := false,a和b的類型(int和bool)將由編譯器自動推斷。這是使用變量的首選形式,但是它只能被用在函數體內,而不可以用於全局變量的聲明與賦值。

註意事項:(1)、如果在相同的代碼塊中,我們不可以再次對於相同名稱的變量使用初始化聲明。(2)、如果你聲明了一個局部變量卻沒有在相同的代碼塊中使用它,同樣會得到編譯錯誤。但是全局變量是允許聲明但不使用。同一類型的多個變量可以聲明在同一行。

空白標識符_也被用於拋棄值。_實際上是一個只寫變量,你不能得到它的值。這樣做是因為Go語言中你必須使用所有被聲明的變量,但有時你並不需要使用從一個函數得到的所有返回值。

多個變量可以聲明在同一行,多個變量也可以在同一行進行賦值,這被稱為並行或同時賦值。並行賦值也被用於當一個函數返回多個返回值時。

5. 常量:是一個簡單值的標識符,在程序運行時,不會被修改的量。常量中的數據類型只可以是布爾型、數字型(整數型、浮點型和復數)和字符串型。

你可以省略類型說明符,因為編譯器可以根據變量的值來推斷其類型。也可以在同一行聲明多個常量和賦值。常量還可以用作枚舉。

常量可以用len()、cap()、unsafe.Sizeof()函數計算表達式的值。常量表達式中,函數必須是內置函數。

iota:特殊常量,可以認為是一個可以被編譯器修改的常量。在每一個const關鍵字出現時,被重置為0,然後再下一個const出現之前,每出現一次iota,其所代表的數字會自動增加1。iota可以被用作枚舉值。

6. 運算符:用於在程序運行時執行數學或邏輯運算。

Go語言內置的運算符有:算術運算符、關系運算符、邏輯運算符、位運算符、賦值運算符、其它運算符。

算術運算符:+、-、*、/、%、++、--

關系運算符:==、!=、>、<、>=、<=

邏輯運算符:&&、||、!

位運算符:&、|、^、<<、>>,對整數在內存中的二進制位進行操作。

賦值運算符:=、+=、-=、*=、/=、%=、<<=、>>=、&=、^=、|=

其它運算符:&(獲取變量存儲地址)、*(指針變量)

運算符優先級:二元運算符的運算方向均是從左至右。可以使用括號來臨時提升某個表達式的整體運算優先級。

7. 條件語句:需要開發者通過指定一個或多個條件,並通過測試條件是否為true來決定是否執行指定語句,並在條件為false的情況下執行另外的語句。

if語句:由布爾表達式後緊跟一個或多個語句組成。if語句後可以使用可選的else語句。你也可以在if或else if語句中嵌入一個或多個if或else if語句。

switch語句:用於基於不同條件執行不同動作,每一個case分支都是唯一的,從上到下逐一檢查,直到匹配為止。匹配項後面也不需要再加break。case類型不被局限於常量或整數,但必須是相同的類型。switch語句還可以被用於type--switch來判斷某個interface變量中實際存儲的變量類型。

select語句:select是Go中的一個控制結構,類似於用於通信的switch語句。每個case必須是一個通信操作,要麽是發送要麽是接收。select隨機執行一個可運行的case。如果沒有case可運行,它將阻塞,直到有case可運行。一個默認的子句應該總是可運行的。select語句的語法:(1)、每個case都必須是一個通信;(2)、所有channel表達式都會被求值;(3)、所有被發送的表達式都會被求值;(4)、如果任意某個通信可以進行,它就執行,其它被忽略;(5)、如果有多個case都可以運行,select會隨機公平地選出一個執行,其它不會執行。否則,如果有default子句,則執行該語句。如果沒有default子句,select將阻塞,直到某個通信可以運行。Go不會重新對channel或值進行求值。

8. 循環語句:for,可以嵌套一個或多個for。循環控制語句可以控制循環體內語句的執行過程,包括break、continue、goto。如果循環中條件語句永遠不為false則會進行無限循環。有些類似於C語言中的for和while。

break語句:(1)、用於循環語句中跳出循環,並開始執行循環之後的語句;(2)、在switch中在執行一條case後跳出語句的作用。

continue語句:有點像break語句,但是continue不是跳出循環,而是跳過當前循環執行下一次循環語句。

goto語句:可以無條件地轉移到過程中指定的行。在結構化程序設計中一般不主張使用goto語句。

9. 函數:是基本的代碼塊,用於執行一個任務。Go語言最少有個main()函數。函數聲明告訴了編譯器函數的名稱、返回類型和參數。Go語言標準庫提供了多種可動用的內置的函數。

函數定義格式:func function_name([parameter list]) [return_types] {函數體}

函數定義解析:(1)、func:函數由func開始聲明。(2)、function_name:函數名稱,函數名和參數列表一起構成了函數簽名。(3)、parameter list:參數列表,參數就像一個占位符,當函數被調用時,你可以將值傳遞給參數,這個值被稱為實際參數。參數列表指定的是參數類型、順序、及參數個數。參數是可選的,函數也可以不包含參數。(4)、return_types:返回類型,函數返回一列值。(5)、函數體:函數定義的代碼集合。

Go函數可以返回多個值。

函數參數:函數如果使用參數,該變量可稱為函數的形參。形參就像定義在函數體內的局部變量。調用函數,可以通過兩種方式傳遞參數:值傳遞和引用傳遞。默認情況下,Go語言使用的是值傳遞,即在調用過程中不會影響到實際參數。

值傳遞:是指在調用函數時將實際參數復制一份傳遞到函數中,這樣在函數中如果對參數進行修改,將不會影響到實際參數。

引用傳遞:是指在調用函數時將實際參數的地址傳遞到函數中,那麽在函數中對參數所進行的修改,將影響到實際參數。

函數用法:(1)、函數作為值:函數定義後可作為值來使用。(2)、閉包:是匿名函數,可在動態編程中使用。匿名函數是一個”內聯”語句或表達式。匿名函數的優越性在於可以直接使用函數內的變量,不必聲明。(3)、方法:是一個包含了接受者的函數,接受者可以是命名類型或者結構體類型的一個值或者是一個指針。所有給定類型的方法屬於該類型的方法集。

10. 變量作用域:Go語言中變量可以在三個地方聲明:局部變量、全局變量、形式參數。

(1)、局部變量:在函數體內聲明的變量稱之為局部變量,它們的作用域只在函數體內,參數和返回值變量也是局部變量。

(2)、全局變量:在函數體外聲明的變量稱之為全局變量,全局變量可以在整個包甚至外部包(被導出後)使用。全局變量可以在任何函數中使用。

(3)、形式參數:函數定義中的變量稱為形式參數。形式參數會作為函數的局部變量來使用。

Go語言程序中全局變量與局部變量名稱可以相同,但是函數內的局部變量會被優先考慮。

11. 數組:是具有相同唯一類型的一組已編號且長度固定的數據項序列,這種類型可以是任意的原始類型如整型、字符串或者自定義類型。數組元素可以通過索引(位置)來讀取(或者修改),索引從0開始,第一個元素索引為0,第二個索引為1,以此類推。

聲明數組:Go語言數組聲明需要指定元素類型及元素個數。數組長度必須是整數且大於0。

初始化數組:初始化數組中{}中的元素個數不能大於[]中的數字。如果忽略[]中的數字不設置數字大小,Go語言會根據元素的個數來設置數組的大小。

訪問數組元素:數組元素可以通過索引(位置)來讀取。格式為數組名後加中括號,中括號中為索引的值。

多維數組:Go語言支持多維數組。

向函數傳遞數組:如果你想向函數傳遞數組參數,你需要在函數定義時,聲明形參為數組。

12. 指針:變量是一種方便的占位符,用於引用計算機內存地址。Go語言的取地址符是&,放到一個變量前使用就會返回相應變量的內存地址。一個指針變量指向了一個值的內存地址。

指針使用流程:定義指針變量;為指針變量賦值;訪問指針變量中指向地址的值。在指針類型前面加上*號(前綴)來獲取指針所指向的內容。

空指針:當一個指針被定義後沒有分配到任何變量時,它的值為nil。nil指針也為空指針。nil在概念上和其它語言的null、None、nil、NULL一樣,都指代零值或空值。

指針數組:可以定義一個指針數組來存儲地址。

指向指針的指針:如果一個指針變量存放的又是另一個指針變量的地址,則稱這個指針變量為指向指針的指針變量。訪問指向指針的指針變量值需要使用兩個*號。

向函數傳遞指針參數:只需要在函數定義的參數上設置為指針類型即可。通過引用或地址傳參,在函數調用時可以改變其值。

13. 結構體:Go語言中數組可以存儲同一類型的數據,但在結構體中我們可以為不同項定義不同的數據類型。結構體是由一系列具有相同類型或不同類型的數據構成的數據集合。

結構體定義需要使用type和struct語句。struct語句定義一個新的數據類型,結構體中有一個或多個成員。type語句設定了結構體的名稱。一旦定義了結構體類型,它就能用於變量的聲明。如果要訪問結構體成員,需要使用點號(.)操作符。你可以像其它數據類型一樣將結構體類型作為參數傳遞給函數。你可以定義指向結構體的指針類似於其它指針變量。

14. 切片(slice):Go語言切片是對數組的抽象。Go數組的長度不可改變,Go中提供了一種靈活,功能強悍的內置類型切片(“動態數組”)。與數組相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。有些類似於C++中的vector。

你可以聲明一個未指定大小的數組來定義切片,切片不需要說明長度,或使用make()函數來創建切片。

切片是可索引的,並且可以用len()方法獲取長度。切片提供了計算容量的方法cap()可以測量切片最長可以達到多少。一個空切片在未初始化之前默認為nil,長度為0.可以通過設置下限及上限來設置截取切片。

如果想增加切片的容量,我們必須創建一個新的更大的切片並把原分片的內容都拷貝過來。可使用拷貝切片的copy方法,或向切片追加新元素的append方法。

15. range關鍵字:Go語言中range關鍵字用於for循環中叠代數組(array)、切片(slice)、通道(channel)或集合(map)的元素。在數組和切片中它返回元素的索引值,在集合中返回key-value對的key值。

16. Map(集合):Map是一種無序的鍵值對的集合。Map最重要的一點是通過key來快速檢索數據,key類似於索引,指向數據的值。Map是一種集合,所以我們可以像叠代數組和切片那樣叠代它。Map是無序的,我們無法決定它的返回順序,這是因為Map是使用hash表來實現的。

可以使用內建函數make也可以使用map關鍵字來定義Map。如果不初始化map,那麽就會創建一個nil map。nil map不能用來存放鍵值對。delete()函數用來刪除集合的元素。

17. 遞歸函數:遞歸,就是在運行的過程中調用自己。在使用遞歸時,需要設置退出條件,否則遞歸將陷入無限循環中。

18. 類型轉換:用於將一種數據類型的變量轉換為另外一種類型的變量,形式為:type_name(expression)

19. 接口:把所有的具有共性的方法定義在一起,任何其它類型只要實現了這些方法就是實現了這個接口。

20. 錯誤處理:Go語言通過內置的錯誤接口提供了非常簡單的錯誤處理機制。

以下是測試代碼:

[plain] view plain copy
  1. // 變量相關測試代碼
  2. package main
  3. import "fmt"
  4. // 全局變量聲明
  5. var c float32
  6. var x = 11
  7. func main() {
  8. // 局部變量聲明
  9. // 指定變量類型,聲明後若不賦值,使用默認值
  10. var available bool
  11. available = true
  12. fmt.Println(available)
  13. // 根據值自動判定變量類型
  14. var a = 1
  15. var b = 2.5
  16. fmt.Println(a, b)
  17. c = float32(a) + float32(b)
  18. fmt.Printf("c = %f\n", c)
  19. // 省略var, 註意 :=左側的變量不應該是已經聲明過的,否則會導致編譯錯誤,這種形式只能被用在函數體中
  20. valid := false
  21. _, d := 5, 6 // 空白標識符
  22. fmt.Println(valid, d)
  23. // 多變量聲明
  24. var enabled, disabled = true, "111"
  25. fmt.Println(enabled, disabled)
  26. // 獲取變量a的內存地址
  27. fmt.Println(&a)
  28. // Go語言程序中全局變量與局部變量名稱可以相同,但是函數內的局部變量會被優先考慮
  29. var x = -11
  30. fmt.Printf("x = %d\n", x)
  31. }
[plain] view plain copy
  1. // 常量相關測試代碼
  2. package main
  3. import "fmt"
  4. import "unsafe"
  5. // 常量還可以用作枚舉
  6. const (
  7. o = "abc"
  8. p = len(o)
  9. q = unsafe.Sizeof(o)
  10. )
  11. // itoa: iota可以被用作枚舉值,第一個iota等於0,每當iota在新的一行被使用時,它的值都會自動加1
  12. const (
  13. d = iota
  14. e
  15. f
  16. )
  17. func main() {
  18. const a string = "abc" // 顯示類型定義
  19. const b = "def" // 隱式類型定義
  20. fmt.Println(a, b)
  21. const x, y, z = 1, 0.2, "blog"
  22. fmt.Println(x, y, z)
  23. fmt.Println(o, p, q)
  24. fmt.Println(d, e, f)
  25. }
[plain] view plain copy
  1. // 運算符相關測試代碼
  2. package main
  3. import "fmt"
  4. func main() {
  5. // 算術運算符
  6. var a, b, c = 1, 2, 3
  7. fmt.Printf("a + b = %d\n", a+b)
  8. fmt.Printf("a - c = %d\n", a-c)
  9. fmt.Printf("a * b = %d\n", a*b)
  10. c++ // 註:++和--好像僅有前綴運算符
  11. fmt.Printf("c++ = %d\n", c)
  12. b--
  13. fmt.Printf("--b = %d\n", b)
  14. // 關系運算符
  15. if a > b { // 註:visual studio code會默認把if (a > b)調整為if a > b
  16. fmt.Printf("a > b\n")
  17. } else {
  18. fmt.Printf("a <= b\n")
  19. }
  20. // 邏輯運算符
  21. x, y := true, false
  22. if x && y {
  23. fmt.Printf("true\n")
  24. } else {
  25. fmt.Printf("false\n")
  26. }
  27. // 位運算符: 好像僅支持整數
  28. a, b = 1, 3
  29. c = a & b
  30. fmt.Printf("c = %d\n", c)
  31. fmt.Printf("b << 2: %d\n", b<<2)
  32. // 賦值運算符
  33. b <<= 2
  34. fmt.Printf("b = %d\n", b)
  35. // 其它運算符:&、*
  36. fmt.Printf("b‘s address: %0x\n", &b)
  37. var ptr *int
  38. ptr = &a
  39. fmt.Printf("pointer: %0x\n", ptr)
  40. }
[plain] view plain copy
  1. // 條件語句相關測試代碼
  2. package main
  3. import "fmt"
  4. func main() {
  5. // if
  6. a := 1.2
  7. if a > 0 {
  8. fmt.Printf("a > 0, a = %f\n", a)
  9. }
  10. // if else
  11. b := 2.5
  12. if b > 10 {
  13. fmt.Printf("b > 10\n")
  14. } else {
  15. fmt.Printf("b <= 10\n")
  16. }
  17. fmt.Printf("b = %f\n", b)
  18. // if 嵌套
  19. if a > 0 {
  20. if b > 0 {
  21. fmt.Printf("a > 0, b > 0\n")
  22. }
  23. }
  24. // switch
  25. grade := "B"
  26. marks := 90
  27. switch marks {
  28. case 90:
  29. grade = "A"
  30. case 80:
  31. grade = "B"
  32. case 50, 60:
  33. grade = "C"
  34. default:
  35. grade = "D"
  36. }
  37. fmt.Printf("grade = %s\n", grade)
  38. // type switch
  39. var x interface{}
  40. switch i := x.(type) {
  41. case nil:
  42. fmt.Printf(" x 的類型: %T\n", i)
  43. case int:
  44. fmt.Printf("x 是 int 型\n")
  45. case float64:
  46. fmt.Printf("x 是 float64 型\n")
  47. case func(int) float64:
  48. fmt.Printf("x 是 func(int) 型\n")
  49. case bool, string:
  50. fmt.Printf("x 是 bool 或 string 型\n")
  51. default:
  52. fmt.Printf("未知型\n")
  53. }
  54. // select
  55. var c1, c2, c3 chan int
  56. var i1, i2 int
  57. select {
  58. case i1 = <-c1:
  59. fmt.Printf("received ", i1, " from c1\n")
  60. case c2 <- i2:
  61. fmt.Printf("sent ", i2, " to c2\n")
  62. case i3, ok := (<-c3): // same as: i3, ok := <-c3
  63. if ok {
  64. fmt.Printf("received ", i3, " from c3\n")
  65. } else {
  66. fmt.Printf("c3 is closed\n")
  67. }
  68. default:
  69. fmt.Printf("no communication\n")
  70. }
  71. }
[plain] view plain copy
  1. // 循環語句相關測試代碼
  2. package main
  3. import "fmt"
  4. func main() {
  5. // for
  6. a, b := 0, 15
  7. fmt.Printf("a的值為: ")
  8. for a = 0; a < 10; a++ {
  9. fmt.Printf(" %d ", a)
  10. }
  11. fmt.Printf("\n")
  12. fmt.Printf("a的值為: ")
  13. for a < b {
  14. a++
  15. fmt.Printf(" %d ", a)
  16. }
  17. fmt.Printf("\n")
  18. // for嵌套、break
  19. var i, j int
  20. fmt.Printf("2到100之間的素數包括:")
  21. for i = 2; i < 100; i++ {
  22. for j = 2; j <= (i / j); j++ {
  23. if i%j == 0 {
  24. break
  25. }
  26. }
  27. if j > (i / j) {
  28. fmt.Printf(" %d ", i)
  29. }
  30. }
  31. fmt.Printf("\n")
  32. // continue
  33. a = 0
  34. fmt.Printf("a的奇數:")
  35. for a < 20 {
  36. a++
  37. if a%2 == 0 {
  38. continue
  39. }
  40. fmt.Printf(" %d ", a)
  41. }
  42. fmt.Printf("\n")
  43. // goto
  44. a = 0
  45. fmt.Printf("打印a的值:")
  46. Loop:
  47. for a < 10 {
  48. if a == 5 {
  49. a++
  50. goto Loop
  51. }
  52. fmt.Printf(" %d ", a)
  53. a++
  54. }
  55. fmt.Printf("\n")
  56. }
[plain] view plain copy
  1. // 函數相關測試代碼
  2. package main
  3. import (
  4. "fmt"
  5. "math"
  6. )
  7. // 函數返回兩個數的最大值,值傳遞
  8. func max(num1, num2 int) int {
  9. var result int
  10. if num1 > num2 {
  11. result = num1
  12. } else {
  13. result = num2
  14. }
  15. return result
  16. }
  17. // 函數支持返回多個值,值傳遞
  18. func swap(x, y string) (string, string) {
  19. return y, x
  20. }
  21. // Go函數不支持C++中的函數重載,引用傳遞
  22. func swap1(x *int, y *int) {
  23. var temp int
  24. temp = *x
  25. *x = *y
  26. *y = temp
  27. }
  28. func getSequence() func() int {
  29. i := 0
  30. return func() int {
  31. i++
  32. return i
  33. }
  34. }
  35. type Circle struct {
  36. radius float64
  37. }
  38. func (c Circle) getArea() float64 {
  39. // c.radius 即為Circle類型對象中的屬性
  40. return 3.14 * c.radius * c.radius
  41. }
  42. func main() {
  43. a, b := 100, 200
  44. var ret = max(a, b)
  45. fmt.Printf("a,b最大值為: %d\n", ret)
  46. var x, y = "hello", "beijing"
  47. fmt.Printf("x: %s, y: %s\n", x, y)
  48. m, n := swap(x, y)
  49. fmt.Printf("x: %s, y: %s\n", x, y)
  50. fmt.Printf("m: %s, n: %s\n", m, n)
  51. p, q := -100, 500
  52. fmt.Printf("p: %d, q: %d\n", p, q)
  53. swap1(&p, &q)
  54. fmt.Printf("p: %d, q: %d\n", p, q)
  55. // 函數用法:函數作為值
  56. getSquareRoot := func(x float64) float64 {
  57. return math.Sqrt(x)
  58. }
  59. fmt.Printf("square root: %f\n", getSquareRoot(9))
  60. // 函數用法:閉包
  61. nextNumber := getSequence()
  62. // 調用nextNumber函數,i 變量自增 1 並返回
  63. fmt.Println("i的值: %d", nextNumber())
  64. fmt.Println("i的值: %d", nextNumber())
  65. fmt.Println("i的值: %d", nextNumber())
  66. // 創建新的函數nextNumber1,並查看結果
  67. nextNumber1 := getSequence()
  68. fmt.Println("i的值: %d", nextNumber1())
  69. fmt.Println("i的值: %d", nextNumber1())
  70. // 函數用法:方法
  71. var c1 Circle
  72. c1.radius = 10.00
  73. fmt.Println("Area of Circle(c1) = ", c1.getArea())
  74. }
[plain] view plain copy
  1. // 數組相關測試代碼
  2. package main
  3. import "fmt"
  4. func getAverage(arr []int, size int) float32 {
  5. var avg, sum float32
  6. for i := 0; i < size; i++ {
  7. sum += float32(arr[i])
  8. }
  9. avg = sum / float32(size)
  10. return avg
  11. }
  12. func main() {
  13. // 一維數組
  14. const num = 10
  15. var n [num]int
  16. for i := 0; i < num; i++ {
  17. n[i] = i + 100
  18. }
  19. for j := 0; j < num; j++ {
  20. fmt.Printf("Element[%d] = %d\n", j, n[j])
  21. }
  22. // 初始化數組
  23. const num2 = 5
  24. var m = [num2]float32{0., 1., 2., 3., 4.}
  25. for i := 0; i < num2; i++ {
  26. fmt.Printf("Element[%d] = %f\n", i, m[i])
  27. }
  28. // 初始化二維數組並訪問
  29. var a = [3][4]int{{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}}
  30. fmt.Printf("a[2][3]: %d\n", a[2][3])
  31. // 向函數傳遞數組
  32. var balance = []int{1000, 2, 3, 17, 50}
  33. avg := getAverage(balance, 5)
  34. fmt.Printf("平均值:%f\n", avg)
  35. }
[plain] view plain copy
  1. // 指針相關測試代碼
  2. package main
  3. import "fmt"
  4. const MAX int = 3
  5. func swap(x *int, y *int) {
  6. var temp int
  7. temp = *x
  8. *x = *y
  9. *y = temp
  10. }
  11. func main() {
  12. // 指針常規操作
  13. var a = 20
  14. var ip *int
  15. ip = &a
  16. fmt.Printf("a 變量的地址是: %x\n", &a)
  17. fmt.Printf("ip 變量儲存的指針地址: %x\n", ip)
  18. fmt.Printf("*ip 變量的值: %d\n", *ip)
  19. var ptr *int
  20. fmt.Printf("ptr 的值為 : %x\n", ptr)
  21. if ptr == nil {
  22. fmt.Printf("ptr為空指針\n")
  23. }
  24. // 指針數組
  25. b := []int{10, 100, 200}
  26. var ptr2 [MAX]*int
  27. for i := 0; i < MAX; i++ {
  28. ptr2[i] = &b[i]
  29. }
  30. for i := 0; i < MAX; i++ {
  31. fmt.Printf("b[%d] = %d\n", i, *ptr2[i])
  32. }
  33. // 指向指針的指針
  34. var pptr **int
  35. pptr = &ip
  36. fmt.Printf("指向指針的指針變量 **pptr = %d\n", **pptr)
  37. // 向函數傳遞指針參數
  38. x, y := -11, 22
  39. fmt.Printf("x = %d, y = %d\n", x, y)
  40. swap(&x, &y)
  41. fmt.Printf("x = %d, y = %d\n", x, y)
  42. }
[plain] view plain copy
  1. // 結構體相關測試代碼
  2. package main
  3. import "fmt"
  4. type Books struct {
  5. title string
  6. author string
  7. subject string
  8. book_id int
  9. }
  10. func main() {
  11. // 訪問結構體成員
  12. var Book1, Book2 Books
  13. Book1 = Books{"Go語言", "www.runoob.com", "Go語言教程", 649507}
  14. Book2.title = "Python 教程"
  15. Book2.author = "www.runoob.com"
  16. Book2.subject = "Python 語言教程"
  17. Book2.book_id = 6495700
  18. fmt.Printf("Book 1 title: %s, autor: %s, subject: %s, book_id: %d\n",
  19. Book1.title, Book1.author, Book1.subject, Book1.book_id)
  20. fmt.Printf("Book 2 title: %s, autor: %s, subject: %s, book_id: %d\n",
  21. Book2.title, Book2.author, Book2.subject, Book2.book_id)
  22. // 結構體作為函數參數
  23. printBook(Book1)
  24. printBook(Book2)
  25. // 結構體指針
  26. printBook2(&Book1)
  27. printBook2(&Book2)
  28. }
  29. func printBook(book Books) {
  30. fmt.Printf("Book 1 title: %s, autor: %s, subject: %s, book_id: %d\n",
  31. book.title, book.author, book.subject, book.book_id)
  32. }
  33. func printBook2(book *Books) {
  34. fmt.Printf("Book 1 title: %s, autor: %s, subject: %s, book_id: %d\n",
  35. book.title, book.author, book.subject, book.book_id)
  36. }
[plain] view plain copy
  1. // 切片(slice)相關測試代碼
  2. package main
  3. import "fmt"
  4. func main() {
  5. // 定義切片
  6. //var slice1 []int
  7. //slice2 := make([]int, 5)
  8. //slice3 := make([]int, 5, 10)
  9. // 切片初始化
  10. //slice4 := []int{1, 2, 3}
  11. //var arr = [5]float32{0., 1., 2., 3., 4.}
  12. //slice5 := arr[:]
  13. // len()和cap()函數
  14. var numbers = make([]int, 3, 5)
  15. printSlice(numbers)
  16. // 空(nil)切片
  17. var number2 []int
  18. printSlice(number2)
  19. // 切片截取
  20. numbers3 := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
  21. printSlice(numbers3)
  22. fmt.Println("numbers3 ==", numbers3)
  23. // 打印子切片從索引1(包含) 到索引4(不包含)
  24. fmt.Println("numbers3[1:4] ==", numbers3[1:4])
  25. // 默認下限為
  26. fmt.Println("numbers3[:3] ==", numbers3[:3])
  27. // 默認上限為 len(s)
  28. fmt.Println("numbers3[4:] ==", numbers3[4:])
  29. // 增加切片的容量
  30. var numbers4 []int
  31. printSlice(numbers4)
  32. // 允許追加空切片
  33. numbers4 = append(numbers4, 0)
  34. printSlice(numbers4)
  35. // 向切片添加一個元素
  36. numbers4 = append(numbers4, 1)
  37. printSlice(numbers4)
  38. // 同時添加多個元素
  39. numbers4 = append(numbers4, 2, 3, 4)
  40. printSlice(numbers4)
  41. // 創建切片 numbers5是之前切片的兩倍容量
  42. numbers5 := make([]int, len(numbers4), (cap(numbers4))*2)
  43. printSlice(numbers5)
  44. // 拷貝numbers4的內容到numbers5
  45. copy(numbers5, numbers4)
  46. printSlice(numbers5)
  47. }
  48. func printSlice(x []int) {
  49. fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
  50. }
[plain] view plain copy
  1. // 範圍(range)相關測試代碼
  2. package main
  3. import "fmt"
  4. func main() {
  5. // 使用range去求一個slice的和,使用數組跟這個很類似
  6. nums := []int{2, 3, 4}
  7. sum := 0
  8. for _, num := range nums {
  9. sum += num
  10. }
  11. fmt.Printf("sum: %d\n", sum)
  12. // 在數組上使用range將傳入index和值兩個變量,上面那個例子我們不需要使用該元素的序號,所以我們使用空白符"_"省略
  13. for i, num := range nums {
  14. if num == 3 {
  15. fmt.Printf("index: %d\n", i)
  16. }
  17. }
  18. // range也可以用在map的鍵值對上
  19. kvs := map[string]string{"a": "apple", "b": "banana"}
  20. for k, v := range kvs {
  21. fmt.Printf("%s -> %s\n", k, v)
  22. }
  23. // range也可以用來枚舉Unicode字符串. 第一個參數是字符的索引,第二個是字符(Unicode的值)本身
  24. for i, c := range "go" {
  25. fmt.Println(i, c)
  26. }
  27. }
[plain] view plain copy
  1. // Map(集合)相關測試代碼
  2. package main
  3. import "fmt"
  4. func main() {
  5. // 創建map
  6. var countryCapitalMap map[string]string
  7. countryCapitalMap = make(map[string]string)
  8. // map插入key-value對,各個國家對應的首都
  9. countryCapitalMap["France"] = "Paris"
  10. countryCapitalMap["Italy"] = "Rome"
  11. countryCapitalMap["Japan"] = "Tokyo"
  12. countryCapitalMap["India"] = "New Delhi"
  13. // 使用key輸出map值
  14. for country := range countryCapitalMap {
  15. fmt.Printf("Capital of %s is %s\n", country, countryCapitalMap[country])
  16. }
  17. // 查看元素在集合中是否存在
  18. captial, ok := countryCapitalMap["United States"]
  19. // 如果ok是true,則存在,否則不存在
  20. if ok {
  21. fmt.Println("Capital of United States is", captial)
  22. } else {
  23. fmt.Println("Capital of United States is not present")
  24. }
  25. // 創建map
  26. countryCapitalMap2 := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New Delhi"}
  27. fmt.Println("原始 map:")
  28. for country := range countryCapitalMap2 {
  29. fmt.Println("Capital of", country, "is", countryCapitalMap2[country])
  30. }
  31. // 刪除元素
  32. delete(countryCapitalMap2, "France")
  33. fmt.Println("刪除元素後 map:")
  34. for country := range countryCapitalMap2 {
  35. fmt.Println("Capital of", country, "is", countryCapitalMap2[country])
  36. }
  37. }
[plain] view plain copy
  1. // 遞歸相關測試代碼
  2. package main
  3. import "fmt"
  4. func Factorial(n uint64) (result uint64) {
  5. if n > 0 {
  6. result = n * Factorial(n-1)
  7. return result
  8. }
  9. return 1
  10. }
  11. func fibonacci(n int) int {
  12. if n < 2 {
  13. return n
  14. }
  15. return fibonacci(n-2) + fibonacci(n-1)
  16. }
  17. func main() {
  18. // 階乘
  19. var i = 15
  20. fmt.Printf("%d 的階乘是 %d\n", i, Factorial(uint64(i)))
  21. // 斐波那契數列
  22. for i = 0; i < 10; i++ {
  23. fmt.Printf("%d\t", fibonacci(i))
  24. }
  25. fmt.Println()
  26. }
[plain] view plain copy
  1. // 接口相關測試代碼
  2. package main
  3. import "fmt"
  4. type Phone interface {
  5. call()
  6. }
  7. type NokiaPhone struct {
  8. }
  9. func (nokiaPhone NokiaPhone) call() {
  10. fmt.Println("I am Nokia, I can call you!")
  11. }
  12. type IPhone struct {
  13. }
  14. func (iPhone IPhone) call() {
  15. fmt.Println("I am iPhone, I can call you!")
  16. }
  17. func main() {
  18. var phone Phone
  19. phone = new(NokiaPhone)
  20. phone.call()
  21. phone = new(IPhone)
  22. phone.call()
  23. }
[plain] view plain copy
  1. // 錯誤處理相關測試代碼
  2. package main
  3. import "fmt"
  4. type DivideError struct {
  5. dividee int
  6. divider int
  7. }
  8. // 實現‘error‘接口
  9. func (de *DivideError) Error() string {
  10. strFormat := `
  11. Cannot proceed, the divider is zero.
  12. dividee: %d
  13. divider: 0
  14. `
  15. return fmt.Sprintf(strFormat, de.dividee)
  16. }
  17. func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
  18. if varDivider == 0 {
  19. dData := DivideError{varDividee, varDivider}
  20. errorMsg = dData.Error()
  21. return
  22. } else {
  23. return varDividee / varDivider, ""
  24. }
  25. }
  26. func main() {
  27. // 正常情況
  28. if result, errorMsg := Divide(100, 10); errorMsg == "" {
  29. fmt.Println("100/10 = ", result)
  30. }
  31. // 當被除數為零的時候會返回錯誤信息
  32. if _, errorMsg := Divide(100, 0); errorMsg != "" {
  33. fmt.Println("errorMsg is: ", errorMsg)
  34. }
  35. }

以上內容摘自:runoob.com
GitHub: https://github.com/fengbingchun/Go_Test

Go語言基礎介紹