主頁 > 後端開發 > 切片比陣列好用在哪

切片比陣列好用在哪

2023-06-10 07:55:41 後端開發

1. 引言

在Go語言中,陣列和切片都是常見的資料結構,它們經常被用于存盤資料,可以相互替換,本文將介紹Go語言中陣列和切片的基本概念,同時詳細探討切片的優勢,從而能夠充分的理解切片相對于陣列的優點,更好得對切片進行使用,

2. 基本介紹

2.1 陣列

陣列是一種固定長度、具有相同型別的元素序列,在Go語言中,陣列的長度在創建時確定,并且無法動態增長或縮小,陣列的宣告方式為var name [size]Type,其中name是陣列的識別符號,size是陣列的長度,Type是陣列存盤的元素型別,下面是陣列使用的基本示例:

package main

import "fmt"

func main() {
        // 宣告一個整數陣列
        var numbers [2]int
               
        // 初始化陣列元素
        numbers[0] = 1
        numbers[1] = 2
        
        // 訪問陣列元素
        fmt.Println("陣列中的元素:", numbers[0], numbers[1])
}

在上面的例子中,我們定義了一個長度為2的整數陣列,分別對其對其賦值和訪問,

2.2 切片

Go語言中的切片實際上是對底層陣列的一個參考,切片的長度可以動態改變,而且可以通過切片運算式或內置的appendcopy函式對切片進行操作,切片的宣告方式為var name []Type,其中name是切片的識別符號,Type是切片存盤的元素型別,下面是切片使用的一個基本的例子:

package main

import "fmt"

func main() {
        // 宣告一個整數切片
        var numbers []int
        // 賦值切片
        numbers = []int{1, 2}
        // 訪問切片元素
        fmt.Println("切片中的元素:", numbers[0], numbers[1]) 
}

2.3 總述

看起來陣列和切片在定義和使用上有些相似,但它們在長度、記憶體分配、大小調整和傳遞方式等方面存在重要的區別,接下來,我們將探討切片相對于陣列的優勢,并解釋為何在許多情況下選擇切片更加合適,

3. 切片優勢

3.1 動態長度

切片在Go語言中具有動態增長和縮小的能力,這是切片相對于陣列的重要優勢之一,通過動態調整切片的長度,我們可以根據需要有效地處理和管理資料,

在Go語言中,我們可以使用內置的append函式向切片中添加元素,append函式接受一個切片和一個或多個元素作為引數,并回傳一個新的切片,其中包含原切片的所有元素以及添加的新元素,如果切片的容量不足以容納新元素,append函式會自動進行記憶體分配并擴展底層陣列的大小,以容納更多的元素,

以下是一個示例,演示了如何使用append函式向切片中添加元素:

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3} // 宣告一個切片

    // 使用 append 函式向切片添加元素
    slice = append(slice, 4)
    slice = append(slice, 5, 6)

    fmt.Println(slice) // 輸出: [1 2 3 4 5 6]
}

通過重復呼叫append函式,我們可以根據需要動態地增加切片的長度,而不必擔心底層陣列的固定長度,

另外,切片也支持使用切片運算式來創建一個新的切片,該切片是原切片的子序列,通過指定起始和結束索引,我們可以選擇性地提取切片中的一部分資料,以下是一個示例,演示了如何使用切片運算式來縮小切片的長度:

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3, 4, 5, 6} // 宣告一個切片

    // 使用切片運算式縮小切片的長度
    slice = slice[1:4] // 選擇索引1到索引3的元素(不包含索引4)

    fmt.Println(slice) // 輸出: [2 3 4]
}

通過調整切片運算式中的起始和結束索引,我們可以靈活地縮小切片的長度,以滿足特定需求,

對于陣列而言,在創建時需要指定固定的長度,而且無法在運行時改變長度,這意味著陣列的長度是靜態的,無法根據需要進行動態調整,比如下面示例代碼:

package main

import "fmt"

func main() {
        // 宣告一個長度為2的整數陣列
        var numbers [2]int
        // 賦值前5個元素
        numbers[0] = 1
        numbers[1] = 2
        // 這里無法再繼續賦值
        // numners[2] = 3
}

這里定義一個長度為2的整數陣列,如果元素數超過2時,此時將無法繼續寫入,需要重新定義長度更大的一個整數陣列,將舊陣列的元素全部拷貝過來,之后才能繼續寫入,

而切片則具有動態長度和靈活性,可以根據需要進行動態調整,切片在處理長度不確定的資料時更加方便和高效,因此,在許多情況下,選擇切片而不是陣列可以更好地滿足實際需求,

3.2 隨意切割和連接

切片在Go語言中具有出色的靈活性,可以進行切割和連接等操作,這些操作使得我們能夠輕松地處理和操作切片的子序列,以滿足不同的需求,

切片可以通過切片運算式進行切割,即選擇切片中的一部分資料,切片運算式使用起始索引和結束索引來指定切片的范圍,例如,slice[1:4]會回傳一個新的切片,包含從索引1到索引3的元素(不包含索引4),通過切割操作,我們可以獲取切片的子序列,便于對資料進行分析、處理和傳遞,

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3, 4, 5, 6} // 宣告一個切片

    // 切割操作
    subSlice := slice[1:4] // 選擇索引1到索引3的元素(不包含索引4)
    fmt.Println(subSlice) // 輸出: [2 3 4]
}

切片還支持使用內置的append函式進行連接操作,將一個切片連接到另一個切片的末尾,append函式會回傳一個新的切片,其中包含原始切片和要連接的切片的所有元素,通過連接操作,我們可以將多個切片合并成一個更大的切片,方便進行統一的處理和操作,

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3, 4, 5, 6} // 宣告一個切片
    // 連接操作
    anotherSlice := []int{7, 8, 9}
    mergedSlice := append(slice, anotherSlice...)
    fmt.Println(mergedSlice) // 輸出: [1 2 3 4 5 6 7 8 9]
}

通過切割操作和連接操作,我們可以按需選擇和組合切片中的元素,使得切片在處理資料時更加靈活和方便,這些操作可以根據具體需求進行自由組合,滿足不同場景下的資料處理要求,

3.3 引數傳遞的性能優勢

在函式引數傳遞和回傳值方面,切片具有明顯的優勢,并且能夠避免資料的復制和性能開銷,

將切片作為函式的引數傳遞時,實際上是傳遞切片的參考而不是復制整個切片,相比之下,如果傳遞陣列作為引數,會進行陣列的復制,產生額外的記憶體開銷和時間消耗,

由于切片傳遞的是參考,而不是復制整個資料,所以在函式引數傳遞時可以大大減少記憶體開銷,無論切片的大小如何,傳遞的開銷都是固定的,只是參考指標的復制,這對于大型資料集合的處理尤為重要,可以顯著減少記憶體占用,

下面通過一個基準測驗,證明使用切片傳遞引數,相比使用陣列傳遞引數來說,整體性能更好:

const (
   arraySize   = 1000000 // 陣列大小
   sliceLength = 1000000 // 切片長度
)

// 使用陣列作為函式引數
func processArray(arr [arraySize]int) int {
   // 避免編譯器優化,正確展示效果
   // 使用 reflect.ValueOf 將陣列轉換為 reflect.Value
   arrValue := reflect.ValueOf(&arr).Elem()

   sum := 0
   for i := 0; i < arrValue.Len(); i++ {
      // 使用 reflect.Value 索引操作修改陣列元素的值
      arrValue.Index(i).SetInt(2)
   }
   return sum
}

// 使用切片作為函式引數
func processSlice(slice []int) int {
   // 避免編譯器優化
   arrValue := reflect.ValueOf(&slice).Elem()
   sum := 0
   for i := 0; i < arrValue.Len(); i++ {
      // 使用 reflect.Value 索引操作修改陣列元素的值
      arrValue.Index(i).SetInt(2)
   }
   return sum
}

// 使用陣列作為引數的性能測驗函式
func BenchmarkArray(b *testing.B) {
   var arr [arraySize]int
   for i := 0; i < arraySize; i++ {
      arr[i] = i
   }

   b.ResetTimer()
   for i := 0; i < b.N; i++ {
      processArray(arr)
   }
}

// 使用切片作為引數的性能測驗函式
func BenchmarkSlice(b *testing.B) {
   slice := make([]int, sliceLength)
   for i := 0; i < sliceLength; i++ {
      slice[i] = i
   }
   b.ResetTimer()
   for i := 0; i < b.N; i++ {
      processSlice(slice)
   }
}

這里我們定義了BenchmarkArrayBenchmarkSlice 兩個基準測驗,分別使用陣列和切片來作為引數來傳遞,下面是這兩個基準測驗的運行結果:

BenchmarkArray-4             116           9980122 ns/op         8003584 B/op          1 allocs/op
BenchmarkSlice-4             169           6898980 ns/op              24 B/op          1 allocs/op

其中ns/op 表示每次操作的平均執行時間,即函式執行的耗時,B/op 表示每次操作的平均記憶體分配量,即每次操作分配的記憶體大小,allocs/op 表示每次操作的平均記憶體分配次數,

在這里例子中,可以看到,陣列傳遞引數,每一次操作會分配8003584位元組的記憶體,而使用切片來傳遞引數,每次只會傳遞24位元組的記憶體,而且陣列作為引數傳遞也比切片作為引數傳遞的平均執行時間傳遞更長,

這個基準測驗的結果也證明了,在函式引數傳遞和回傳值方面,相對于陣列,切片具有明顯的優勢,并且能夠避免資料的復制和性能開銷,

4. 總結

本文介紹了Go語言中陣列和切片的基本概念,并詳細探討了切片相對于陣列的優勢,

陣列是一種固定長度、具有相同型別的元素序列,而切片是對底層陣列的一個參考,并具有動態長度的能力,切片可以使用切片運算式和內置的append函式進行靈活的切割和連接操作,使得資料的處理更加方便和高效,

切片在函式引數傳遞和回傳值方面也具有性能優勢,因為切片傳遞的是參考而不是復制整個資料,可以減少記憶體開銷,

總的來說,切片在處理長度不確定、需要動態調整的資料時更加靈活和高效,在許多情況下,選擇切片而不是陣列可以更好地滿足實際需求,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/554759.html

標籤:其他

上一篇:java集成chatGpt完整案例代碼(效果和官網一樣逐字輸出)

下一篇:返回列表

標籤雲
其他(160677) Python(38219) JavaScript(25489) Java(18216) C(15237) 區塊鏈(8270) C#(7972) AI(7469) 爪哇(7425) MySQL(7241) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5873) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4589) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2435) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1984) 功能(1967) HtmlCss(1956) Web開發(1951) C++(1933) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1880) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • 切片比陣列好用在哪

    # 1. 引言 在Go語言中,陣列和切片都是常見的資料結構,它們經常被用于存盤資料,可以相互替換。本文將介紹Go語言中陣列和切片的基本概念,同時詳細探討切片的優勢。從而能夠充分的理解切片相對于陣列的優點,更好得對切片進行使用。 # 2. 基本介紹 ### 2.1 陣列 陣列是一種固定長度、具有相同類 ......

    uj5u.com 2023-06-10 07:55:41 more
  • java集成chatGpt完整案例代碼(效果和官網一樣逐字輸出)

    背景 要集成chatGpt參考我上一篇文章即可。但是,如果要實作官網一樣的效果,逐字輸出,難度就提升了不少了。經過在官網的研究發現它應該是采用了SSE技術,這是一種最新的HTTP互動技術。SSE(Server-Sent Events):通俗解釋起來就是一種基于HTTP的,以流的形式由服務端持續向客戶 ......

    uj5u.com 2023-06-10 07:55:33 more
  • Java物件中轉換空值的欄位

    在后端回傳資料給前端時,公司的框架會把值為null的資料去掉,方便前端取值。 如:Person物件為:{name:"浩二", age:24, weight:null, height:114},那回傳給前端的就為{name:"浩二", age:24, height:114}。 如果這個時候有個需求: ......

    uj5u.com 2023-06-10 07:54:49 more
  • 構建高可用、高效、安全和可靠的分布式系統:Spring Cloud為開發人

    Spring Cloud是一個基于Spring框架的云應用開發工具箱,可以快速構建分布式應用程式。它為開發人員提供了許多有用的功能,例如服務發現、負載均衡、配置管理和應用監控等,這些功能可以使分布式系統更加穩定和可靠。 如果您還沒有了解過Spring Cloud,我強烈建議您觀看以下這個視頻鏈接: ......

    uj5u.com 2023-06-10 07:54:43 more
  • Java 集合框架體系簡介

    陣列可以通過索引快速訪問和操作元素,在許多場景下仍然是非常有用的,但如果需要動態調整大小或保存不同型別的元素,則可以考慮使用集合類來代替陣列。集合類還提供了一系列增加、洗掉、修改和查找元素的方法。集合框架中還提供了多種優化和封裝好的實作類,通過使用合適的集合類可以更高效地組織和操作資料。 ......

    uj5u.com 2023-06-10 07:54:37 more
  • BS和CS

    # BS和CS - **CS:**客戶端服務器架構模式 - **優點:**充分利用客戶端機器的資源,減輕服務器的負荷(一部分安全要求不高的計算任務存盤任務放在客戶端執行,從而能夠減輕服務器的壓力,也能夠減輕網路負荷); - **缺點:**需要安裝;升級維護成本較高; - **BS:**瀏覽器服務器架 ......

    uj5u.com 2023-06-10 07:54:30 more
  • 百度人臉識別_SpringBoot整合離線SDK

    ### 一、前言 1. 建議使用低版本 SDK : [Baidu_Face_Offline_SDK_Windows_Java_6.1.3](https://www.123pan.com/s/AvoiVv-d7aud.html) - 目前已知8.x版本對服務端不兼容,存在運行程序中,第一次呼叫sdk能 ......

    uj5u.com 2023-06-10 07:54:26 more
  • Angular4 教程_編程入門自學教程_菜鳥教程-免費教程分享

    ## 教程簡介 Angular是Google推出的Web前端開發框架,從12年發布起就受到了強烈的關注,他首次提出了雙向系結的概念,讓人耳目一新,在2016年9月中旬,Google正式發布了Angular的第二代開發框架Angular 2,2017年3月推出了Angular4。 [Angular 4 ......

    uj5u.com 2023-06-10 07:54:21 more
  • for-range排坑指南

    0x01 遍歷取不到所有元素指標? 如下代碼想從陣列遍歷獲取一個指標元素切片集合 arr := [2]int{1, 2} res := []*int{} for _, v := range arr { res = append(res, &v) } //expect: 1 2 fmt.Println ......

    uj5u.com 2023-06-10 07:54:14 more
  • 【K哥爬蟲普法】一個人、一年半、掙了2000萬!

    ![01](https://img2023.cnblogs.com/other/2501174/202306/2501174-20230609142240935-1220768091.png) > 我國目前并未出臺專門針對網路爬蟲技術的法律規范,但在司法實踐中,相關判決已屢見不鮮,K 哥特設了“K哥 ......

    uj5u.com 2023-06-10 07:54:04 more