Go语言基础介绍
????????Go是一個開源的編程語言。Go語言被設(shè)計成一門應(yīng)用于搭載Web服務(wù)器,存儲集群或類似用途的巨型中央服務(wù)器的系統(tǒng)編程語言。目前,Go最新發(fā)布版本為1.10.
????????Go語言可以運行在Linux、FreeBSD、Mac OS X和Windows系統(tǒng)上。
????????1. 結(jié)構(gòu):Go語言的基礎(chǔ)組成有以下幾個部分:包聲明、引入包、函數(shù)、變量、語句&表達(dá)式、注釋。
????????(1)、必須在源文件中非注釋的第一行指明這個文件屬于哪個包,如:package main
????????(2)、注釋與C++相同,有單行注釋即”//”和多行注釋即”/* … */”兩種。
????????(3)、當(dāng)標(biāo)識符(包括常量、變量、類型、函數(shù)名、結(jié)構(gòu)字段等等)以一個大寫字母開頭,那么使用這種形式的標(biāo)識符的對象就可以被外部包的代碼所使用(客戶端程序需要先導(dǎo)入這個包),這被稱為導(dǎo)出;標(biāo)識符如果以小寫字母開頭,則對包外是不可見的,但是它們在整個包的內(nèi)部是可見并且可用的。
????????2.? 基礎(chǔ)語法:
????????(1)、Go標(biāo)記:Go程序可以由多個標(biāo)記組成,可以是關(guān)鍵字、標(biāo)識符、常量、字符串、字符。
????????(2)、行分隔符:在Go程序中,一行代表一個語句結(jié)束。每個語句不需要像C++語言一樣以分號”;”結(jié)尾,因為這些工作都將由Go編譯器自動完成。如果你打算將多個語句寫在同一行,它們必須使用”;”為區(qū)分,但在實際開發(fā)中我們并不鼓勵這種做法。
????????(3)、注釋:注釋不會被編譯,每一個包應(yīng)該有相關(guān)注釋。單行注釋以”//”開頭,多行注釋以”/*”開頭,以”*/”結(jié)尾,與C++相同。
????????(4)、標(biāo)識符:用來命名變量、類型等程序?qū)嶓w。一個標(biāo)識符實際上就是一個或是多個字母(A~Z和a~z)、數(shù)字(0~9)、下劃線”_”組成的序列,但是第一個字符必須是字母或下劃線而不能是數(shù)字。標(biāo)識符不能是Go語言的關(guān)鍵字。
????????(5)、關(guān)鍵字:25個關(guān)鍵字: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個預(yù)定義標(biāo)識符: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。
????????程序一般由關(guān)鍵字、常量、變量、運算符、類型和函數(shù)組成。程序中可能會使用到這些分隔符:()、[]、{}。程序中可能會使用到這些標(biāo)點符號:.、,、;、:和…。
????????3. 數(shù)據(jù)類型:在Go編程語言中,數(shù)據(jù)類型用于聲明函數(shù)和變量:布爾型(true、false);數(shù)字類型(整型、浮點型、復(fù)數(shù));字符串類型(一串固定長度的字符連接起來的字符序列);派生類型(指針類型、數(shù)組類型、結(jié)構(gòu)化類型、Channel類型、函數(shù)類型、切片類型、接口類型、Map類型)。
????????4. 變量:聲明變量的一般形式是使用var關(guān)鍵字。也可多變量聲明。
????????變量聲明方式:(1)、指定變量類型,聲明后若不賦值,使用默認(rèn)值;(2)、根據(jù)值自行判定變量類型;(3)、省略var,注意:=左側(cè)的變量不應(yīng)該是已經(jīng)聲明過的,否則會導(dǎo)致編譯錯誤。
????????值類型和引用類型:所有像int、float、bool和string這些基本類型都屬于值類型,使用這些類型的變量直接指向存在內(nèi)存中的值。你可以通過&i來獲取變量i的內(nèi)存地址。值類型的變量的值存儲在棧中。內(nèi)存地址會根據(jù)機(jī)器的不同而有所不同,甚至相同的程序在不同的機(jī)器上執(zhí)行后也會有不同的內(nèi)存地址。因為每臺機(jī)器可能有不同的存儲器布局,并且位置分配也可能不同。更復(fù)雜的數(shù)據(jù)通常會需要使用多個字,這些數(shù)據(jù)一般使用引用類型保存。一個引用類型的變量r1存儲的是r1的值所在的內(nèi)存地址(數(shù)字),或內(nèi)存地址中第一個字所在的位置。這個內(nèi)存地址稱之為指針,這個指針實際上也被存在另外的某一個字中。同一個引用類型的指針指向的多個字可以是連續(xù)的內(nèi)存地址中(內(nèi)存布局是連續(xù)的),也可以將這些字分散存放在內(nèi)存中,每個字都指示了下一個字所在的內(nèi)存地址。
????????簡短形式,使用:=賦值操作符:我們知道可以在變量的初始化時省略變量的類型而由系統(tǒng)自動推斷,聲明語句寫上var關(guān)鍵字其實是顯得多余了,因此我們可以將它們簡寫為:a:= 5 或b := false,a和b的類型(int和bool)將由編譯器自動推斷。這是使用變量的首選形式,但是它只能被用在函數(shù)體內(nèi),而不可以用于全局變量的聲明與賦值。
????????注意事項:(1)、如果在相同的代碼塊中,我們不可以再次對于相同名稱的變量使用初始化聲明。(2)、如果你聲明了一個局部變量卻沒有在相同的代碼塊中使用它,同樣會得到編譯錯誤。但是全局變量是允許聲明但不使用。同一類型的多個變量可以聲明在同一行。
????????空白標(biāo)識符_也被用于拋棄值。_實際上是一個只寫變量,你不能得到它的值。這樣做是因為Go語言中你必須使用所有被聲明的變量,但有時你并不需要使用從一個函數(shù)得到的所有返回值。
????????多個變量可以聲明在同一行,多個變量也可以在同一行進(jìn)行賦值,這被稱為并行或同時賦值。并行賦值也被用于當(dāng)一個函數(shù)返回多個返回值時。
????????5. 常量:是一個簡單值的標(biāo)識符,在程序運行時,不會被修改的量。常量中的數(shù)據(jù)類型只可以是布爾型、數(shù)字型(整數(shù)型、浮點型和復(fù)數(shù))和字符串型。
????????你可以省略類型說明符,因為編譯器可以根據(jù)變量的值來推斷其類型。也可以在同一行聲明多個常量和賦值。常量還可以用作枚舉。
????????常量可以用len()、cap()、unsafe.Sizeof()函數(shù)計算表達(dá)式的值。常量表達(dá)式中,函數(shù)必須是內(nèi)置函數(shù)。
????????iota:特殊常量,可以認(rèn)為是一個可以被編譯器修改的常量。在每一個const關(guān)鍵字出現(xiàn)時,被重置為0,然后再下一個const出現(xiàn)之前,每出現(xiàn)一次iota,其所代表的數(shù)字會自動增加1。iota可以被用作枚舉值。
????????6. 運算符:用于在程序運行時執(zhí)行數(shù)學(xué)或邏輯運算。
????????Go語言內(nèi)置的運算符有:算術(shù)運算符、關(guān)系運算符、邏輯運算符、位運算符、賦值運算符、其它運算符。
????????算術(shù)運算符:+、-、*、/、%、++、--
????????關(guān)系運算符:==、!=、>、<、>=、<=
????????邏輯運算符:&&、||、!
????????位運算符:&、|、^、<<、>>,對整數(shù)在內(nèi)存中的二進(jìn)制位進(jìn)行操作。
????????賦值運算符:=、+=、-=、*=、/=、%=、<<=、>>=、&=、^=、|=
????????其它運算符:&(獲取變量存儲地址)、*(指針變量)
????????運算符優(yōu)先級:二元運算符的運算方向均是從左至右。可以使用括號來臨時提升某個表達(dá)式的整體運算優(yōu)先級。
????????7. 條件語句:需要開發(fā)者通過指定一個或多個條件,并通過測試條件是否為true來決定是否執(zhí)行指定語句,并在條件為false的情況下執(zhí)行另外的語句。
????????if語句:由布爾表達(dá)式后緊跟一個或多個語句組成。if語句后可以使用可選的else語句。你也可以在if或else if語句中嵌入一個或多個if或else if語句。
????????switch語句:用于基于不同條件執(zhí)行不同動作,每一個case分支都是唯一的,從上到下逐一檢查,直到匹配為止。匹配項后面也不需要再加break。case類型不被局限于常量或整數(shù),但必須是相同的類型。switch語句還可以被用于type--switch來判斷某個interface變量中實際存儲的變量類型。
????????select語句:select是Go中的一個控制結(jié)構(gòu),類似于用于通信的switch語句。每個case必須是一個通信操作,要么是發(fā)送要么是接收。select隨機(jī)執(zhí)行一個可運行的case。如果沒有case可運行,它將阻塞,直到有case可運行。一個默認(rèn)的子句應(yīng)該總是可運行的。select語句的語法:(1)、每個case都必須是一個通信;(2)、所有channel表達(dá)式都會被求值;(3)、所有被發(fā)送的表達(dá)式都會被求值;(4)、如果任意某個通信可以進(jìn)行,它就執(zhí)行,其它被忽略;(5)、如果有多個case都可以運行,select會隨機(jī)公平地選出一個執(zhí)行,其它不會執(zhí)行。否則,如果有default子句,則執(zhí)行該語句。如果沒有default子句,select將阻塞,直到某個通信可以運行。Go不會重新對channel或值進(jìn)行求值。
????????8. 循環(huán)語句:for,可以嵌套一個或多個for。循環(huán)控制語句可以控制循環(huán)體內(nèi)語句的執(zhí)行過程,包括break、continue、goto。如果循環(huán)中條件語句永遠(yuǎn)不為false則會進(jìn)行無限循環(huán)。有些類似于C語言中的for和while。
????????break語句:(1)、用于循環(huán)語句中跳出循環(huán),并開始執(zhí)行循環(huán)之后的語句;(2)、在switch中在執(zhí)行一條case后跳出語句的作用。
????????continue語句:有點像break語句,但是continue不是跳出循環(huán),而是跳過當(dāng)前循環(huán)執(zhí)行下一次循環(huán)語句。
????????goto語句:可以無條件地轉(zhuǎn)移到過程中指定的行。在結(jié)構(gòu)化程序設(shè)計中一般不主張使用goto語句。
????????9. 函數(shù):是基本的代碼塊,用于執(zhí)行一個任務(wù)。Go語言最少有個main()函數(shù)。函數(shù)聲明告訴了編譯器函數(shù)的名稱、返回類型和參數(shù)。Go語言標(biāo)準(zhǔn)庫提供了多種可動用的內(nèi)置的函數(shù)。
????????函數(shù)定義格式:func function_name([parameter list]) [return_types] {函數(shù)體}
????????函數(shù)定義解析:(1)、func:函數(shù)由func開始聲明。(2)、function_name:函數(shù)名稱,函數(shù)名和參數(shù)列表一起構(gòu)成了函數(shù)簽名。(3)、parameter list:參數(shù)列表,參數(shù)就像一個占位符,當(dāng)函數(shù)被調(diào)用時,你可以將值傳遞給參數(shù),這個值被稱為實際參數(shù)。參數(shù)列表指定的是參數(shù)類型、順序、及參數(shù)個數(shù)。參數(shù)是可選的,函數(shù)也可以不包含參數(shù)。(4)、return_types:返回類型,函數(shù)返回一列值。(5)、函數(shù)體:函數(shù)定義的代碼集合。
????????Go函數(shù)可以返回多個值。
????????函數(shù)參數(shù):函數(shù)如果使用參數(shù),該變量可稱為函數(shù)的形參。形參就像定義在函數(shù)體內(nèi)的局部變量。調(diào)用函數(shù),可以通過兩種方式傳遞參數(shù):值傳遞和引用傳遞。默認(rèn)情況下,Go語言使用的是值傳遞,即在調(diào)用過程中不會影響到實際參數(shù)。
????????值傳遞:是指在調(diào)用函數(shù)時將實際參數(shù)復(fù)制一份傳遞到函數(shù)中,這樣在函數(shù)中如果對參數(shù)進(jìn)行修改,將不會影響到實際參數(shù)。
????????引用傳遞:是指在調(diào)用函數(shù)時將實際參數(shù)的地址傳遞到函數(shù)中,那么在函數(shù)中對參數(shù)所進(jìn)行的修改,將影響到實際參數(shù)。
????????函數(shù)用法:(1)、函數(shù)作為值:函數(shù)定義后可作為值來使用。(2)、閉包:是匿名函數(shù),可在動態(tài)編程中使用。匿名函數(shù)是一個”內(nèi)聯(lián)”語句或表達(dá)式。匿名函數(shù)的優(yōu)越性在于可以直接使用函數(shù)內(nèi)的變量,不必聲明。(3)、方法:是一個包含了接受者的函數(shù),接受者可以是命名類型或者結(jié)構(gòu)體類型的一個值或者是一個指針。所有給定類型的方法屬于該類型的方法集。
????????10. 變量作用域:Go語言中變量可以在三個地方聲明:局部變量、全局變量、形式參數(shù)。
????????(1)、局部變量:在函數(shù)體內(nèi)聲明的變量稱之為局部變量,它們的作用域只在函數(shù)體內(nèi),參數(shù)和返回值變量也是局部變量。
????????(2)、全局變量:在函數(shù)體外聲明的變量稱之為全局變量,全局變量可以在整個包甚至外部包(被導(dǎo)出后)使用。全局變量可以在任何函數(shù)中使用。
????????(3)、形式參數(shù):函數(shù)定義中的變量稱為形式參數(shù)。形式參數(shù)會作為函數(shù)的局部變量來使用。
????????Go語言程序中全局變量與局部變量名稱可以相同,但是函數(shù)內(nèi)的局部變量會被優(yōu)先考慮。
????????11. 數(shù)組:是具有相同唯一類型的一組已編號且長度固定的數(shù)據(jù)項序列,這種類型可以是任意的原始類型如整型、字符串或者自定義類型。數(shù)組元素可以通過索引(位置)來讀取(或者修改),索引從0開始,第一個元素索引為0,第二個索引為1,以此類推。
????????聲明數(shù)組:Go語言數(shù)組聲明需要指定元素類型及元素個數(shù)。數(shù)組長度必須是整數(shù)且大于0。
????????初始化數(shù)組:初始化數(shù)組中{}中的元素個數(shù)不能大于[]中的數(shù)字。如果忽略[]中的數(shù)字不設(shè)置數(shù)字大小,Go語言會根據(jù)元素的個數(shù)來設(shè)置數(shù)組的大小。
????????訪問數(shù)組元素:數(shù)組元素可以通過索引(位置)來讀取。格式為數(shù)組名后加中括號,中括號中為索引的值。
????????多維數(shù)組:Go語言支持多維數(shù)組。
????????向函數(shù)傳遞數(shù)組:如果你想向函數(shù)傳遞數(shù)組參數(shù),你需要在函數(shù)定義時,聲明形參為數(shù)組。
????????12. 指針:變量是一種方便的占位符,用于引用計算機(jī)內(nèi)存地址。Go語言的取地址符是&,放到一個變量前使用就會返回相應(yīng)變量的內(nèi)存地址。一個指針變量指向了一個值的內(nèi)存地址。
????????指針使用流程:定義指針變量;為指針變量賦值;訪問指針變量中指向地址的值。在指針類型前面加上*號(前綴)來獲取指針?biāo)赶虻膬?nèi)容。
????????空指針:當(dāng)一個指針被定義后沒有分配到任何變量時,它的值為nil。nil指針也為空指針。nil在概念上和其它語言的null、None、nil、NULL一樣,都指代零值或空值。
????????指針數(shù)組:可以定義一個指針數(shù)組來存儲地址。
????????指向指針的指針:如果一個指針變量存放的又是另一個指針變量的地址,則稱這個指針變量為指向指針的指針變量。訪問指向指針的指針變量值需要使用兩個*號。
????????向函數(shù)傳遞指針參數(shù):只需要在函數(shù)定義的參數(shù)上設(shè)置為指針類型即可。通過引用或地址傳參,在函數(shù)調(diào)用時可以改變其值。
????????13. 結(jié)構(gòu)體:Go語言中數(shù)組可以存儲同一類型的數(shù)據(jù),但在結(jié)構(gòu)體中我們可以為不同項定義不同的數(shù)據(jù)類型。結(jié)構(gòu)體是由一系列具有相同類型或不同類型的數(shù)據(jù)構(gòu)成的數(shù)據(jù)集合。
????????結(jié)構(gòu)體定義需要使用type和struct語句。struct語句定義一個新的數(shù)據(jù)類型,結(jié)構(gòu)體中有一個或多個成員。type語句設(shè)定了結(jié)構(gòu)體的名稱。一旦定義了結(jié)構(gòu)體類型,它就能用于變量的聲明。如果要訪問結(jié)構(gòu)體成員,需要使用點號(.)操作符。你可以像其它數(shù)據(jù)類型一樣將結(jié)構(gòu)體類型作為參數(shù)傳遞給函數(shù)。你可以定義指向結(jié)構(gòu)體的指針類似于其它指針變量。
????????14. 切片(slice):Go語言切片是對數(shù)組的抽象。Go數(shù)組的長度不可改變,Go中提供了一種靈活,功能強(qiáng)悍的內(nèi)置類型切片(“動態(tài)數(shù)組”)。與數(shù)組相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。有些類似于C++中的vector。
????????你可以聲明一個未指定大小的數(shù)組來定義切片,切片不需要說明長度,或使用make()函數(shù)來創(chuàng)建切片。
????????切片是可索引的,并且可以用len()方法獲取長度。切片提供了計算容量的方法cap()可以測量切片最長可以達(dá)到多少。一個空切片在未初始化之前默認(rèn)為nil,長度為0.可以通過設(shè)置下限及上限來設(shè)置截取切片。
????????如果想增加切片的容量,我們必須創(chuàng)建一個新的更大的切片并把原分片的內(nèi)容都拷貝過來。可使用拷貝切片的copy方法,或向切片追加新元素的append方法。
????????15. range關(guān)鍵字:Go語言中range關(guān)鍵字用于for循環(huán)中迭代數(shù)組(array)、切片(slice)、通道(channel)或集合(map)的元素。在數(shù)組和切片中它返回元素的索引值,在集合中返回key-value對的key值。
????????16. Map(集合):Map是一種無序的鍵值對的集合。Map最重要的一點是通過key來快速檢索數(shù)據(jù),key類似于索引,指向數(shù)據(jù)的值。Map是一種集合,所以我們可以像迭代數(shù)組和切片那樣迭代它。Map是無序的,我們無法決定它的返回順序,這是因為Map是使用hash表來實現(xiàn)的。
????????可以使用內(nèi)建函數(shù)make也可以使用map關(guān)鍵字來定義Map。如果不初始化map,那么就會創(chuàng)建一個nil map。nil map不能用來存放鍵值對。delete()函數(shù)用來刪除集合的元素。
????????17. 遞歸函數(shù):遞歸,就是在運行的過程中調(diào)用自己。在使用遞歸時,需要設(shè)置退出條件,否則遞歸將陷入無限循環(huán)中。
????????18. 類型轉(zhuǎn)換:用于將一種數(shù)據(jù)類型的變量轉(zhuǎn)換為另外一種類型的變量,形式為:type_name(expression)
????????19. 接口:把所有的具有共性的方法定義在一起,任何其它類型只要實現(xiàn)了這些方法就是實現(xiàn)了這個接口。
????? ? 20. 錯誤處理:Go語言通過內(nèi)置的錯誤接口提供了非常簡單的錯誤處理機(jī)制。
????? ? 以下是測試代碼:
// 變量相關(guān)測試代碼
package mainimport "fmt"// 全局變量聲明
var c float32
var x = 11func main() {// 局部變量聲明// 指定變量類型,聲明后若不賦值,使用默認(rèn)值var available boolavailable = truefmt.Println(available)// 根據(jù)值自動判定變量類型var a = 1var b = 2.5fmt.Println(a, b)c = float32(a) + float32(b)fmt.Printf("c = %f\n", c)// 省略var, 注意 :=左側(cè)的變量不應(yīng)該是已經(jīng)聲明過的,否則會導(dǎo)致編譯錯誤,這種形式只能被用在函數(shù)體中valid := false_, d := 5, 6 // 空白標(biāo)識符fmt.Println(valid, d)// 多變量聲明var enabled, disabled = true, "111"fmt.Println(enabled, disabled)// 獲取變量a的內(nèi)存地址fmt.Println(&a)// Go語言程序中全局變量與局部變量名稱可以相同,但是函數(shù)內(nèi)的局部變量會被優(yōu)先考慮var x = -11fmt.Printf("x = %d\n", x)
}
// 常量相關(guān)測試代碼
package mainimport "fmt"
import "unsafe"// 常量還可以用作枚舉
const (o = "abc"p = len(o)q = unsafe.Sizeof(o)
)// itoa: iota可以被用作枚舉值,第一個iota等于0,每當(dāng)iota在新的一行被使用時,它的值都會自動加1
const (d = iotaef
)func main() {const a string = "abc" // 顯示類型定義const b = "def" // 隱式類型定義fmt.Println(a, b)const x, y, z = 1, 0.2, "blog"fmt.Println(x, y, z)fmt.Println(o, p, q)fmt.Println(d, e, f)
}
// 運算符相關(guān)測試代碼
package mainimport "fmt"func main() {// 算術(shù)運算符var a, b, c = 1, 2, 3fmt.Printf("a + b = %d\n", a+b)fmt.Printf("a - c = %d\n", a-c)fmt.Printf("a * b = %d\n", a*b)c++ // 注:++和--好像僅有前綴運算符fmt.Printf("c++ = %d\n", c)b--fmt.Printf("--b = %d\n", b)// 關(guān)系運算符if a > b { // 注:visual studio code會默認(rèn)把if (a > b)調(diào)整為if a > bfmt.Printf("a > b\n")} else {fmt.Printf("a <= b\n")}// 邏輯運算符x, y := true, falseif x && y {fmt.Printf("true\n")} else {fmt.Printf("false\n")}// 位運算符: 好像僅支持整數(shù)a, b = 1, 3c = a & bfmt.Printf("c = %d\n", c)fmt.Printf("b << 2: %d\n", b<<2)// 賦值運算符b <<= 2fmt.Printf("b = %d\n", b)// 其它運算符:&、*fmt.Printf("b's address: %0x\n", &b)var ptr *intptr = &afmt.Printf("pointer: %0x\n", ptr)
}
// 條件語句相關(guān)測試代碼
package mainimport "fmt"func main() {// ifa := 1.2if a > 0 {fmt.Printf("a > 0, a = %f\n", a)}// if elseb := 2.5if b > 10 {fmt.Printf("b > 10\n")} else {fmt.Printf("b <= 10\n")}fmt.Printf("b = %f\n", b)// if 嵌套if a > 0 {if b > 0 {fmt.Printf("a > 0, b > 0\n")}}// switchgrade := "B"marks := 90switch marks {case 90:grade = "A"case 80:grade = "B"case 50, 60:grade = "C"default:grade = "D"}fmt.Printf("grade = %s\n", grade)// type switchvar x interface{}switch i := x.(type) {case nil:fmt.Printf(" x 的類型: %T\n", i)case int:fmt.Printf("x 是 int 型\n")case float64:fmt.Printf("x 是 float64 型\n")case func(int) float64:fmt.Printf("x 是 func(int) 型\n")case bool, string:fmt.Printf("x 是 bool 或 string 型\n")default:fmt.Printf("未知型\n")}// selectvar c1, c2, c3 chan intvar i1, i2 intselect {case i1 = <-c1:fmt.Printf("received ", i1, " from c1\n")case c2 <- i2:fmt.Printf("sent ", i2, " to c2\n")case i3, ok := (<-c3): // same as: i3, ok := <-c3if ok {fmt.Printf("received ", i3, " from c3\n")} else {fmt.Printf("c3 is closed\n")}default:fmt.Printf("no communication\n")}}
// 循環(huán)語句相關(guān)測試代碼
package mainimport "fmt"func main() {// fora, b := 0, 15fmt.Printf("a的值為: ")for a = 0; a < 10; a++ {fmt.Printf(" %d ", a)}fmt.Printf("\n")fmt.Printf("a的值為: ")for a < b {a++fmt.Printf(" %d ", a)}fmt.Printf("\n")// for嵌套、breakvar i, j intfmt.Printf("2到100之間的素數(shù)包括:")for i = 2; i < 100; i++ {for j = 2; j <= (i / j); j++ {if i%j == 0 {break}}if j > (i / j) {fmt.Printf(" %d ", i)}}fmt.Printf("\n")// continuea = 0fmt.Printf("a的奇數(shù):")for a < 20 {a++if a%2 == 0 {continue}fmt.Printf(" %d ", a)}fmt.Printf("\n")// gotoa = 0fmt.Printf("打印a的值:")
Loop:for a < 10 {if a == 5 {a++goto Loop}fmt.Printf(" %d ", a)a++}fmt.Printf("\n")
}
// 函數(shù)相關(guān)測試代碼
package mainimport ("fmt""math"
)// 函數(shù)返回兩個數(shù)的最大值,值傳遞
func max(num1, num2 int) int {var result intif num1 > num2 {result = num1} else {result = num2}return result
}// 函數(shù)支持返回多個值,值傳遞
func swap(x, y string) (string, string) {return y, x
}// Go函數(shù)不支持C++中的函數(shù)重載,引用傳遞
func swap1(x *int, y *int) {var temp inttemp = *x*x = *y*y = temp
}func getSequence() func() int {i := 0return func() int {i++return i}
}type Circle struct {radius float64
}func (c Circle) getArea() float64 {// c.radius 即為Circle類型對象中的屬性return 3.14 * c.radius * c.radius
}func main() {a, b := 100, 200var ret = max(a, b)fmt.Printf("a,b最大值為: %d\n", ret)var x, y = "hello", "beijing"fmt.Printf("x: %s, y: %s\n", x, y)m, n := swap(x, y)fmt.Printf("x: %s, y: %s\n", x, y)fmt.Printf("m: %s, n: %s\n", m, n)p, q := -100, 500fmt.Printf("p: %d, q: %d\n", p, q)swap1(&p, &q)fmt.Printf("p: %d, q: %d\n", p, q)// 函數(shù)用法:函數(shù)作為值getSquareRoot := func(x float64) float64 {return math.Sqrt(x)}fmt.Printf("square root: %f\n", getSquareRoot(9))// 函數(shù)用法:閉包nextNumber := getSequence()// 調(diào)用nextNumber函數(shù),i 變量自增 1 并返回fmt.Println("i的值: %d", nextNumber())fmt.Println("i的值: %d", nextNumber())fmt.Println("i的值: %d", nextNumber())// 創(chuàng)建新的函數(shù)nextNumber1,并查看結(jié)果nextNumber1 := getSequence()fmt.Println("i的值: %d", nextNumber1())fmt.Println("i的值: %d", nextNumber1())// 函數(shù)用法:方法var c1 Circlec1.radius = 10.00fmt.Println("Area of Circle(c1) = ", c1.getArea())
}
// 數(shù)組相關(guān)測試代碼
package mainimport "fmt"func getAverage(arr []int, size int) float32 {var avg, sum float32for i := 0; i < size; i++ {sum += float32(arr[i])}avg = sum / float32(size)return avg
}func main() {// 一維數(shù)組const num = 10var n [num]intfor i := 0; i < num; i++ {n[i] = i + 100}for j := 0; j < num; j++ {fmt.Printf("Element[%d] = %d\n", j, n[j])}// 初始化數(shù)組const num2 = 5var m = [num2]float32{0., 1., 2., 3., 4.}for i := 0; i < num2; i++ {fmt.Printf("Element[%d] = %f\n", i, m[i])}// 初始化二維數(shù)組并訪問var a = [3][4]int{{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}}fmt.Printf("a[2][3]: %d\n", a[2][3])// 向函數(shù)傳遞數(shù)組var balance = []int{1000, 2, 3, 17, 50}avg := getAverage(balance, 5)fmt.Printf("平均值:%f\n", avg)
}
// 指針相關(guān)測試代碼
package mainimport "fmt"const MAX int = 3func swap(x *int, y *int) {var temp inttemp = *x*x = *y*y = temp
}func main() {// 指針常規(guī)操作var a = 20var ip *intip = &afmt.Printf("a 變量的地址是: %x\n", &a)fmt.Printf("ip 變量儲存的指針地址: %x\n", ip)fmt.Printf("*ip 變量的值: %d\n", *ip)var ptr *intfmt.Printf("ptr 的值為 : %x\n", ptr)if ptr == nil {fmt.Printf("ptr為空指針\n")}// 指針數(shù)組b := []int{10, 100, 200}var ptr2 [MAX]*intfor i := 0; i < MAX; i++ {ptr2[i] = &b[i]}for i := 0; i < MAX; i++ {fmt.Printf("b[%d] = %d\n", i, *ptr2[i])}// 指向指針的指針var pptr **intpptr = &ipfmt.Printf("指向指針的指針變量 **pptr = %d\n", **pptr)// 向函數(shù)傳遞指針參數(shù)x, y := -11, 22fmt.Printf("x = %d, y = %d\n", x, y)swap(&x, &y)fmt.Printf("x = %d, y = %d\n", x, y)
}
// 結(jié)構(gòu)體相關(guān)測試代碼
package mainimport "fmt"type Books struct {title stringauthor stringsubject stringbook_id int
}func main() {// 訪問結(jié)構(gòu)體成員var Book1, Book2 BooksBook1 = Books{"Go語言", "www.runoob.com", "Go語言教程", 649507}Book2.title = "Python 教程"Book2.author = "www.runoob.com"Book2.subject = "Python 語言教程"Book2.book_id = 6495700fmt.Printf("Book 1 title: %s, autor: %s, subject: %s, book_id: %d\n",Book1.title, Book1.author, Book1.subject, Book1.book_id)fmt.Printf("Book 2 title: %s, autor: %s, subject: %s, book_id: %d\n",Book2.title, Book2.author, Book2.subject, Book2.book_id)// 結(jié)構(gòu)體作為函數(shù)參數(shù)printBook(Book1)printBook(Book2)// 結(jié)構(gòu)體指針printBook2(&Book1)printBook2(&Book2)
}func printBook(book Books) {fmt.Printf("Book 1 title: %s, autor: %s, subject: %s, book_id: %d\n",book.title, book.author, book.subject, book.book_id)
}func printBook2(book *Books) {fmt.Printf("Book 1 title: %s, autor: %s, subject: %s, book_id: %d\n",book.title, book.author, book.subject, book.book_id)
}
// 切片(slice)相關(guān)測試代碼
package mainimport "fmt"func main() {// 定義切片//var slice1 []int//slice2 := make([]int, 5)//slice3 := make([]int, 5, 10)// 切片初始化//slice4 := []int{1, 2, 3}//var arr = [5]float32{0., 1., 2., 3., 4.}//slice5 := arr[:]// len()和cap()函數(shù)var numbers = make([]int, 3, 5)printSlice(numbers)// 空(nil)切片var number2 []intprintSlice(number2)// 切片截取numbers3 := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}printSlice(numbers3)fmt.Println("numbers3 ==", numbers3)// 打印子切片從索引1(包含) 到索引4(不包含)fmt.Println("numbers3[1:4] ==", numbers3[1:4])// 默認(rèn)下限為fmt.Println("numbers3[:3] ==", numbers3[:3])// 默認(rèn)上限為 len(s)fmt.Println("numbers3[4:] ==", numbers3[4:])// 增加切片的容量var numbers4 []intprintSlice(numbers4)// 允許追加空切片numbers4 = append(numbers4, 0)printSlice(numbers4)// 向切片添加一個元素numbers4 = append(numbers4, 1)printSlice(numbers4)// 同時添加多個元素numbers4 = append(numbers4, 2, 3, 4)printSlice(numbers4)// 創(chuàng)建切片 numbers5是之前切片的兩倍容量numbers5 := make([]int, len(numbers4), (cap(numbers4))*2)printSlice(numbers5)// 拷貝numbers4的內(nèi)容到numbers5copy(numbers5, numbers4)printSlice(numbers5)
}func printSlice(x []int) {fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}
// 范圍(range)相關(guān)測試代碼
package mainimport "fmt"func main() {// 使用range去求一個slice的和,使用數(shù)組跟這個很類似nums := []int{2, 3, 4}sum := 0for _, num := range nums {sum += num}fmt.Printf("sum: %d\n", sum)// 在數(shù)組上使用range將傳入index和值兩個變量,上面那個例子我們不需要使用該元素的序號,所以我們使用空白符"_"省略for i, num := range nums {if num == 3 {fmt.Printf("index: %d\n", i)}}// range也可以用在map的鍵值對上kvs := map[string]string{"a": "apple", "b": "banana"}for k, v := range kvs {fmt.Printf("%s -> %s\n", k, v)}// range也可以用來枚舉Unicode字符串. 第一個參數(shù)是字符的索引,第二個是字符(Unicode的值)本身for i, c := range "go" {fmt.Println(i, c)}
}
// Map(集合)相關(guān)測試代碼
package mainimport "fmt"func main() {// 創(chuàng)建mapvar countryCapitalMap map[string]stringcountryCapitalMap = make(map[string]string)// map插入key-value對,各個國家對應(yīng)的首都countryCapitalMap["France"] = "Paris"countryCapitalMap["Italy"] = "Rome"countryCapitalMap["Japan"] = "Tokyo"countryCapitalMap["India"] = "New Delhi"// 使用key輸出map值for country := range countryCapitalMap {fmt.Printf("Capital of %s is %s\n", country, countryCapitalMap[country])}// 查看元素在集合中是否存在captial, ok := countryCapitalMap["United States"]// 如果ok是true,則存在,否則不存在if ok {fmt.Println("Capital of United States is", captial)} else {fmt.Println("Capital of United States is not present")}// 創(chuàng)建mapcountryCapitalMap2 := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New Delhi"}fmt.Println("原始 map:")for country := range countryCapitalMap2 {fmt.Println("Capital of", country, "is", countryCapitalMap2[country])}// 刪除元素delete(countryCapitalMap2, "France")fmt.Println("刪除元素后 map:")for country := range countryCapitalMap2 {fmt.Println("Capital of", country, "is", countryCapitalMap2[country])}
}
// 遞歸相關(guān)測試代碼
package mainimport "fmt"func Factorial(n uint64) (result uint64) {if n > 0 {result = n * Factorial(n-1)return result}return 1
}func fibonacci(n int) int {if n < 2 {return n}return fibonacci(n-2) + fibonacci(n-1)
}func main() {// 階乘var i = 15fmt.Printf("%d 的階乘是 %d\n", i, Factorial(uint64(i)))// 斐波那契數(shù)列for i = 0; i < 10; i++ {fmt.Printf("%d\t", fibonacci(i))}fmt.Println()
}
// 接口相關(guān)測試代碼
package mainimport "fmt"type Phone interface {call()
}type NokiaPhone struct {
}func (nokiaPhone NokiaPhone) call() {fmt.Println("I am Nokia, I can call you!")
}type IPhone struct {
}func (iPhone IPhone) call() {fmt.Println("I am iPhone, I can call you!")
}func main() {var phone Phonephone = new(NokiaPhone)phone.call()phone = new(IPhone)phone.call()
}
// 錯誤處理相關(guān)測試代碼
package mainimport "fmt"type DivideError struct {dividee intdivider int
}// 實現(xiàn)'error'接口
func (de *DivideError) Error() string {strFormat := `Cannot proceed, the divider is zero.dividee: %ddivider: 0`return fmt.Sprintf(strFormat, de.dividee)
}func Divide(varDividee int, varDivider int) (result int, errorMsg string) {if varDivider == 0 {dData := DivideError{varDividee, varDivider}errorMsg = dData.Error()return} else {return varDividee / varDivider, ""}
}func main() {// 正常情況if result, errorMsg := Divide(100, 10); errorMsg == "" {fmt.Println("100/10 = ", result)}// 當(dāng)被除數(shù)為零的時候會返回錯誤信息if _, errorMsg := Divide(100, 0); errorMsg != "" {fmt.Println("errorMsg is: ", errorMsg)}
}????? ? 以上內(nèi)容摘自:
runoob.com
????? ? GitHub:? https://github.com/fengbingchun/Go_Test?
總結(jié)
- 上一篇: 深度学习中的卷积网络简介
- 下一篇: Windows下通过Python 3.x