日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Golang——切片使用大全(创建、初始化、遍历、截取、修改、添加、切片的copy、切片作为函数参数、切片求和、切片求最大值)

發布時間:2025/3/15 编程问答 29 豆豆

概念:

  • 切片出現的原因也是因為數組的可操作性不高。切片的長度是不固定的,可以追加數據,可以理解切片是一個動態數組,切片的底層是一個結構體
  • 切片類型(slice)本身并不是動態數組或數組指針。它內部通過指針引用底層數組,設定相關屬性將操作限定在指定范圍內。當需要時,會申請更大的內存,將當前數據復制過去, 以實現類似動態數組的功能。
type slice struct { array unsafe.Pointer len int cap int }

切片的創建:

可直接創建切片對象,無需預先準備數組。因為是引用類型,須使用make函數或顯式初始化語句,它會自動完成底層數組內存分配

普通格式:

var 切片名 [] 數據類型

自動推導類型創建切片:

切片名 := [] 類型{}

make函數創建切片:
長度是已經初始化的空間,容量是已經開辟的空間,包括已經初始化的空間和空閑的空間

// 長度是不能大于容量的,容量可以省略不寫,不寫時候就默認和長度的值一樣 切片名稱 := make ([]切片類型,長度 容量)// 返回切片的容量使用cap,返回切片的長度使用len fmt.Println(cap(切片名稱))

演示:

func main() {s1 := make([]int, 3, 5) // 指定len、cap,底層數組初始化為零值s2 := make([]int, 3) // 省略cap,和len相等s3 := []int{10, 20, 5: 30} // 按初始化元素分配底層數組,并設置len、cap,設置索引5的數據為30fmt.Println(s2, len(s2), cap(s2))fmt.Println(s1, len(s1), cap(s1))fmt.Println(s3, len(s3), cap(s3)) }

輸出:

[0 0 0] 3 3 [0 0 0] 3 5 [10 20 0 0 0 30] 6 6

切片初始化:

三種創建格式,都是可以通過append向切片添加數據的

初始化格式:

/// 普通格式創建的切片 切片名 [索引] =// 自動推導類型創建的切片 切片名 := [] 類型{數據1,數據2,數據3}// make函數方式創建的切片可以通過append和循環初始化 切片名稱 = append(切片名稱, 數據1,數據2...)

演示:

func SliceDemo2() {var slice []intslice = append(slice, 1, 2, 3, 4)slice[1] = 111fmt.Println("切片中的數據", slice)fmt.Println("可以通過索引取部分數據", slice[0])fmt.Println("切片長度:", len(slice)) }func SliceDemo03() {slice := []int{1, 2, 3, 4, 5}slice = append(slice, 6, 7, 8, 9, 10)slice[1] = 111fmt.Println("切片中的數據", slice)fmt.Println("可以通過索引取部分數據", slice[0])fmt.Println("切片長度:", len(slice)) }func SliceDemo04() {slice := make([]int, 3, 4)for i := 0; i < len(slice); i++ {slice[i] = i + 1}slice = append(slice, 1)fmt.Println("切片中的數據", slice)fmt.Println("可以通過索引取部分數據", slice[0])fmt.Println("切片長度:", len(slice))fmt.Println("切片容量:", cap(slice)) }

注意下面兩種定義方式的區別。前者僅定義了一個[ ]int類型變量,并未執行初始化操作, 而后者則用初始化表達式完成了全部創建過程

func main() {var a []intb := []int{}println(a == nil, b == nil) }

可獲取元素地址,但不能向數組那樣直接通過指針(*slice)訪問元素內容

func main() {s := []int{0, 1, 2, 3, 4}p := &s // 取s地址p0 := &s[0] // 取s[0]地址p1 := &s[1]println(p, p0, p1)// 取p中[1]的數據且加100(*p)[1] += 100 // *[]int不支持indexing操作,須先用指針操作符獲取[]int對象fmt.Println(s)fmt.Println((*p)[1]) //這里加括號是優先級問題 }

如果元素類型也是切片,那么就能實現類似交錯數組的功能

func main() {x := [][]int{{1, 2},{10, 20, 30},{100},}fmt.Println(x[1])x[2] = append(x[2], 200, 300)fmt.Println(x[2]) }

輸出:

[1 2] [10 20 30] [100]

切片遍歷:

遍歷和數組一樣可以使用普通的for循環和range遍歷得到

演示:

func main() {slice := []int{1, 2, 3, 4, 5}for i := 0; i < len(slice); i++ {fmt.Print(slice[i])}for _, v := range slice {fmt.Println(v)} }

切片截取:

切片截取就是從切片中獲取指定的數據
如果初始化切片時,沒有指定切片的容量,切片容量是跟隨原切片的

切片截取的操作:

操作含義
s[n]切片s中索引位置為n的項
s[:]從切片s的索引位置0到len(s)-1處所獲得的切片
s[low:]從切片s的索引位置low到len(s)-1處所獲得的切片
s[:high]從切片s的索引位置0到high處所獲得的切片,len=high
s[low:high]從切片s的索引位置low到high處所獲得的切片,len=high-low
s[low:high:max]從切片s的索引位置low到high處所獲得的切片,len=high-low,cap=max-low
len(s)切片s的長度,總是<=cap(s)
cap(s)切片s的容量,總是>=len(s)

func main() {slice := []int{1, 2, 3, 4, 5}/**第一個值:截取的起始索引第二個值:截取的終止索引(不包括該值)第三個值:用來計算切片的容量,可以省略,默認和長度一樣容量 = 第三個值 - 第一個值長度 = 第二個值 - 第一個值*/newSlice := slice[0:3:3]fmt.Println("截取后的切片", newSlice)fmt.Println("切片的長度", len(newSlice))fmt.Println("切片的容量", cap(newSlice))// 和復制一樣了newSlice2 := slice[:]fmt.Println("截取后的切片", newSlice2)fmt.Println("切片的長度", len(newSlice2))fmt.Println("切片的容量", cap(newSlice2)) }

切片值的修改:

切片截取后返回新切片,對新切片的值進行修改,會影響原來的切片

原因:

切片截取后新的切片,不會給新的切片是指向了原來的切片,沒有給新的切片開辟新的空間,所以對于新的切片操作會影響到原來的切片

演示:

func main() {slice := []int{1, 2, 3, 4, 5}newSlice2 := slice[0:3]fmt.Println("切片修改前slice的數據:", slice)newSlice2[0] = 1111fmt.Println("切片修改后slice的數據:", slice) }

輸出:

切片修改前slice的數據: [1 2 3 4 5] 切片修改后slice的數據: [1111 2 3 4 5]

append函數:

append函數是向切片的末尾slice(len)添加數據
如果添加的內容超出了切片初始定義的容量,切片會自動擴容
擴容機制是:上一次的容量 * 2
如果超過1024字節,每次擴容上一次的1/4
append每次擴容都是一個新的內存,和原來的無關聯,所以如果是通過參數傳遞的方式,使用append添加數據,但是不會影響到原切片的數據,原因就是append每次拓展都是一個新的空間,指向的內存不再是原切片。

func main() {slice := make([]int, 3, 4)// 這里定義了切片的長度是3,初始容量是4,系統會對長度賦上默認值,int類型就是0,所以打印3個0fmt.Println("初始切片的數據:", slice, "長度:", len(slice))slice = append(slice, 1)// 添加數據,此時容量是4,數據已經有4個了,如果繼續多加點數據,會不會報錯fmt.Println("第一次添加數據:", slice, "長度:", len(slice))slice = append(slice, 2, 3, 4, 5, 6, 7, 8, 9)fmt.Println("第二次添加數據:", slice, "長度:", len(slice)) }

輸出:

初始切片的數據: [0 0 0] 長度: 3 第一次添加數據: [0 0 0 1] 長度: 4 第二次添加數據: [0 0 0 1 2 3 4 5 6 7 8 9] 長度: 12

copy函數:

把切片2的數據(0索引到len-1)賦值到切片1中
注意:如果切片1的容量不夠,則不賦值剩余的數據。如果切片1的數據比切片2的多,從切片2復制的數據是有多少,復制多少。
總結:copy只是復制索引相對應的數據,如果長度不夠,不會覆蓋原來的數據

格式:

copy(切片1,切片2)

演示:

// 從切片2復制到切片1,但是切片2的數據比切片1的多,所以,最終只是復制了一部分,也就是索引相對應的數據 func main() {slice := []int{1, 2, 3}slice2 := []int{4, 5, 6, 7, 8, 9}copy(slice, slice2)fmt.Println(slice) // [4 5 6] }// 從切片1復制到切片1,但是切片1的數據比切片2的少,所以,最終只是復制了一部分,也就是索引相對應的數據 func main() {slice := []int{1, 2, 3}slice2 := []int{4, 5, 6, 7, 8, 9}copy(slice2, slice)fmt.Println(slice2) // [1 2 3 7 8 9] }

還可直接從字符串中復制數據到[ ]byte

func main() {b := make([]byte, 3)n := copy(b, "abcde")fmt.Println(n, b) }

切片作為函數參數:

切片可以做為函數的參數,但是在函數中修改切片的值,會影響到原切片
因為切片的底層是結構體,結構體里有個參數Pointer,Pointer會指向切片的內存地址,使用的是淺拷貝方式,所以會影響到原切片值

演示:

func main() {slice := []int{1, 2, 3, 4, 5}SliceDemo10(slice) }func SliceDemo10(slice []int) {for _, v := range slice {fmt.Println(v)}slice = append(slice, 5, 6, 7)fmt.Println(slice) }

輸出:

1 2 3 4 5 [1 2 3 4 5 5 6 7]

切片求和:

func main() {// 定義變量,并收集用戶輸入的個數var count intfmt.Println("請輸入要求和的個數:")fmt.Scan(&count)// 定義切片,將輸入的個數保存到切片slice := make([]int, count)statisticalData(slice)// 求和summation(slice) }func statisticalData(slice []int) {for i := 0; i < len(slice); i++ {fmt.Printf("請輸入第%d個數\n", i+1)fmt.Scan(&slice[i])} } func summation(slice []int) {var sum intfor i := 0; i < len(slice); i++ {sum += slice[i]}fmt.Println("和為:", sum) }

切片求最大值:

func main() {// 定義變量,并收集用戶輸入的個數var count intfmt.Println("請輸入要比較的數:")fmt.Scan(&count)// 定義切片,將輸入的個數保存到切片slice := make([]int, count)statisticalData(slice)// 比較最大值maximum(slice) }func statisticalData(slice []int) {for i := 0; i < len(slice); i++ {fmt.Printf("請輸入第%d個數\n", i+1)fmt.Scan(&slice[i])} }func maximum(slice []int) {max := slice[0]for i := 0; i < len(slice); i++ {if max < slice[i] {max = slice[i]}}fmt.Println("最大值是:", max) }

總結

以上是生活随笔為你收集整理的Golang——切片使用大全(创建、初始化、遍历、截取、修改、添加、切片的copy、切片作为函数参数、切片求和、切片求最大值)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。