一、Go基礎(chǔ)
標(biāo)識(shí)符:
go語(yǔ)言中的標(biāo)識(shí)符由字母數(shù)字和下劃線(_)組成,并且只能以字母和下劃線(_)開(kāi)頭
關(guān)鍵字:
關(guān)鍵字是指編程語(yǔ)言中預(yù)先定義好的具有特殊含義的標(biāo)識(shí)符。關(guān)鍵字和保留字都不建議用作變量名。
Go語(yǔ)言有25個(gè)關(guān)鍵字:
關(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 ??????????????????? ? ??? returm ??????????????????? ?? ???? ? ? ?? var
Go語(yǔ)言有37個(gè)保留字:
類(lèi)型??? 包含保留字
Constants????? true ?false ?iota ?nil
Typesint ? ? ? ? int8 ?int16 ?int32 ?int64 ?uint ?uint8 ?uint16 ?uint32 ?uint64 ?uintptr ?float32 ?float64 ?complex128 ?complex64 bool ????????????? ? ? ??? byte ?rune ?string ?error
Functions?????? make ?len ?cap ?new ?append ?copy ?close ?delete complex ?real ?imag panic ?recover
1、變量聲明
1.變量的來(lái)歷
程序運(yùn)行過(guò)程中的數(shù)據(jù)都是保存在內(nèi)存中的,我們想要在代碼中操作某個(gè)數(shù)據(jù)時(shí)就要去內(nèi)存上找到這個(gè)變量,但是如果我們直接在代碼中通過(guò)內(nèi)存地址去操作變量的話,代碼的可讀性會(huì)非常差而且還容易出錯(cuò),所以我們就利用變量將這個(gè)數(shù)據(jù)的內(nèi)存地址保存起來(lái),以后直接通過(guò)這個(gè)變量就能在找到內(nèi)存上對(duì)應(yīng)的數(shù)據(jù)了。
2.變量類(lèi)型
變量(Variable)的功能是存儲(chǔ)數(shù)據(jù)。不同的變量保存數(shù)據(jù)類(lèi)型可能會(huì)不一樣。經(jīng)過(guò)半個(gè)多世紀(jì)的發(fā)展,編程語(yǔ)言已經(jīng)基本形成了一套固定的類(lèi)型,常見(jiàn)的變量的數(shù)據(jù)類(lèi)型有:整形、浮點(diǎn)型、布爾型等。
Go語(yǔ)言中的每一個(gè)變量都有自己的類(lèi)型,并且變量必須經(jīng)過(guò)聲明才能開(kāi)始使用。
3.變量的聲明
Go語(yǔ)言中的變量需要聲明后才能使用,同一作用域內(nèi)不支持重復(fù)聲明。并且Go語(yǔ)言的變量聲明后必須使用。
·標(biāo)準(zhǔn)聲明
Go語(yǔ)言的變量聲明格式為:
var?變量名?變量類(lèi)型
變量聲明以關(guān)鍵字var開(kāi)頭,變量類(lèi)型放在變量的后面,行尾無(wú)需分號(hào)。
var?name?string
var?age?int
var?isOK?bool
·批量聲明
每聲明一個(gè)變量就需要寫(xiě)var關(guān)鍵字會(huì)比較繁瑣,go語(yǔ)言中還支持批量變量的聲明
var(
a?string
????b?int
????c?bool
????d?float32
)
·變量的初始化
Go語(yǔ)言在聲明變量的時(shí)候,會(huì)自動(dòng)對(duì)變量對(duì)應(yīng)的內(nèi)存區(qū)域進(jìn)行初始劃操作。每個(gè)變量會(huì)被初始化成其類(lèi)型的默認(rèn)值,例如:整形和浮點(diǎn)類(lèi)型變量的默認(rèn)值為0。字符串變量的默認(rèn)值為空字符串。布爾類(lèi)型莫認(rèn)為false。切片、函數(shù)、指針變量默認(rèn)為nil。也可以在聲明變量的時(shí)候?yàn)槠渲付ǔ跏贾?。變量初始化的?biāo)準(zhǔn)格式如下:
var?變量名?類(lèi)型?=?表達(dá)式
//?例
var?username?string?=?"eric"
var?age?int?=?18
也能一次初始化多個(gè)變量
var?name,?age?=?"eric",?18
·類(lèi)型推導(dǎo)
有時(shí)候我們會(huì)將變量的類(lèi)型省略,這個(gè)時(shí)候編譯器會(huì)根據(jù)等號(hào)右邊的值來(lái)推導(dǎo)變量的類(lèi)型完成初始化。
var?name?=?"eric"
var?age?=?18
·短變量聲明
在函數(shù)內(nèi)部,可以使用跟簡(jiǎn)略的:=方式聲明并初始化變量。
package?main
import?("fmt")
//?全局變量m
var?m?=?100
func?main(){
????n?:=?10
????m?:=?200??//此處聲明局部變量m
????fmt.PrintLn(m,n)
}
·匿名變量
在使用多重賦值的時(shí)候,如果想要忽略某個(gè)值,可以使用匿名變量(anonymous variable)。匿名變量用一個(gè)下劃線_表示,例如:
func?foo()?(int,?string){
????return?18,?"eric"
}
func?main()?{
????x,_?:=?foo()
????_,y?:=?foo()
????fmt.Println("x=",?x)
????fmt.Println("y=",?y)
}
匿名變量不占命名空間,不會(huì)分配內(nèi)存,所以匿名變量之間不存在重復(fù)聲明。(在Lua等變編程語(yǔ)言里,匿名變量也被叫做啞圓變量。)
注意事項(xiàng):
1. 函數(shù)外的每個(gè)語(yǔ)句都必須以關(guān)鍵字開(kāi)始(var、const、func等)
2. :=不能使用在函數(shù)外。
3. _多用于占位,表示忽略值。
4. go語(yǔ)言中變量聲明必須使用,不適用就編譯不過(guò)去
5. 同一個(gè)作用域({})中不能重復(fù)聲明同名的變量
2、常量
相對(duì)于變量,常量是恒定不變的值,多用于定義程序運(yùn)行期間不會(huì)改變的那些值。常量的聲明和變量的聲明非常類(lèi)似,只是把var換成了const,常量在定義的時(shí)候必須賦值。
const?pi?=?3.14159275453
const?e?=?2.7182
聲明了pi e 這兩個(gè)常量之后,在整個(gè)程序運(yùn)行期間他們的值都不能再發(fā)生變化了。多個(gè)常量也可以一起聲明:
const(
pi?=?3.14159275453
????e?=?2.7182
)
const同時(shí)聲明多個(gè)常量時(shí),如果省略了值則表示和上面一行的值相同。例如:
const(
n1?=?100
????n2
????n3
)
//?n1,n2,n3的值都是100
3、iota
使用_跳過(guò)某些值
const(
n1?=?iote?//?第一次默認(rèn)為0
????n2????????//?1
????_
????n4????????//3
)
iota聲明中間插隊(duì)
const(
n1?=?iota?//?0
????n2?=?100??//?100
????n3?=?iota?//?2
????n4????????//?3
)
const?n5?=?iota?//?0
定義數(shù)量級(jí)(這里的<<表示左移操作,1<<10表示將1的二進(jìn)制向左移10位,也就是由1變成了10000000000,也就是十進(jìn)制的1024。同理2<<2表示將2的二進(jìn)制向左移2位,也就是由10變成了1000,也就是十進(jìn)制的8。)
const(
_?=?iota
????KB?=?1<<(10*iota)
????MB?=?1<<(10*iota)
????GB?=?1<<(10*iota)
????TB?=?1<<(10*iota)
????PB?=?1<<(10*iota)
)
多個(gè)iota定義在一行
const(
a,?b?=?iota?+?1,?iota?+?2??//?1,2
????c,?d???????????????????????//?2,3
????e,?f???????????????????????//?3,4
)
二、Go的基本數(shù)據(jù)類(lèi)型
Go語(yǔ)言中有豐富的數(shù)據(jù)類(lèi)型,除了基本的整形、浮點(diǎn)型、布爾型、字符串外,還有數(shù)組、切片、結(jié)構(gòu)體、函數(shù)、map、通道(channel)等。Go語(yǔ)言的基本數(shù)據(jù)類(lèi)型和其它語(yǔ)言大同小異。
1、整形
基本整形
整形分為以下兩個(gè)大類(lèi):
??? ·按長(zhǎng)度分為:int8、int16、int32、int64
??? ·對(duì)應(yīng)的無(wú)符號(hào)整形:uint8、uint16、uint32、uint64
其中,uint8是我們常用和熟知的byte型,int16對(duì)應(yīng)C語(yǔ)言中的shot型(C:短整型),int64對(duì)應(yīng)C語(yǔ)言中的long型(C:長(zhǎng)整型)。
類(lèi)型??????? 描述
uint8無(wú)符號(hào) 8位整型 (0 到 255)
uint16無(wú)符號(hào) 16位整型 (0 到 65535)
uint32無(wú)符號(hào) 32位整型 (0 到 4294967295)
uint64無(wú)符號(hào) 64位整型 (0 到 18446744073709551615)
int8有符號(hào) 8位整型 (-128 到 127)
int16有符號(hào) 16位整型 (-32768 到 32767)
int32有符號(hào) 32位整型 (-2147483648 到 2147483647)
int64有符號(hào) 64位整型 (-9223372036854775808 到 9223372036854775807)
特殊整形
類(lèi)型??????? 描述
uint32位操作系統(tǒng)上就是uint32,64位操作系統(tǒng)上就是uint64
int32位操作系統(tǒng)上就是int32,64位操作系統(tǒng)上就是int64
uintptr無(wú)符號(hào)整型,用于存放一個(gè)指針
注意: 在使用int和 uint類(lèi)型時(shí),不能假定它是32位或64位的整型,而是考慮int和uint可能在不同平臺(tái)上的差異。
注意事項(xiàng):獲取對(duì)象的長(zhǎng)度的內(nèi)建len()函數(shù)返回值的長(zhǎng)度可以根據(jù)不同平臺(tái)的字節(jié)長(zhǎng)度進(jìn)行變化。實(shí)際使用中,切片或map的元素?cái)?shù)量等都可以用int來(lái)表示。在涉及到二進(jìn)制傳輸、讀寫(xiě)文件的結(jié)構(gòu)描述時(shí),為了保持文件的結(jié)構(gòu)不會(huì)受到不同編譯目標(biāo)平臺(tái)的字節(jié)長(zhǎng)度影響,不要使用int和uint。
數(shù)字字面量語(yǔ)法(Number literals syntax)
Go1.13版本之后引入了數(shù)字字面量語(yǔ)法,這樣便于開(kāi)發(fā)者以二進(jìn)制、八進(jìn)制或十六進(jìn)制浮點(diǎn)數(shù)的格式定義數(shù)字,例如:v:=0b001101101,代表二進(jìn)制的101101,相當(dāng)于十進(jìn)制的45。v:=0o377,代表八進(jìn)制的377,相當(dāng)于十進(jìn)制的255。v:=0x1p-2,代表十六進(jìn)制的1除以22,也就是0.25。
package?main
import?"fmt"
func?main(){
//?十進(jìn)制
var?a?int?=?10
fmt.Printf("%d?\n",?a)??//?10
fmt.Printf("%b?\n",?a)??//?1010??占位符%b表示二進(jìn)制
//?八進(jìn)制??以0開(kāi)頭
var?b?int?=?077
fmt.Printf("%o?\n",?b)??//?77
//?十六進(jìn)制??以0x開(kāi)頭
var?c?int?=?0xff
fmt.Printf("%x?\n",?c)??//?ff
fmt.Printf("%X?\n",?c)??//?FF
}
2、浮點(diǎn)型
Go語(yǔ)言中有兩種浮點(diǎn)型數(shù):float32和float64。這兩種浮點(diǎn)型數(shù)據(jù)格式遵循IEEE 754標(biāo)準(zhǔn):flaot32的浮點(diǎn)最大范圍約為1.8e308,可以使用一個(gè)常量定義:mathMaxFloat64。
打印浮點(diǎn)數(shù)時(shí),可以使用fmt包配合動(dòng)詞%f,代碼示例:
package?main
import?(
????"fmt"
????"math"
)
func?main()?{
????fmt.Printf("%f\n",?math.Pi)
????fmt.Printf("%.2f\n",?math.Pi)
????//?浮點(diǎn)數(shù)
asd?:=?3.1415926
fmt.Printf("%T\n",?asd)?//?默認(rèn)Go語(yǔ)言中的小鼠都是float64類(lèi)型
asf?:=?float32(3.14159)
fmt.Printf("%T\n",?asf)?//?顯示聲明float32類(lèi)型
//?asd?=?asf??//?float32類(lèi)型的值不能直接賦值給float64,反之還真不能
}
3、復(fù)數(shù)
兩種數(shù)據(jù)類(lèi)型complate64和complate128
package?main
import?(
????"fmt"
????"math"
)
func?main()?{
????var?c1?complex64
????c1?=?1?+?2i
????var?c2?complex128
????c2?=?2?+?3i
????fmt.Println(c1)
????fmt.Println(c2)
}
4、布爾值
Go語(yǔ)言中以bool類(lèi)型進(jìn)行聲明布爾類(lèi)型數(shù)據(jù),布爾類(lèi)型數(shù)據(jù)只有true(真)和falde(假)兩個(gè)值。
注意:
1.布爾類(lèi)型變量的默認(rèn)值為false。
2.Go語(yǔ)言中不允許將整形強(qiáng)制轉(zhuǎn)換為布爾型。
3.布爾型無(wú)法參予數(shù)值運(yùn)算,也無(wú)法與其它類(lèi)型進(jìn)行轉(zhuǎn)換。
5、字符串
Go語(yǔ)言中的字符串以原生數(shù)據(jù)類(lèi)型出現(xiàn),使用字符串就像使用其他原生數(shù)據(jù)類(lèi)型(int、bool、float32、float64等)一樣。Go語(yǔ)言里的字符串的內(nèi)部實(shí)現(xiàn)使用UTF-8編碼。字符串的值為雙引號(hào)(")中的內(nèi)容,可以在Go語(yǔ)言的源碼中直接添加非ASCII碼字符,例如:
s1?:=?"hello"
s2?:=?"你好"
字符串轉(zhuǎn)義符
Go語(yǔ)言的字符串常見(jiàn)轉(zhuǎn)義符包含回車(chē)、換行、單雙引號(hào)、制表符等,如下表格所示。
轉(zhuǎn)義符?????????????????????????????????????????????????????? 含義
\r??????????????????????????????????????????????????????? 回車(chē)符(返回行首)
\n???????????????????????????????????????????? 換行符(直接跳到下一行的同列位置)
\t?????????????????????????????????????????????????????????????????? 制表符
\'??????????????????????????????????????????????????????????????????? 單引號(hào)
\"??????????????????????????????????????????????????????????????????? 雙引號(hào)
\\??????????????????????????????????????????????????????????????????? 反斜杠
舉個(gè)例子,我們要打印一個(gè)Windows平臺(tái)下的一個(gè)文件路徑:
package?main
import?(
????"fmt"
)
func?main()?{
????fmt.Println("str?:=?\"c:\\User\\AppDate\\.go\"")
}
多行字符串
Go語(yǔ)言中要定義一個(gè)多行字符串時(shí),就必須使用反引號(hào)字符:
package?main
import?(
????"fmt"
)
func?main()?{
asd?:=?`第一行
第二行
第三行`
fmt.Println(asd)
}
反引號(hào)間換行將被作為字符串中的換行,但是所有的轉(zhuǎn)義字符均無(wú)效,文本將會(huì)原樣輸出。
字符串的常用操作
方法?????????????????????????????????????????????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 介紹
len(str)?????????????????????????????????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ?????? 求長(zhǎng)度
+或fmt.Sprintf???????????????????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????? 拼接字符串
strings.Spli?????????????????????????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????????? 分割
strings.contains?????????????????????????????????????????????????????????????????????????????????? 判斷是否包含
strings.HasPrefix,strings.HasSuffix??????????????????????????????????????????????????? 前綴/后綴判斷
strings.Index(),strings.LastIndex()??????????????????????????????????????????????????? 子串出現(xiàn)的位置
strings.Join(a[]string, sep string)???????????????????????????????????????????????????????????? join操作