校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃

主頁 > 知識庫 > Go語言中的復合類型詳細介紹

Go語言中的復合類型詳細介紹

熱門標簽:外呼系統多少錢一年 經常接到推銷電話機器人的電話 海外照相館地圖標注入駐 外呼系統如何接收服務密碼 滁州自建外呼系統 客服級電銷機器人 智能營銷軟件 工商信用卡外呼系統教程 旅游廁所如何電子地圖標注

golang復合類型包括:結構體、數組、切片、Maps。

1、數組

數組

golang中的數組與C語言中的數組差異很大,倒更類似Pascal中的數組。 (Slice,下個話題,有些像C語言中的數組)

復制代碼 代碼如下:

var ar [3]int

聲明ar為一個擁有三個整型數的數組,所有元素初始化為0。

大小是類型的一個組成部分。

內置的函數len可以用于獲取數組大小:

復制代碼 代碼如下:

len(ar) = 3

數組是值類型

golang中的數組是值,而非C語言中的隱式指針。你可以獲得數組的地址,并生成一個指向數組的指針(例如,將其高效地傳遞給函數):

復制代碼 代碼如下:

func f(a [3]int) { fmt.Println(a) }  
func fp(a *[3]int) { fmt.Println(a) }  
 
func main() {  
    var ar [3] int 
    f(ar) // 傳遞一個ar的拷貝  
    fp(ar) // 傳遞一個指向ar的指針  

輸出結果:

復制代碼 代碼如下:

[0 0 0]

[0 0 0]

數組字面值

所有的符合類型都有相同的值創建語法。以數組為例,其語法如下:

3個整數的數組:

復制代碼 代碼如下:

[3]int{1, 2, 3}

10個整數的數組,前三個元素不是0:

復制代碼 代碼如下:

[10]int{ 1, 2, 3}

不想數?使用…代表長度:

復制代碼 代碼如下:

[...]int{1, 2, 3}

不想初始化所有值?使用key:value對:

復制代碼 代碼如下:

[10]int{2:1, 3:1, 5:1, 7:1}

指向數組字面值的指針

你可以獲取數組字面值的地址,這樣可以得到一個指向新建數組實例的指針:

復制代碼 代碼如下:

func fp(a *[3]int) { fmt.Println(a) }  
func main() {  
    for i := 0; i 3; i++ {  
        fp([3]int{i, i*i, i*i*i})  
    }  

輸出結果:

復制代碼 代碼如下:

[0 0 0]
[1 1 1]
[2 4 8]

2、切片(Slice)

切片

切片是對數組中某一段的引用。

切片比普通數組應用得更多也更廣泛。

切片使用的代價很低。

一個切片類型很像一個沒有大小的數組類型:

復制代碼 代碼如下:

var a []int

內置的len(a)可以返回切片中元素的個數。

通過對數組或切片進行"切片",我們可以創建一個新切片:

復制代碼 代碼如下:

a = ar[7:9]

a(上面例子中的a)的有效下標值是0和1;len(a) == 2。

切片速記

當對數組進行切片時,第一個下標值默認是0:

ar[:n]等價于a[0:n]。

第二個下標值默認為len(array/slice):

ar[n:]等價于ar[n:len(ar)]。

因此由數組創建切片時:

ar[:]等價于ar[0:len(ar)]。

切片引用數組

概念上:

復制代碼 代碼如下:

type Slice struct {
base *elemType // 指向0th元素的指針
len int // 切片中元素的數量
cap int // 切片可以容納元素的數量
}

數組:

復制代碼 代碼如下:

ar: 7 1 5 4 3 8 7 2 11 5 3

切片:

復制代碼 代碼如下:

a = ar[7:9] :base = ar[7](指向ar中的2) len = 2 cap = 4

創建切片

切片字面值看起來像沒有指定大小的數組字面值:

復制代碼 代碼如下:

var slice = []int{1,2,3,4,5}

上面代碼創建了一個長度為5的數組并創建一個切片用于引用這個數組。

我們可以使用內置的make函數分配一個切片(底層實際是個數組):

復制代碼 代碼如下:

var s100 = make([]int, 100) // slice: 100 ints

為何用make而不是用new?因為我們需要創建切片,而不僅僅是為了分配內存。注意make([]int, 10)返回[]int,而new([]int)返回*[]int。

使用make創建切片、map以及channel。

切片容量

切片是對底層數組的一個引用。因此存在一些在數組里但卻沒在切片引用的范圍內的元素。

內置的函數cap(capacity)用于報告切片可能增長到多長。

復制代碼 代碼如下:

var ar = [10]int{0,1,2,3,4,5,6,7,8,9}
var a = ar[5:7] // 引用子數組{5,6}

len(a) = 2,cap(a) = 5,現在我們可以重新切片:

復制代碼 代碼如下:

a = a[0:4] // 引用子數組 {5,6,7,8}

len(a)現在是4,而cap(a)依舊是5。

調整切片大小

切片可被當作可增長的數組用。使用make分配一個切片,并指定其長度和容量。當要增長時,我們可以做重新切片:

復制代碼 代碼如下:

var sl = make([]int, 0, 100) // 長度 0, 容量 100  
func appendToSlice(i int, sl []int) []int {  
    if len(sl) == cap(sl) { error(…) }  
    n := len(sl)  
    sl = sl[0:n+1] // 長度增加1  
    sl[n] = i  
    return sl  
}

因此,sl的長度總是元素的個數,但其容量可根據需要增加。

這種手法代價很小,并且是Go語言中的慣用法。

切片使用的代價很小

你可以根據需要自由地分配和調整切片大小。它們的傳遞僅需要很小的代價;不必分配。

記住它們是引用,因此下層的存儲可以被修改。

例如,I/O使用切片,而不是計數:

復制代碼 代碼如下:

func Read(fd int, b []byte) int 
var buffer [100]byte  
    for i := 0; i 100; i++ {  
    // 每次向Buffer中填充一個字節  
    Read(fd, buffer[i:i+1]) // no allocation here  

拆分一個Buffer:

復制代碼 代碼如下:

header, data := buf[:n], buf[n:]

字符串也可以被切片,而且效率相似。

3、Maps

maps

Map是另外一種引用類型。它們是這樣聲明的:

復制代碼 代碼如下:

var m map[string]float64

這里聲明了一個map,索引key的類型為string,值類型為float64。這類似于C++中的類型*mapstring, float64>。

對于給定map m,len(m)返回key的數量。

map的創建

和創建一個切片一樣,一個map變量是一個空引用;在可以使用它之前,應先要向里面放入一些內容。

三種方式:

1) 字面值:逗號分隔的key:value對列表

復制代碼 代碼如下:

m = map[string]float64{"1":1, "pi":3.1415}

2) 創建
復制代碼 代碼如下:

m = make(map[string]float64) // make not new

3) 賦值
復制代碼 代碼如下:

var m1 map[string]float64
m1 = m // m1和m現在引用相同的map

map索引

(接下來的幾個例子全都使用:

復制代碼 代碼如下:

m = map[string]float64{"1":1, "pi":3.1415})

訪問一個元素;如果該元素不存在,則得到對應map value類型的零值:
復制代碼 代碼如下:

one := m["1"]
zero := m["not present"] // zero被置為0.0.

設置一個元素的值(兩次設置將更新為最新值)
復制代碼 代碼如下:

m["2"] = 2
m["2"] = 3 // 思維混亂

測試存在性

要測試一個map中是否存在某個key,我們可以使用一個多項賦值的"comma, om"形式:

復制代碼 代碼如下:

m = map[string]float64{"1":1, "pi":3.1415}

var value float64
var present bool

value, present = m[x]

或者按慣例:

復制代碼 代碼如下:

value, ok := m[x] // "comma ok" 形式

如果map中存在x這個key,布爾變量會被設置為true;value會被賦值為map中key對應的值。相反,布爾變量會被設置為false,value被設置為相應值類型的零值。

刪除

使用多元賦值可以刪除map中的一個值:

復制代碼 代碼如下:

m = map[string]float64{"1":1.0, "pi":3.1415}

var keep bool
var value float64
var x string = f()

m[x] = v, keep

如果keep的值為true,則將v賦值到map中;如果keep為false,則刪除map中的key x。因此刪除一個key:

復制代碼 代碼如下:

m[x] = 0, false // 從map中刪除x

譯注:Go 1中上述的刪除方式已被取消,取而代之的是delete(m, x)。

for和range

對于數組、切片和map(以及我們在第三部分將要看到的更多類型),for循環提供了一種特殊的語法用于迭代訪問其中的元素。

復制代碼 代碼如下:

m := map[string]float64{"1":1.0, "pi":3.1415}

for key, value := range m {
fmt.Printf("key %s, value %g\n", key, value)
}

只用一個變量,我們可以獲得key:

復制代碼 代碼如下:

for key = range m {
fmt.Printf("key %s\n", key)
}

變量可以用:=賦值或聲明。

對于數組和切片來說,通過這種方式我們可以獲得元素的下標以及元素值。

將range用于字符串

將for range用于字符串時,實際迭代的元素是Unicode碼點(code point),而不是字節(對字節,可使用[]byte或使用標準的for語句)。我們假設字符串包

含使用UTF-8編碼的字符。

下面循環:

復制代碼 代碼如下:

s := "[\u00ff\u754c]"
for i, c := range s {
fmt.Printf("%d:%q ", i, c) // %q for 'quoted'
}

輸出:0:'[' 1:'ÿ' 3:'界' 6:']'

如果遇到了錯誤的UTF-8碼點,這個字符將被設置為U+FFFD,下標向后移動一個字節。

4、Structs

structs

對于Go中的struct,你應該感覺十分熟悉:簡單的數據字段聲明。

復制代碼 代碼如下:

var p struct {
x, y float64
}

更常用的是:

復制代碼 代碼如下:

type Point struct {
x, y float64
}
var p Point

struct允許程序員定義內存布局。

struct是值類型

struct是值類型,new(StructType)返回一個指向零值的指針(分配的內存都被置0)。

復制代碼 代碼如下:

type Point struct {
x, y float64
}
var p Point
p.x = 7
p.y = 23.4
var pp *Point = new(Point)
*pp = p
pp.x = Pi // (*pp).x的語法糖

對于結構體指針,沒有->符號可用。Go提供了間接的方式。

創建結構體

結構體是值類型,因此你可只通過聲明就可以創建一個全0的結構體變量。

你也可以使用new創建一個結構體。

復制代碼 代碼如下:

var p Point // 零值
pp := new(Point) // 慣用法

結構體字面值語法也不出所料:

復制代碼 代碼如下:

p = Point{7.2, 8.4}
p = Point{y:8.4, x:7.2}
pp = Point{7.2, 8.4} // 慣用法
pp = Point{} //也是慣用法,== new(Point)

和數組一樣,得到了結構體字面值的地址,就得到了新建結構體的地址。

這些例子都是構造器。

導出類型和字段

只有當結構體的字段(和方法,即將講解)名字的首字母大寫時,它才能被包外可見。

私有類型和字段:

復制代碼 代碼如下:

type point struct { x, y float64 }

導出類型和字段:
復制代碼 代碼如下:

type Point struct { X, Y float64 }

導出類型和私有類型混合字段:
復制代碼 代碼如下:

type Point struct {
X, Y float64 // exported
name string // not exported
}

你甚至可以創建一個帶有導出字段的私有類型。(練習:何時能派上用場呢?)

匿名字段

在一個結構體內,你可以聲明不帶名字的字段,比如另外一個結構體類型。這些字段被稱為匿名字段。它們看起來就像里層的結構體簡單插入或“嵌入”到

外層結構體似的。

這個簡單的機制為從其他類型繼承已有的實現提供了一種方法。

下面是一個例子。

一個匿名結構體字段:

復制代碼 代碼如下:

type A struct {
ax, ay int
}

type B struct {
A
bx, by float64
}

B看起來像有四個字段ax、ay、bx和by。B可看成{ax, ay int; bx, by float64}。

然后B的字面值必須提供細節:

復制代碼 代碼如下:

b := B{A{1, 2}, 3.0, 4.0}
fmt.Println(b.ax, b.ay, b.bx, b.by)

輸出1 2 3 4

匿名字段以類型作為名字

匿名字段不僅僅是簡單插入這些字段這么簡單,其含義更為豐富:B還擁有字段A。匿名字段看起來就像名字為其類型名的字段。

復制代碼 代碼如下:

b := B{A{ 1, 2}, 3.0, 4.0}
fmt.Println(b.A)

輸出:{1 2}。如果A來自于另外一個包,這個字段依舊被稱為A。

復制代碼 代碼如下:

import "pkg"
type C struct { pkg.A }

c := C {pkg.A{1, 2}}
fmt.Println(c.A) // 不是 c.pkg.A

任意類型的匿名字段

任何具名類型或指向具名類型的指針都可以用作匿名字段。它們可以出現在結構體中的任意位置。

復制代碼 代碼如下:

type C struct {
x float64
int
string
}
c := C{3.5, 7, "hello"}
fmt.Println(c.x, c.int, c.string)

輸出:3.5 7 hello

沖突和遮蔽

如果有兩個字段具有相同的名字(可能是一個繼承類型的名字),代碼將遵循下面規則:

1) 外層的名字遮蔽內層的名字。這提供了一個重寫字段/方法的方式。
2) 如果在同一層次上出現了相同的名字,如果名字被使用,那么將是一個錯誤。(如果沒有使用,不會出現錯誤)

二義性是沒有規則能解決的,必須被修正。

沖突的例子

復制代碼 代碼如下:

type A struct { a int }
type B struct { a, b int }
type C struct { A; B }
var c C

使用c.a將會出現錯誤。它到底是c.A.a還是c.B.a呢?

復制代碼 代碼如下:

type D struct { B; b float64 }
var d D

使用d.b沒有問題:它是float64類型變量,不是d.B.b。要獲得內層的b,可用d.B.b。

您可能感興趣的文章:
  • GO語言基本類型分析
  • GO語言類型轉換和類型斷言實例分析
  • Go語言基礎知識總結(語法、變量、數值類型、表達式、控制結構等)
  • GO語言基本數據類型總結
  • Go語言的方法接受者類型用值類型還是指針類型?
  • 為什么Go語言把類型聲明放在后面?
  • Go語言基本的語法和內置數據類型初探
  • Go語言中如何通過方法為類型添加行為

標簽:喀什 九江 湘潭 楚雄 晉城 本溪 運城 深圳

巨人網絡通訊聲明:本文標題《Go語言中的復合類型詳細介紹》,本文關鍵詞  語言,中的,復合,類型,詳細,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Go語言中的復合類型詳細介紹》相關的同類信息!
  • 本頁收集關于Go語言中的復合類型詳細介紹的相關信息資訊供網民參考!
  • 推薦文章
    校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃
    亚洲mv大片欧洲mv大片精品| 成人一区二区三区| 国产成人av电影在线| 欧美日韩一区二区三区四区五区| 久久久噜噜噜久久人人看| 亚洲一区二区中文在线| 成人伦理片在线| 精品久久国产97色综合| 香蕉成人啪国产精品视频综合网| 成人一道本在线| 久久精品人人做| 久久精品国产免费看久久精品| 欧美日韩一区二区三区四区五区| 亚洲欧洲成人av每日更新| 国产一区二区调教| 欧美xxxxxxxx| 美国三级日本三级久久99 | 亚洲成人av中文| 成人av电影在线网| 国产区在线观看成人精品| 久久99热这里只有精品| 欧美吞精做爰啪啪高潮| 亚洲国产美国国产综合一区二区| 99综合电影在线视频| 国产精品久久久久久久久晋中 | 一本大道久久精品懂色aⅴ| 国产三级精品在线| 国产精品亚洲人在线观看| 精品国产第一区二区三区观看体验 | 久久综合丝袜日本网| 六月婷婷色综合| 日韩一区二区在线看| 日本欧美韩国一区三区| 欧美一级黄色片| 另类小说视频一区二区| 精品久久久久久最新网址| 韩国成人在线视频| 国产三级一区二区| 成人一级黄色片| 亚洲精品视频观看| 欧美精品色一区二区三区| 水蜜桃久久夜色精品一区的特点| 91精品麻豆日日躁夜夜躁| 日本欧美一区二区三区乱码| 精品国产伦一区二区三区观看方式| 美日韩一区二区三区| 久久久久久99精品| www.日韩av| 三级影片在线观看欧美日韩一区二区| 欧美日本一区二区| 精品系列免费在线观看| 国产欧美视频一区二区| 一本到三区不卡视频| 偷拍日韩校园综合在线| 久久久久9999亚洲精品| 91免费国产视频网站| 日韩中文字幕1| 久久人人爽人人爽| 99精品视频一区| 天堂影院一区二区| 久久亚洲一级片| 色综合中文综合网| 欧美久久久久久久久中文字幕| 日本在线不卡一区| 久久精品这里都是精品| 在线观看亚洲精品视频| 秋霞av亚洲一区二区三| 国产精品初高中害羞小美女文| 欧美亚洲综合色| 国产福利一区在线| 亚洲国产中文字幕在线视频综合 | 国产成人三级在线观看| 亚洲国产成人av| 久久精品人人做| 5566中文字幕一区二区电影| 懂色av中文一区二区三区| 天天射综合影视| 国产精品久久久久久福利一牛影视 | 91精品国产高清一区二区三区| 国产成人午夜视频| 日韩av电影免费观看高清完整版| 国产精品久久久久久久久免费桃花 | 成人精品一区二区三区四区| 欧美aⅴ一区二区三区视频| 中文字幕人成不卡一区| 欧美成人在线直播| 欧美视频一区二区三区四区| 成人精品免费网站| 国产一区二区三区电影在线观看| 亚洲五月六月丁香激情| 亚洲色大成网站www久久九九| 久久久久久久久久久久久久久99| 欧美一区二区三区思思人| 色婷婷综合久久久久中文一区二区 | 成人免费一区二区三区在线观看| 亚洲精品在线电影| 69久久99精品久久久久婷婷| 欧美在线观看视频在线| 97成人超碰视| 成人18视频日本| 国产精品99久久久| 国内精品久久久久影院色| 日韩av午夜在线观看| 日韩成人dvd| 丝袜亚洲另类欧美综合| 五月婷婷激情综合| 亚洲国产精品人人做人人爽| 亚洲午夜一区二区| 亚洲精品中文在线观看| 自拍偷拍国产亚洲| 18成人在线观看| 亚洲精品免费在线播放| 亚洲精品视频自拍| 亚洲图片有声小说| 午夜国产精品一区| 偷拍亚洲欧洲综合| 麻豆精品在线播放| 国产呦萝稀缺另类资源| 国产suv精品一区二区6| 成年人网站91| 欧美性猛片aaaaaaa做受| 欧美日韩精品一区二区三区 | 日本韩国视频一区二区| 在线一区二区三区四区| 欧美色视频在线观看| 日韩一区二区三区三四区视频在线观看| 欧美日韩高清一区| 6080yy午夜一二三区久久| 精品少妇一区二区三区| 久久精品人人做人人综合| 亚洲欧洲日本在线| 亚洲国产精品视频| 看片的网站亚洲| 成人av免费在线观看| 欧美中文字幕不卡| 欧美不卡一区二区三区四区| 久久久久国产精品麻豆ai换脸| 综合自拍亚洲综合图不卡区| 亚洲综合男人的天堂| 日日欢夜夜爽一区| 国产一区 二区 三区一级| 99热精品一区二区| 欧美日韩精品二区第二页| 欧美精品一区男女天堂| 17c精品麻豆一区二区免费| 亚洲成人午夜影院| 国产精品91xxx| 欧美无砖专区一中文字| 26uuu亚洲| 亚洲图片欧美视频| 国产精品 欧美精品| 欧美色图在线观看| 国产人成亚洲第一网站在线播放 | 9191久久久久久久久久久| 久久久美女毛片| 亚洲成在线观看| 成人永久免费视频| 欧美一区二区三区免费| 国产精品福利电影一区二区三区四区| 亚洲gay无套男同| av亚洲精华国产精华| 欧美大白屁股肥臀xxxxxx| 自拍偷拍国产精品| 韩国女主播一区二区三区| 欧美在线短视频| 欧美国产日韩亚洲一区| 青青青爽久久午夜综合久久午夜| av成人老司机| 精品国产成人在线影院| 三级一区在线视频先锋| 欧美中文一区二区三区| 日本一二三不卡| 狠狠色丁香久久婷婷综| 欧美日韩精品系列| 一区二区三区免费网站| 成人精品免费视频| 久久久久久免费毛片精品| 日本91福利区| 欧美日本视频在线| 亚洲一区二区三区四区在线 | 成人黄色片在线观看| 欧美电影免费观看高清完整版在 | 国产中文字幕精品| 欧美一二三四在线| 午夜免费久久看| 欧美亚洲国产bt| 亚洲精品伦理在线| av在线这里只有精品| 中文字幕一区二区三区四区不卡| 国产精品一区二区不卡| 精品国产乱码久久久久久久久 | 2021久久国产精品不只是精品| 午夜精品123| 欧美亚洲动漫精品| 亚洲一区精品在线| 欧美日韩国产在线播放网站| 亚洲福利视频导航| 制服丝袜激情欧洲亚洲| 日韩高清国产一区在线| 日韩一区二区精品在线观看|