golang復(fù)合類型包括:結(jié)構(gòu)體、數(shù)組、切片、Maps。
1、數(shù)組
數(shù)組
golang中的數(shù)組與C語言中的數(shù)組差異很大,倒更類似Pascal中的數(shù)組。 (Slice,下個話題,有些像C語言中的數(shù)組)
聲明ar為一個擁有三個整型數(shù)的數(shù)組,所有元素初始化為0。
大小是類型的一個組成部分。
內(nèi)置的函數(shù)len可以用于獲取數(shù)組大?。?/p>
數(shù)組是值類型
golang中的數(shù)組是值,而非C語言中的隱式指針。你可以獲得數(shù)組的地址,并生成一個指向數(shù)組的指針(例如,將其高效地傳遞給函數(shù)):
輸出結(jié)果:
[0 0 0]
數(shù)組字面值
所有的符合類型都有相同的值創(chuàng)建語法。以數(shù)組為例,其語法如下:
3個整數(shù)的數(shù)組:
10個整數(shù)的數(shù)組,前三個元素不是0:
不想數(shù)?使用…代表長度:
不想初始化所有值?使用key:value對:
指向數(shù)組字面值的指針
你可以獲取數(shù)組字面值的地址,這樣可以得到一個指向新建數(shù)組實例的指針:
輸出結(jié)果:
2、切片(Slice)
切片
切片是對數(shù)組中某一段的引用。
切片比普通數(shù)組應(yīng)用得更多也更廣泛。
切片使用的代價很低。
一個切片類型很像一個沒有大小的數(shù)組類型:
內(nèi)置的len(a)可以返回切片中元素的個數(shù)。
通過對數(shù)組或切片進(jìn)行"切片",我們可以創(chuàng)建一個新切片:
a(上面例子中的a)的有效下標(biāo)值是0和1;len(a) == 2。
切片速記
當(dāng)對數(shù)組進(jìn)行切片時,第一個下標(biāo)值默認(rèn)是0:
ar[:n]等價于a[0:n]。
第二個下標(biāo)值默認(rèn)為len(array/slice):
ar[n:]等價于ar[n:len(ar)]。
因此由數(shù)組創(chuàng)建切片時:
ar[:]等價于ar[0:len(ar)]。
切片引用數(shù)組
概念上:
數(shù)組:
切片:
創(chuàng)建切片
切片字面值看起來像沒有指定大小的數(shù)組字面值:
上面代碼創(chuàng)建了一個長度為5的數(shù)組并創(chuàng)建一個切片用于引用這個數(shù)組。
我們可以使用內(nèi)置的make函數(shù)分配一個切片(底層實際是個數(shù)組):
為何用make而不是用new?因為我們需要創(chuàng)建切片,而不僅僅是為了分配內(nèi)存。注意make([]int, 10)返回[]int,而new([]int)返回*[]int。
使用make創(chuàng)建切片、map以及channel。
切片容量
切片是對底層數(shù)組的一個引用。因此存在一些在數(shù)組里但卻沒在切片引用的范圍內(nèi)的元素。
內(nèi)置的函數(shù)cap(capacity)用于報告切片可能增長到多長。
len(a) = 2,cap(a) = 5,現(xiàn)在我們可以重新切片:
len(a)現(xiàn)在是4,而cap(a)依舊是5。
調(diào)整切片大小
切片可被當(dāng)作可增長的數(shù)組用。使用make分配一個切片,并指定其長度和容量。當(dāng)要增長時,我們可以做重新切片:
因此,sl的長度總是元素的個數(shù),但其容量可根據(jù)需要增加。
這種手法代價很小,并且是Go語言中的慣用法。
切片使用的代價很小
你可以根據(jù)需要自由地分配和調(diào)整切片大小。它們的傳遞僅需要很小的代價;不必分配。
記住它們是引用,因此下層的存儲可以被修改。
例如,I/O使用切片,而不是計數(shù):
拆分一個Buffer:
字符串也可以被切片,而且效率相似。
3、Maps
maps
Map是另外一種引用類型。它們是這樣聲明的:
對于給定map m,len(m)返回key的數(shù)量。
map的創(chuàng)建
和創(chuàng)建一個切片一樣,一個map變量是一個空引用;在可以使用它之前,應(yīng)先要向里面放入一些內(nèi)容。
三種方式:
1) 字面值:逗號分隔的key:value對列表
map索引
(接下來的幾個例子全都使用:
測試存在性
要測試一個map中是否存在某個key,我們可以使用一個多項賦值的"comma, om"形式:
var value float64
var present bool
value, present = m[x]
或者按慣例:
如果map中存在x這個key,布爾變量會被設(shè)置為true;value會被賦值為map中key對應(yīng)的值。相反,布爾變量會被設(shè)置為false,value被設(shè)置為相應(yīng)值類型的零值。
刪除
使用多元賦值可以刪除map中的一個值:
var keep bool
var value float64
var x string = f()
m[x] = v, keep
如果keep的值為true,則將v賦值到map中;如果keep為false,則刪除map中的key x。因此刪除一個key:
譯注:Go 1中上述的刪除方式已被取消,取而代之的是delete(m, x)。
for和range
對于數(shù)組、切片和map(以及我們在第三部分將要看到的更多類型),for循環(huán)提供了一種特殊的語法用于迭代訪問其中的元素。
for key, value := range m {
fmt.Printf("key %s, value %g\n", key, value)
}
只用一個變量,我們可以獲得key:
變量可以用:=賦值或聲明。
對于數(shù)組和切片來說,通過這種方式我們可以獲得元素的下標(biāo)以及元素值。
將range用于字符串
將for range用于字符串時,實際迭代的元素是Unicode碼點(code point),而不是字節(jié)(對字節(jié),可使用[]byte或使用標(biāo)準(zhǔn)的for語句)。我們假設(shè)字符串包
含使用UTF-8編碼的字符。
下面循環(huán):
輸出:0:'[' 1:'ÿ' 3:'界' 6:']'
如果遇到了錯誤的UTF-8碼點,這個字符將被設(shè)置為U+FFFD,下標(biāo)向后移動一個字節(jié)。
4、Structs
structs
對于Go中的struct,你應(yīng)該感覺十分熟悉:簡單的數(shù)據(jù)字段聲明。
更常用的是:
type Point struct {
x, y float64
}
var p Point
struct允許程序員定義內(nèi)存布局。
struct是值類型
struct是值類型,new(StructType)返回一個指向零值的指針(分配的內(nèi)存都被置0)。
對于結(jié)構(gòu)體指針,沒有->符號可用。Go提供了間接的方式。
創(chuàng)建結(jié)構(gòu)體
結(jié)構(gòu)體是值類型,因此你可只通過聲明就可以創(chuàng)建一個全0的結(jié)構(gòu)體變量。
你也可以使用new創(chuàng)建一個結(jié)構(gòu)體。
結(jié)構(gòu)體字面值語法也不出所料:
和數(shù)組一樣,得到了結(jié)構(gòu)體字面值的地址,就得到了新建結(jié)構(gòu)體的地址。
這些例子都是構(gòu)造器。
導(dǎo)出類型和字段
只有當(dāng)結(jié)構(gòu)體的字段(和方法,即將講解)名字的首字母大寫時,它才能被包外可見。
私有類型和字段:
匿名字段
在一個結(jié)構(gòu)體內(nèi),你可以聲明不帶名字的字段,比如另外一個結(jié)構(gòu)體類型。這些字段被稱為匿名字段。它們看起來就像里層的結(jié)構(gòu)體簡單插入或“嵌入”到
外層結(jié)構(gòu)體似的。
這個簡單的機(jī)制為從其他類型繼承已有的實現(xiàn)提供了一種方法。
下面是一個例子。
一個匿名結(jié)構(gòu)體字段:
type B struct {
A
bx, by float64
}
B看起來像有四個字段ax、ay、bx和by。B可看成{ax, ay int; bx, by float64}。
然后B的字面值必須提供細(xì)節(jié):
輸出1 2 3 4
匿名字段以類型作為名字
匿名字段不僅僅是簡單插入這些字段這么簡單,其含義更為豐富:B還擁有字段A。匿名字段看起來就像名字為其類型名的字段。
輸出:{1 2}。如果A來自于另外一個包,這個字段依舊被稱為A。
任意類型的匿名字段
任何具名類型或指向具名類型的指針都可以用作匿名字段。它們可以出現(xiàn)在結(jié)構(gòu)體中的任意位置。
輸出:3.5 7 hello
沖突和遮蔽
如果有兩個字段具有相同的名字(可能是一個繼承類型的名字),代碼將遵循下面規(guī)則:
1) 外層的名字遮蔽內(nèi)層的名字。這提供了一個重寫字段/方法的方式。
2) 如果在同一層次上出現(xiàn)了相同的名字,如果名字被使用,那么將是一個錯誤。(如果沒有使用,不會出現(xiàn)錯誤)
二義性是沒有規(guī)則能解決的,必須被修正。
沖突的例子
使用c.a將會出現(xiàn)錯誤。它到底是c.A.a還是c.B.a呢?
使用d.b沒有問題:它是float64類型變量,不是d.B.b。要獲得內(nèi)層的b,可用d.B.b。
標(biāo)簽:喀什 九江 湘潭 楚雄 晉城 本溪 運城 深圳
巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Go語言中的復(fù)合類型詳細(xì)介紹》,本文關(guān)鍵詞 語言,中的,復(fù)合,類型,詳細(xì),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。