二:Go编程语言规范-类型
1.類型
布爾值,數(shù)值與字符串類型的實(shí)例的命名是預(yù)聲明的。 數(shù)組,結(jié)構(gòu),指針,函數(shù),接口,切片,映射和信道這些復(fù)合類型可由類型字面構(gòu)造。
每個(gè)類型?T?都有一個(gè)?基本類型:若?T?為預(yù)聲明類型或類型字面, 其相應(yīng)的基本類型為?T?本身。否則,T的基本類型為其?類型聲明中所依據(jù)類型的基本類型。
type T1 stringtype T2 T1type T3 []T1type T4 T3?
以上 string,T1 和 T2 的基本類型為 string。 []T1,T3 和 T4 的基本類型為 []T1 。
2.類型與值
注意下面說(shuō)的是類型相同
-
- 若兩個(gè)數(shù)組類型其元素類型相同且長(zhǎng)度相同,那么它們的類型相同。
- 若兩個(gè)切片類型其元素類型相同,那么它們的類型相同。
- 若兩個(gè)結(jié)構(gòu)類型其字段序列相同,相應(yīng)字段名相同,類型相同,標(biāo)注相同,那么它們的類型相同。 兩個(gè)匿名字段其名字被認(rèn)為相同。出自不同包的小寫(xiě)字段名總不相同。
- 若兩個(gè)指針類型其基礎(chǔ)類型相同,那么它們的類型相同。
- 若兩個(gè)函數(shù)類型其形參個(gè)數(shù)相同,返回值相同,相應(yīng)形參類型相同,返回值類型相同, 兩函數(shù)都可變或都不可變,那么它們的類型相同。形參和返回值名無(wú)需匹配。
- 若兩個(gè)接口類型其方法集相同,名字相同,函數(shù)類型相同,那么它們的類型相同。 出自不同包的小寫(xiě)方法名總不相同。兩接口類型是否相同與方法的次序無(wú)關(guān)。
- 若兩個(gè)映射類型其鍵值類型相同,那么它們的類型相同。
- 若兩個(gè)信道類型其值類型相同,方向相同,那么它們的類型相同。
3.可賦值性
-
- 當(dāng)?x?的類型和?T?相同時(shí)。
- 當(dāng)?x?的類型?V?和?T?有相同的?基本類型?且在?V?或?T?中至少有一個(gè)不是已命名類型時(shí)。
- 當(dāng)?T?為接口類型且?x?實(shí)現(xiàn)了?T時(shí)。
- 當(dāng)?x?為雙向信道值、T?為信道類型、?x?的類型?V?和?T?的元素類型相同且在?V?或?T?中至少有一個(gè)不是已命名類型時(shí)。
- 當(dāng)?x?為預(yù)聲明標(biāo)識(shí)符?nil?且?T?為指針、函數(shù)、切片、映射、通道或接口類型時(shí)。
- 當(dāng)?x?為無(wú)類型化,可通過(guò)類型?T?的值來(lái)表示的?常量時(shí)。
任何類型都可賦予空白標(biāo)識(shí)符.
4.布爾類型 bool
布爾類型 表示由預(yù)聲明常量 true 和 false所代表的布爾值的集。 預(yù)聲明的布爾類型為 bool。
5.數(shù)值類型 int等
uint8 所有無(wú)符號(hào) 8位整數(shù)集(0 到 255) uint16 所有無(wú)符號(hào)16位整數(shù)集(0 到 65535) uint32 所有無(wú)符號(hào)32位整數(shù)集(0 到 4294967295) uint64 所有無(wú)符號(hào)64位整數(shù)集(0 到 18446744073709551615)int8 所有帶符號(hào) 8位整數(shù)集(-128 到 127) int16 所有帶符號(hào)16位整數(shù)集(-32768 到 32767) int32 所有帶符號(hào)32位整數(shù)集(-2147483648 到 2147483647) int64 所有帶符號(hào)64位整數(shù)集(-9223372036854775808 到 9223372036854775807)float32 所有IEEE-754 32位浮點(diǎn)數(shù)集 float64 所有IEEE-754 64位浮點(diǎn)數(shù)集complex64 所有帶float32實(shí)部和虛部的復(fù)數(shù)集 complex128 所有帶float64實(shí)部和虛部的復(fù)數(shù)集byte uint8的別名 rune int32的別名除 byte 為 uint8 的別名以及 rune 為 int32 的別名外,所有數(shù)值類型都是不同的。 當(dāng)不同的數(shù)值類型混合在一個(gè)表達(dá)式或賦值操作中時(shí),必須進(jìn)行類型轉(zhuǎn)換。 例如,int32 與 int 是不同的類型, 盡管它們?cè)谔囟軜?gòu)上可能有相同的大小。
大小取決于具體實(shí)現(xiàn)的預(yù)聲明數(shù)值類型:
uint 32或64位 int 大小與uint相同 uintptr 大到足以存儲(chǔ)指針值無(wú)解釋位的無(wú)符號(hào)整數(shù)6.字符串類型 string
字符串是不可變的: 一旦被創(chuàng)建,字符串的內(nèi)容就不能更改。
字符串 s 的長(zhǎng)度(即其字節(jié)大小)可使用內(nèi)建函數(shù) len 獲取。若該字符串為常量,則其長(zhǎng)度即為編譯時(shí)常量。
字符串的字節(jié)可通過(guò)整數(shù)0 至 len(s)-1 訪問(wèn)。
獲取這樣一個(gè)元素的地址是非法的;若 s[i] 為字符串的第 i 個(gè)字節(jié),&s[i] 就是無(wú)效的。
x := "ssssssss"var str interface{} = x[0]b := str.(byte) //斷言是否是字節(jié).如果是則b為該值,如果不是則恐慌fmt.Println(b)?
7.數(shù)組類型
數(shù)組 a 的長(zhǎng)度可使用內(nèi)建函數(shù) len獲取, 其元素可通過(guò)整數(shù)下標(biāo) 0 到 len(a)-1 尋址。 數(shù)組類型總是一維的,但可組合構(gòu)成多維的類型。
[32]byte [2*N] struct { x, y int32 } [1000]*float64 [3][5]int [2][2][2]float64 // 等價(jià)于[2]([2]([2]float64)) a := [3]int{1, 2, 3} // 聲明了一個(gè)長(zhǎng)度為3的int數(shù)組 b := [10]int{1, 2, 3} // 聲明了一個(gè)長(zhǎng)度為10的int數(shù)組,其中前三個(gè)元素初始化為1、2、3,其它默認(rèn)為0 c := [...]int{4, 5, 6} // 可以省略長(zhǎng)度而采用`...`的方式,Go會(huì)自動(dòng)根據(jù)元素個(gè)數(shù)來(lái)計(jì)算長(zhǎng)度?
8.切片類型 slice
類似于數(shù)組,切片是可索引的且擁有一個(gè)長(zhǎng)度。切片 s 的長(zhǎng)度可通過(guò)內(nèi)建函數(shù) len獲取;不同于數(shù)組的是,切片可在執(zhí)行過(guò)程中被改變, 其元素可通過(guò)整數(shù)0 到 len(s)-1 尋址。 給定元素的切片下標(biāo)可能小于它在其基本數(shù)組中的下標(biāo)。
容量 是該擴(kuò)展的量度: 它是切片的長(zhǎng)度和切片往后數(shù)組的長(zhǎng)度之和;長(zhǎng)度達(dá)到其容量的切片可通過(guò)從原切片 ‘切下’一個(gè)新的來(lái)創(chuàng)建。 切片 a 的容量可使用內(nèi)建函數(shù) cap(a) 獲取。
var sli2 []int sli2 = make([]int, 20, 30)sli2[5] = 10fmt.Println(sli2)sli := make([]int, 5, 10)sli[4] = 5fmt.Println(sli)sli3 := []int{5, 2}fmt.Println(sli3)?
產(chǎn)生切片與分配數(shù)組后再對(duì)其進(jìn)行切片相同,因此這兩個(gè)例子的結(jié)果為相同的切片:
make([]int, 50, 100)new([100]int)[0:50]切片是引用的
9.結(jié)構(gòu)類型
通過(guò)有類型而無(wú)顯式字段名聲明的字段為 匿名字段,亦稱為 嵌入式 字段或該結(jié)構(gòu)中此種類型的嵌入。 這種字段類型必須作為一個(gè)類型名 T 或一個(gè)非接口類型名的指針 *T來(lái)實(shí)現(xiàn), 且 T 本身不能為指針類型。
// 帶類型為T(mén)1,*T2,P.T3和*P.T4的4個(gè)匿名字段的結(jié)構(gòu) struct {T1 // 字段名為T(mén)1*T2 // 字段名為T(mén)2P.T3 // 字段名為T(mén)3*P.T4 // 字段名為T(mén)4x, y int // 字段名為x和y }以下為非法聲明,因?yàn)樽侄蚊诮Y(jié)構(gòu)類型中必須是唯一的:
struct {T // 與匿名字段*T及*P.T相沖突*T // 與匿名字段T及*P.T相沖突*P.T // 與匿名字段T及*T相沖突 }在結(jié)構(gòu) x 中,若 x.f 為表示字段或方法 f 的合法選擇者,則匿名字段的字段或方法 f 即為已提升的。
給定結(jié)構(gòu)類型?S?與名為?T?的類型,包含在結(jié)構(gòu)方法集中的已提升方法如下:
-
- 若?S?包含一個(gè)匿名字段?T,則?S?與?*S?的方法集均包含帶接收者?T?的已提升方法。*S?的方法集也包含帶接收者?*T?的已提升方法。
- 若?S?包含匿名字段?*T,則?S?與?*S?的方法集均包含帶接收者?T?或?*T?的已提升方法。
字段聲明可后跟一個(gè)可選的字符串字面 標(biāo)注,成為所有相應(yīng)字段聲明中字段的屬性。 標(biāo)注可通過(guò) 反射接口 獲得,否則就會(huì)被忽略。
// 一個(gè)對(duì)應(yīng)于時(shí)間戳協(xié)議緩存的結(jié)構(gòu). // 標(biāo)注字符串定義了協(xié)議緩存的字段號(hào). struct {microsec uint64 "field 1"serverIP6 uint64 "field 2"process string "field 3" }10.指針類型
指針類型表示一個(gè)所有給定類型變量的指針的集,稱為指針的 基礎(chǔ)類型。 未初始化的指針的值為 nil。
x:=3y:=&x //y這時(shí)變成了指針,傳x的地址fmt.Println(y, *y) //*y該地址的值注意:上面的*y中的*在表達(dá)式中代表該指針的值,在類型定義中,則代表某類型變量的指針
type strPoint *stringfunc main() {var strP strPointi := "a"strP = &ifmt.Println(strP) }11.函數(shù)類型 func
在Go中函數(shù)也是一種變量,我們可以通過(guò)type來(lái)定義它,它的類型就是所有擁有相同的參數(shù),相同的返回值的一種類型
type typeName func(input1 inputType1 , input2 inputType2 [, ...]) (result1 resultType1 [, ...])type testInt func(int) bool // 聲明了一個(gè)函數(shù)類型 func a(integer int) bool {if integer%2 == 0 {return false}return true }func b(integer int) bool {if integer%2 == 0 {return true}return false }func filter(slice []int, f testInt) []int { // 聲明的函數(shù)類型在這個(gè)地方當(dāng)做了一個(gè)參數(shù),這里即可以傳a,也可以傳bvar result []intfor _, value := range slice {if f(value) {result = append(result, value)}}return result }?
函數(shù)當(dāng)做值和類型在我們寫(xiě)一些通用接口的時(shí)候非常有用,通過(guò)上面例子我們看到testInt這個(gè)類型是一個(gè)函數(shù)類型,然后兩個(gè)filter函數(shù)的參數(shù)和返回值與testInt類型是一樣的,但是我們可以實(shí)現(xiàn)很多種的邏輯,這樣使得我們的程序變得非常的靈活。
函數(shù)簽名中的最后一個(gè)形參可能有一個(gè)帶 ... 前綴的類型。 帶這樣形參的函數(shù)被稱為 變參函數(shù) 它可接受零個(gè)或多個(gè)實(shí)參的函數(shù)。
func() func(x int) int func(a, _ int, z float32) bool func(a, b int, z float32) (bool) func(prefix string, values ...int) func(a, b int, z float64, opt ...interface{}) (success bool) //for _, n := range arg 來(lái)循環(huán)參數(shù) func(int, int, float64) (float64, *[]int) func(n int) func(p *T)12.接口類型 interface
接口類型指定一個(gè)稱為 接口 的 方法集。 接口類型變量可存儲(chǔ)任何帶方法集類型的值,該方法集為此接口的超集。 這種類型表示 實(shí)現(xiàn)此接口。未初始化的接口類型變量的值為 nil。
空interface(interface{})不包含任何的method,正因?yàn)槿绱?#xff0c;所有的類型都實(shí)現(xiàn)了空interface。空interface對(duì)于描述起不到任何的作用(因?yàn)樗话魏蔚膍ethod),但是空interface在我們需要存儲(chǔ)任意類型的數(shù)值的時(shí)候相當(dāng)有用,因?yàn)樗梢源鎯?chǔ)任意類型的數(shù)值。
// 定義a為空接口 var a interface{} var i int = 5 s := "Hello world" // a可以存儲(chǔ)任意類型的數(shù)值 a = i a = s?
一個(gè)函數(shù)把interface{}作為參數(shù),那么他可以接受任意類型的值作為參數(shù),如果一個(gè)函數(shù)返回interface{},那么也就可以返回任意類型的值。是不是很有用啊!
13.映射類型 map
映射通過(guò)另一類型唯一的 鍵 集索引,該類型稱為鍵類型。 未初始化的映射值為 nil。
比較操作符 == 和 != 必須由鍵類型的操作數(shù)完全定義; 因此鍵類型不能是函數(shù),映射或切片。若該鍵類型為接口類型,這些比較運(yùn)算符必須由動(dòng)態(tài)鍵值定義; 失敗將導(dǎo)致一個(gè) 運(yùn)行時(shí)恐慌.
元素的數(shù)量稱為長(zhǎng)度。 對(duì)于映射 m,其長(zhǎng)度可使用內(nèi)建函數(shù) len 獲取并可在執(zhí)行時(shí)更改。元素可在執(zhí)行時(shí)使用賦值來(lái)添加并通過(guò) 下標(biāo)表達(dá)式 來(lái)檢索;它們也可通過(guò)內(nèi)建函數(shù) delete 刪除。
var numbers map[string] intnumbers = make(map[string] int) //注意是=號(hào)numbers["ss"]=5m := make(map[string]string)m["Hello"] = "Bonjour"rating := map[string]float32{"C": 5, "Go": 4.5, "Python": 4.5, "C++": 2}fmt.Println(rating)map也是一種引用類型,如果兩個(gè)map同時(shí)指向一個(gè)底層,那么一個(gè)改變,另一個(gè)也相應(yīng)的改變:
14.信道類型 chan
信道提供一種機(jī)制使兩個(gè)并發(fā)執(zhí)行的函數(shù)同步執(zhí)行,并通過(guò)傳遞具體元素類型的值來(lái)通信。 未初始化的信道值為 nil。
信道雖然使用make創(chuàng)建,但不是引用的.確保在并發(fā)過(guò)程中,各個(gè)并發(fā)的程序(返回值)能夠和父環(huán)境通信
容量根據(jù)元素的數(shù)量設(shè)置信道中緩存的大小。若容量大于零,則信道是異步的:?
若緩存未滿(發(fā)送)或非空(接收),則通信操作無(wú)阻塞成功,且元素在發(fā)送序列中被接收。?
若容量為零或無(wú),則只有當(dāng)發(fā)送者和接收者都做好準(zhǔn)備時(shí)通信才會(huì)成功。 nil 信道永遠(yuǎn)不會(huì)準(zhǔn)備好通信。
信道可通過(guò)內(nèi)建函數(shù)close關(guān)閉; 接收操作符的多值賦值形式可測(cè)試信道是否關(guān)閉。
channel通過(guò)操作符<-來(lái)接收和發(fā)送數(shù)據(jù)
ch <- v // 發(fā)送v到channel ch. v := <-ch // 從ch中接收數(shù)據(jù),并賦值給v舉個(gè)例子:
package mainimport "fmt"func sum(a []int, c chan int) {sum := 0for _, v := range a {sum += v}c <- sum // send sum to c }func main() {a := []int{7, 2, 8, -9, 4, 0}c := make(chan int)go sum(a[:len(a)/2], c)go sum(a[len(a)/2:], c)x, y := <-c, <-c // receive from c fmt.Println(x, y, x + y) }?
默認(rèn)情況下,channel接收和發(fā)送數(shù)據(jù)都是阻塞的,除非另一端已經(jīng)準(zhǔn)備好,這樣就使得Goroutines同步變的更加的簡(jiǎn)單,而不需要顯式的lock。所謂阻塞,也就是如果讀取(value := <-ch)它將會(huì)被阻塞,直到有數(shù)據(jù)接收。其次,任何發(fā)送(ch<-5)將會(huì)被阻塞,直到數(shù)據(jù)被讀出。無(wú)緩沖channel是在多個(gè)goroutine之間同步很棒的工具。
<-操作符指定信道的 方向,發(fā)送 或 接收。 若沒(méi)有給定方向,那么該信道就是 雙向的。 信道可通過(guò)類型轉(zhuǎn)換 或 賦值被強(qiáng)制為只發(fā)送或只接收。
chan T // 可以被用來(lái)發(fā)送和接收類型T的值 chan<- float64 // 只能被用來(lái)發(fā)送浮點(diǎn)數(shù) <-chan int // 只能被用來(lái)接收整數(shù)<-?操作符結(jié)合最左邊的?chan?可能的方式:
chan<- chan int // 等價(jià)于 chan<- (chan int) chan<- <-chan int // 等價(jià)于 chan<- (<-chan int) <-chan <-chan int // 等價(jià)于 <-chan (<-chan int) chan (<-chan int)轉(zhuǎn)載于:https://www.cnblogs.com/cyzsoho/p/4842349.html
總結(jié)
以上是生活随笔為你收集整理的二:Go编程语言规范-类型的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 买国寿安鑫盈360天亏了能撤回吗?
- 下一篇: 廊坊银行电子账户注销流程是什么?