成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

go語言slice評(píng)分 Go slice

go語言中slice和array的區(qū)別

go 是瞬間發(fā)生的動(dòng)作,since 則表示從以前到現(xiàn)在的一段持續(xù)時(shí)間,而瞬間動(dòng)作不可能持續(xù)發(fā)生,只要把瞬間動(dòng)作 go 否定為 not/never go

目前創(chuàng)新互聯(lián)已為近1000家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站托管運(yùn)營(yíng)、企業(yè)網(wǎng)站設(shè)計(jì)、偃師網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。

go語言數(shù)組,切片和字典的區(qū)別和聯(lián)系

、數(shù)組 

與其他大多數(shù)語言類似,Go語言的數(shù)組也是一個(gè)元素類型相同的定長(zhǎng)的序列。

(1)數(shù)組的創(chuàng)建。

數(shù)組有3種創(chuàng)建方式:[length]Type 、[N]Type{value1, value2, ... , valueN}、[...]Type{value1, value2, ... , valueN} 如下:

復(fù)制代碼代碼如下:

func test5() {

var iarray1 [5]int32

var iarray2 [5]int32 = [5]int32{1, 2, 3, 4, 5}

iarray3 := [5]int32{1, 2, 3, 4, 5}

iarray4 := [5]int32{6, 7, 8, 9, 10}

iarray5 := [...]int32{11, 12, 13, 14, 15}

iarray6 := [4][4]int32{{1}, {1, 2}, {1, 2, 3}}

fmt.Println(iarray1)

fmt.Println(iarray2)

fmt.Println(iarray3)

fmt.Println(iarray4)

fmt.Println(iarray5)

fmt.Println(iarray6)

}

結(jié)果:

[0 0 0 0 0]

[1 2 3 4 5]

[1 2 3 4 5]

[6 7 8 9 10]

[11 12 13 14 15]

[[1 0 0 0] [1 2 0 0] [1 2 3 0] [0 0 0 0]]

我們看數(shù)組 iarray1,只聲明,并未賦值,Go語言幫我們自動(dòng)賦值為0。再看 iarray2 和 iarray3 ,我們可以看到,Go語言的聲明,可以表明類型,也可以不表明類型,var iarray3 = [5]int32{1, 2, 3, 4, 5} 也是完全沒問題的。

(2)數(shù)組的容量和長(zhǎng)度是一樣的。cap() 函數(shù)和 len() 函數(shù)均輸出數(shù)組的容量(即長(zhǎng)度)。如:

復(fù)制代碼代碼如下:

func test6() {

iarray4 := [5]int32{6, 7, 8, 9, 10}

fmt.Println(len(iarray4))

fmt.Println(cap(iarray4))

}

輸出都是5。

(3)使用:

復(fù)制代碼代碼如下:

func test7() {

iarray7 := [5]string{"aaa", `bb`, "可以啦", "叫我說什么好", "()"}

fmt.Println(iarray7)

for i := range iarray7 {

fmt.Println(iarray7[i])

}

}

二、切片

Go語言中,切片是長(zhǎng)度可變、容量固定的相同的元素序列。Go語言的切片本質(zhì)是一個(gè)數(shù)組。容量固定是因?yàn)閿?shù)組的長(zhǎng)度是固定的,切片的容量即隱藏?cái)?shù)組的長(zhǎng)度。長(zhǎng)度可變指的是在數(shù)組長(zhǎng)度的范圍內(nèi)可變。

(1)切片的創(chuàng)建。

切片的創(chuàng)建有4種方式:

1)make ( []Type ,length, capacity )

2) make ( []Type, length)

3) []Type{}

4) []Type{value1 , value2 , ... , valueN }

從3)、4)可見,創(chuàng)建切片跟創(chuàng)建數(shù)組唯一的區(qū)別在于 Type 前的“ [] ”中是否有數(shù)字,為空,則代表切片,否則則代表數(shù)組。因?yàn)榍衅情L(zhǎng)度可變的。如下是創(chuàng)建切片的示例:

復(fù)制代碼代碼如下:

func test8() {

slice1 := make([]int32, 5, 8)

slice2 := make([]int32, 9)

slice3 := []int32{}

slice4 := []int32{1, 2, 3, 4, 5}

fmt.Println(slice1)

fmt.Println(slice2)

fmt.Println(slice3)

fmt.Println(slice4)

}

輸出為:

[0 0 0 0 0]

[0 0 0 0 0 0 0 0 0]

[]

[1 2 3 4 5]

如上,創(chuàng)造了4個(gè)切片,3個(gè)空切片,一個(gè)有值的切片。

(2)切片與隱藏?cái)?shù)組:

一個(gè)切片是一個(gè)隱藏?cái)?shù)組的引用,并且對(duì)于該切片的切片也引用同一個(gè)數(shù)組。如下示例,創(chuàng)建了一個(gè)切片slice0,并根據(jù)這個(gè)切片創(chuàng)建了2個(gè)切片 slice1 和 slice2:

復(fù)制代碼代碼如下:

func test9() {

slice0 := []string{"a", "b", "c", "d", "e"}

slice1 := slice0[2 : len(slice0)-1]

slice2 := slice0[:3]

fmt.Println(slice0, slice1, slice2)

slice2[2] = "8"

fmt.Println(slice0, slice1, slice2)

}

輸出為:

[a b c d e] [c d] [a b c]

[a b 8 d e] [8 d] [a b 8]

可見,切片slice0 、 slice1 和 slice2是同一個(gè)底層數(shù)組的引用,所以slice2改變了,其他兩個(gè)都會(huì)變。

(3)遍歷、修改切片:

復(fù)制代碼代碼如下:

func test10() {

slice0 := []string{"a", "b", "c", "d", "e"}

fmt.Println("\n~~~~~~元素遍歷~~~~~~")

for _, ele := range slice0 {

fmt.Print(ele, " ")

ele = "7"

}

fmt.Println("\n~~~~~~索引遍歷~~~~~~")

for index := range slice0 {

fmt.Print(slice0[index], " ")

}

fmt.Println("\n~~~~~~元素索引共同使用~~~~~~")

for index, ele := range slice0 {

fmt.Print(ele, slice0[index], " ")

}

fmt.Println("\n~~~~~~修改~~~~~~")

for index := range slice0 {

slice0[index] = "9"

}

fmt.Println(slice0)

}

如上,前三種循環(huán)使用了不同的for range循環(huán),當(dāng)for后面,range前面有2個(gè)元素時(shí),第一個(gè)元素代表索引,第二個(gè)元素代表元素值,使用 “_” 則表示忽略,因?yàn)間o語言中,未使用的值會(huì)導(dǎo)致編譯錯(cuò)誤。

只有一個(gè)元素時(shí),該元素代表索引。

只有用索引才能修改元素。如在第一個(gè)遍歷中,賦值ele為7,結(jié)果沒有作用。因?yàn)樵谠乇闅v中,ele是值傳遞,ele是該切片元素的副本,修改它不會(huì)影響原本值,而在第四個(gè)遍歷——索引遍歷中,修改的是該切片元素引用的值,所以可以修改。

結(jié)果為:

~~~~~~元素遍歷~~~~~~

a b c d e

~~~~~~索引遍歷~~~~~~

a b c d e

~~~~~~元素索引共同使用~~~~~~

aa bb cc dd ee

~~~~~~修改~~~~~~

[9 9 9 9 9]

(4)、追加、復(fù)制切片:

復(fù)制代碼代碼如下:

func test11() {

slice := []int32{}

fmt.Printf("slice的長(zhǎng)度為:%d,slice為:%v\n", len(slice), slice)

slice = append(slice, 12, 11, 10, 9)

fmt.Printf("追加后,slice的長(zhǎng)度為:%d,slice為:%v\n", len(slice), slice)

slicecp := make([]int32, (len(slice)))

fmt.Printf("slicecp的長(zhǎng)度為:%d,slicecp為:%v\n", len(slicecp), slicecp)

copy(slicecp, slice)

fmt.Printf("復(fù)制賦值后,slicecp的長(zhǎng)度為:%d,slicecp為:%v\n", len(slicecp), slicecp)

}

追加、復(fù)制切片,用的是內(nèi)置函數(shù)append和copy,copy函數(shù)返回的是最后所復(fù)制的元素的數(shù)量。

(5)、內(nèi)置函數(shù)append

內(nèi)置函數(shù)append可以向一個(gè)切片后追加一個(gè)或多個(gè)同類型的其他值。如果追加的元素?cái)?shù)量超過了原切片容量,那么最后返回的是一個(gè)全新數(shù)組中的全新切片。如果沒有超過,那么最后返回的是原數(shù)組中的全新切片。無論如何,append對(duì)原切片無任何影響。如下示例:

復(fù)制代碼代碼如下:

func test12() {

slice := []int32{1, 2, 3, 4, 5, 6}

slice2 := slice[:2]

_ = append(slice2, 50, 60, 70, 80, 90)

fmt.Printf("slice為:%v\n", slice)

fmt.Printf("操作的切片:%v\n", slice2)

_ = append(slice2, 50, 60)

fmt.Printf("slice為:%v\n", slice)

fmt.Printf("操作的切片:%v\n", slice2)

}

如上,append方法用了2次,結(jié)果返回的結(jié)果完全不同,原因是第二次append方法追加的元素?cái)?shù)量沒有超過 slice 的容量。而無論怎樣,原切片slice2都無影響。結(jié)果:

slice為:[1 2 3 4 5 6]

操作的切片:[1 2]

slice為:[1 2 50 60 5 6]

操作的切片:[1 2]

go程序如何分配堆棧的

在Go語言中有一些調(diào)試技巧能幫助我們快速找到問題,有時(shí)候你想盡可能多的記錄異常但仍覺得不夠,搞清楚堆棧的意義有助于定位Bug或者記錄更完整的信息。

本文將討論堆棧跟蹤信息以及如何在堆棧中識(shí)別函數(shù)所傳遞的參數(shù)。

Functions

先從這段代碼開始:

Listing 1

01 package main

02

03 func main() {

04 ? ? slice := make([]string, 2, 4)

05 ? ? Example(slice, "hello", 10)

06 }

07

08 func Example(slice []string, str string, i int) {

09 ? ? panic("Want stack trace")

10 }

Example函數(shù)定義了3個(gè)參數(shù),1個(gè)string類型的slice, 1個(gè)string和1個(gè)integer, 并且拋出了panic,運(yùn)行這段代碼可以看到這樣的結(jié)果:

Listing 2

Panic: Want stack trace

goroutine 1 [running]:

main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)

/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/

temp/main.go:9 +0x64

main.main()

/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/

temp/main.go:5 +0x85

goroutine 2 [runnable]:

runtime.forcegchelper()

/Users/bill/go/src/runtime/proc.go:90

runtime.goexit()

/Users/bill/go/src/runtime/asm_amd64.s:2232 +0x1

goroutine 3 [runnable]:

runtime.bgsweep()

/Users/bill/go/src/runtime/mgc0.go:82

runtime.goexit()

/Users/bill/go/src/runtime/asm_amd64.s:2232 +0x1

堆棧信息中顯示了在panic拋出這個(gè)時(shí)間所有的goroutines狀態(tài),發(fā)生的panic的goroutine會(huì)顯示在最上面。

Listing 3

01 goroutine 1 [running]:

02 main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)

/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/

temp/main.go:9 +0x64

03 main.main()

/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/

temp/main.go:5 +0x85

第1行顯示最先發(fā)出panic的是goroutine 1, 第二行顯示panic位于main.Example中, 并能定位到該行代碼,在本例中第9行引發(fā)了panic。

下面我們關(guān)注參數(shù)是如何傳遞的:

Listing 4

// Declaration

main.Example(slice []string, str string, i int)

// Call to Example by main.

slice := make([]string, 2, 4)

Example(slice, "hello", 10)

// Stack trace

main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)

這里展示了在main中帶參數(shù)調(diào)用Example函數(shù)時(shí)的堆棧信息,比較就能發(fā)現(xiàn)兩者的參數(shù)數(shù)量并不相同,Example定義了3個(gè)參數(shù),堆棧中顯示了6個(gè)參數(shù)。現(xiàn)在的關(guān)鍵問題是我們要弄清楚它們是如何匹配的。

第1個(gè)參數(shù)是string類型的slice,我們知道在Go語言中slice是引用類型,即slice變量結(jié)構(gòu)會(huì)包含三個(gè)部分:指針、長(zhǎng)度(Lengthe)、容量(Capacity)

Listing 5

// Slice parameter value

slice := make([]string, 2, 4)

// Slice header values

Pointer: ?0x2080c3f50

Length: ? 0x2

Capacity: 0x4

// Declaration

main.Example(slice []string, str string, i int)

// Stack trace

main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)

因此,前面3個(gè)參數(shù)會(huì)匹配slice, 如下圖所示:

Figure 1

figure provided by Georgi Knox

我們現(xiàn)在來看第二個(gè)參數(shù),它是string類型,string類型也是引用類型,它包括兩部分:指針、長(zhǎng)度。

Listing 6

// String parameter value

"hello"

// String header values

Pointer: 0x425c0

Length: ?0x5

// Declaration

main.Example(slice []string,?str string, i int)

// Stack trace

main.Example(0x2080c3f50, 0x2, 0x4,?0x425c0, 0x5, 0xa)

可以確定,堆棧信息中第4、5兩個(gè)參數(shù)對(duì)應(yīng)代碼中的string參數(shù),如下圖所示:

Figure 2

figure provided by Georgi Knox

最后一個(gè)參數(shù)integer是single word值。

Listing 7

// Integer parameter value

10

// Integer value

Base 16: 0xa

// Declaration

main.Example(slice []string, str string,?i int)

// Stack trace

main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5,?0xa)

現(xiàn)在我們可以匹配代碼中的參數(shù)到堆棧信息了。

Figure 3

figure provided by Georgi Knox

Methods

如果我們將Example作為結(jié)構(gòu)體的方法會(huì)怎么樣呢?

Listing 8

01 package main

02

03 import "fmt"

04

05 type trace struct{}

06

07 func main() {

08 ? ? slice := make([]string, 2, 4)

09

10 ? ? var t trace

11 ? ? t.Example(slice, "hello", 10)

12 }

13

14 func (t *trace) Example(slice []string, str string, i int) {

15 ? ? fmt.Printf("Receiver Address: %p\n", t)

16 ? ? panic("Want stack trace")

17 }

如上所示修改代碼,將Example定義為trace的方法,并通過trace的實(shí)例t來調(diào)用Example。

再次運(yùn)行程序,會(huì)發(fā)現(xiàn)堆棧信息有一點(diǎn)不同:

Listing 9

Receiver Address:?0x1553a8

panic: Want stack trace

01 goroutine 1 [running]:

02 main.(*trace).Example(0x1553a8, 0x2081b7f50, 0x2, 0x4, 0xdc1d0, 0x5, 0xa)

/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/

temp/main.go:16 +0x116

03 main.main()

/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/

temp/main.go:11 +0xae

首先注意第2行的方法調(diào)用使用了pointer receiver,在package名字和方法名之間多出了"*trace"字樣。另外,參數(shù)列表的第1個(gè)參數(shù)標(biāo)明了結(jié)構(gòu)體(t)地址。我們從堆棧信息中看到了內(nèi)部實(shí)現(xiàn)細(xì)節(jié)。

Packing

如果有多個(gè)參數(shù)可以填充到一個(gè)single word, 則這些參數(shù)值會(huì)合并打包:

Listing 10

01 package main

02

03 func main() {

04 ? ? Example(true, false, true, 25)

05 }

06?

07 func Example(b1, b2, b3 bool, i uint8) {

08 ? ? panic("Want stack trace")

09 }

這個(gè)例子修改Example函數(shù)為4個(gè)參數(shù):3個(gè)bool型和1個(gè)八位無符號(hào)整型。bool值也是用8個(gè)bit表示,所以在32位和64位架構(gòu)下,4個(gè)參數(shù)可以合并為一個(gè)single word。

Listing 11

01 goroutine 1 [running]:

02 main.Example(0x19010001)

/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/

temp/main.go:8 +0x64

03 main.main()

/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/

temp/main.go:4 +0x32

這是本例的堆棧信息,看下圖的具體分析:

Listing 12

// Parameter values

true, false, true, 25

// Word value

Bits ? ?Binary ? ? ?Hex ? Value

00-07 ? 0000 0001 ??01? ??true

08-15 ? 0000 0000 ??00? ? false

16-23 ? 0000 0001 ??01? ? true

24-31 ? 0001 1001 ??19? ? 25

// Declaration

main.Example(b1, b2, b3 bool, i uint8)

// Stack trace

main.Example(0x19010001)

以上展示了參數(shù)值是如何匹配到4個(gè)參數(shù)的。當(dāng)我們看到堆棧信息中包括十六進(jìn)制值,需要知道這些值是如何傳遞的。

go語言中實(shí)現(xiàn)切片(slice)的三種方式

定義一個(gè)切片,然后讓切片去引用一個(gè)已經(jīng)創(chuàng)建好的數(shù)組?;菊Z法如下:

索引1:切片引用的起始元素位

索引2:切片只引用該元素位之前的元素

例程如下:

在該方法中,我們未指定容量cap,這里的值為5是系統(tǒng)定義的。

在方法一中,可以用arr數(shù)組名來操控?cái)?shù)組中的元素,也可以通過slice切片來操控?cái)?shù)組中的元素。切片是直接引用數(shù)組,數(shù)組是事先存在的,程序員是可見的。

通過 make 來創(chuàng)建切片,基本語法如下:

make函數(shù)第三個(gè)參數(shù)cap即容量是可選的,如果一定要自己注明的話,要注意保證cap≥len。

用該方法可以 指定切片的大小(len)和容量(cap)

例程如下:

由于未賦值系統(tǒng)默認(rèn)將元素值置為0,即:

數(shù)值類型數(shù)組:????默認(rèn)值為 0

字符串?dāng)?shù)組:? ? ? ?默認(rèn)值為 ""

bool數(shù)組:? ? ? ? ? ?默認(rèn)值為 false

在方法二中,通過make方式創(chuàng)建的切片對(duì)應(yīng)的數(shù)組是由make底層維護(hù),對(duì)外不可見,即只能通過slice去訪問各個(gè)元素。

定義一個(gè)切片,直接就指定具體數(shù)組,使用原理類似于make的方式。

例程如下:

Go語言中數(shù)組和slice的區(qū)別

PHP的數(shù)組是數(shù)列Array,列表List,散列表/關(guān)聯(lián)數(shù)組/字典Hashtable的聚合體。

是一個(gè)非常高級(jí)的數(shù)據(jù)結(jié)構(gòu)。也是一個(gè)優(yōu)秀的設(shè)計(jì)。

有一套數(shù)組功能函數(shù)支持php的數(shù)組。

C數(shù)組只是一個(gè)"固定長(zhǎng)度、固定類型"的數(shù)列Array,實(shí)現(xiàn)簡(jiǎn)單,功能原始。有數(shù)列的隨機(jī)操作快的長(zhǎng)處,也有數(shù)列的增、刪低效的毛病

如果要比較,PHP的數(shù)組應(yīng)該和C++的STL有一比,功能類似。

本文題目:go語言slice評(píng)分 Go slice
當(dāng)前網(wǎng)址:http://jinyejixie.com/article36/dodhdsg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、品牌網(wǎng)站設(shè)計(jì)、軟件開發(fā)、網(wǎng)站營(yíng)銷、微信小程序

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)
大同市| 博客| 三门县| 龙川县| 宁武县| 张掖市| 新郑市| 高唐县| 高唐县| 苏尼特左旗| 启东市| 鄯善县| 黑河市| 永胜县| 宜兴市| 灵山县| 高雄市| 凌源市| 崇义县| 岳池县| 同仁县| 关岭| 北辰区| 吴川市| 墨脱县| 曲周县| 滁州市| 台前县| 云龙县| 桂东县| 昌邑市| 扶余县| 河津市| 吴堡县| 惠东县| 松阳县| 正安县| 安义县| 临泽县| 延津县| 靖远县|