大資料開發-Go-陣列,切片

Hoult丶吳邪發表於2021-08-08

new()和make的區別

二者看起來沒什麼區別,但是他們的行為不同,分別適用於不同的型別

  • new (T) 為每個新的型別 T 分配一片記憶體,初始化為 0 並且返回型別為 * T 的記憶體地址:這種方法 返回一個指向型別為 T,值為 0 的地址的指標,它適用於值型別如陣列和結構體;它相當於 &T{}。

  • make(T) 返回一個型別為 T 的初始值,它只適用於 3 種內建的引用型別:切片、map 和 channel

bytes包

型別 []byte 的切片十分常見,Go 語言有一個 bytes 包專門用來解決這種型別的操作方法,比如bytes的buffer,就提供Read和Write的方法,讀寫未知長度的bytes時候最好用buffer,下面的例子類似於Java的StringBuilder的append方法

var buffer bytes.Buffer
for {
    if s, ok := getNextString(); ok { //method getNextString() not shown here
        buffer.WriteString(s)
    } else {
        break
    }
}
fmt.Print(buffer.String(), "\n")

slice重組

知道切片建立的時候通常比相關陣列小,例如:

slice1 := make([]type, start_length, capacity)

其中 start_length 作為切片初始長度而 capacity 作為相關陣列的長度。

這麼做的好處是我們的切片在達到容量上限後可以擴容。改變切片長度的過程稱之為切片重組 reslicing,做法如下:slice1 = slice1[0:end],其中 end 是新的末尾索引(即長度),如果想增加切片的容量,我們必須建立一個新的更大的切片並把原分片的內容都拷貝過來

package main
import "fmt"

func main() {
    sl_from := []int{1, 2, 3}
    sl_to := make([]int, 10)

    n := copy(sl_to, sl_from)
    fmt.Println(sl_to)
    fmt.Printf("Copied %d elements\n", n) // n == 3

    sl3 := []int{1, 2, 3}
    sl3 = append(sl3, 4, 5, 6)
    fmt.Println(sl3)
}

注意: append 在大多數情況下很好用,但是如果你想完全掌控整個追加過程,你可以實現一個這樣的 AppendByte 方法:

func AppendByte(slice []byte, data ...byte) []byte {
    m := len(slice)
    n := m + len(data)
    if n > cap(slice) { // if necessary, reallocate
        // allocate double what's needed, for future growth.
        newSlice := make([]byte, (n+1)*2)
        copy(newSlice, slice)
        slice = newSlice
    }
    slice = slice[0:n]
    copy(slice[m:n], data)
    return slice
}

Slice的相關應用

假設 s 是一個字串(本質上是一個位元組陣列),那麼就可以直接通過 c := []byte(s) 來獲取一個位元組的切片 c。另外還可以通過 copy 函式來達到相同的目的:copy(dst []byte, src string) ,使用 substr := str[start:end] 可以從字串 str 獲取到從索引 start 開始到 end-1 位置的子字串

package main

import "fmt"

func main() {
    s := "\u00ff\u754c"
    for i, c := range s {
        fmt.Printf("%d:%c ", i, c)
    }
}

在記憶體中,一個字串實際上是一個雙字結構,即一個指向實際資料的指標和記錄字串長度的整數(見圖 7.4)。因為指標對使用者來說是完全不可見,因此我們可以依舊把字串看做是一個值型別,也就是一個字元陣列。

字串 string s = "hello" 和子字串 t = s[2:3]

  • 修改字串

    • Go 語言中的字串是不可變的,也就是說 str[index] 這樣的表示式是不可以被放在等號左側的,如果必須要修改,必須要先將字串轉為位元組陣列,然後通過修改元素值來達到修改字串的目的,最後要講位元組陣列轉回字串格式
  • 字串對比函式

    • Compare 函式會返回兩個位元組陣列字典順序的整數對比結果
  • 搜尋及排序切片和陣列

    • 標準庫提供了 sort 包來實現常見的搜尋和排序操作。您可以使用 sort 包中的函式 func Ints(a []int) 來實現對 int 型別的切片排序
  • 切片和垃圾回收

    切片的底層指向一個陣列,該陣列的實際容量可能要大於切片所定義的容量。只有在沒有任何切片指向的時候,底層的陣列記憶體才會被釋放,這種特性有時會導致程式佔用多餘的記憶體
    吳邪,小三爺,混跡於後臺,大資料,人工智慧領域的小菜鳥。
    更多請關注
    file

相關文章