Golang中Array是值類型而slice是引用類型。因此兩者之間的賦值或拷貝有些差異,本文帶你了解各自的差異。
1. 拷貝array
前面提及數組是值類型,所以數組變量名不是指向第一個元素的指針。事實上它表示整個數組,下面兩者情況將自動創建數組:
數組變量賦值給另一個數組變量
數組變量傳遞作為函數參數
請看示例:
package main
import "fmt"
func main() {
sample1 := [2]string{"a", "b"}
fmt.Printf("Sample1 Before: %v\n", sample1)
sample2 := sample1
sample2[0] = "c"
fmt.Printf("Sample1 After assignment: %v\n", sample1)
fmt.Printf("Sample2: %v\n", sample2)
test(sample1)
fmt.Printf("Sample1 After Test Function Call: %v\n", sample1)
}
func test(sample [2]string) {
sample[0] = "d"
fmt.Printf("Sample in Test function: %v\n", sample)
}
輸出結果:
Sample1 Before: [a b]
Sample1 After assignment: [a b]
Sample2:
Sample in Test function: [d b]
Sample1 After Test Function Call: [a b]
我們稍作解釋:
sample1 賦給 sample2 ,然后修改sample2中第一個元素。打印sample1驗證是否有影響,當然沒有改變。這是因為sample1 賦給 sample2,會創建sample1的拷貝給sample2,故修改sample2不影響sample1.
傳遞sample1給test函數,然后在函數體內修改其第一個元素。之后打印sample1驗證是否有影響,當然也沒有。原因是一樣的,當sample1作為參數傳遞給test時,sample1的拷貝被創建并傳入,因此修改不會影響原來sample1.
2. 拷貝slice
Golang內置包提供copy函數能夠拷貝slice,函數前面如下,其返回拷貝元素個數:
func copy(dst, src []Type) int
使用copy函數需要考慮兩種情況:
如果src長度大于dst,那么僅拷貝dst長度個元素
如果dst長度大于src,那么僅拷貝src長度個元素
總結為拷貝兩者最小長度元素:min(src,dst)
需要注意的是,一旦拷貝完成,對目標的修改不會影響源,反之亦然。
我們也通過示例說明:
package main
import "fmt"
func main() {
src := []int{1, 2, 3, 4, 5}
dst := make([]int, 5)
numberOfElementsCopied := copy(dst, src)
fmt.Printf("Number Of Elements Copied: %d\n", numberOfElementsCopied)
fmt.Printf("dst: %v\n", dst)
fmt.Printf("src: %v\n", src)
//After changing numbers2
dst[0] = 10
fmt.Println("\nAfter changing dst")
fmt.Printf("dst: %v\n", dst)
fmt.Printf("src: %v\n", src)
}
輸出如下:
Number Of Elements Copied: 5
dst: [1 2 3 4 5]
src: [1 2 3 4 5]
After changing dst
dst: [10 2 3 4 5]
src: [1 2 3 4 5]
3. 總結
本文介紹了Go Array和Slice直接拷貝。Array是值類型直接賦值即拷貝,Slice是引用類型,直接賦值是指針會影響源Slice,但可以通過內置copy函數實現賦值功能。
補充:golang字節數組拷貝BlockCopy函數實現
在C#中,Buffer.BlockCopy(Array, Int32, Array, Int32, Int32) 函數使用比較廣泛,其含義:
將指定數目的字節從起始于特定偏移量的源數組復制到起始于特定偏移量的目標數組。
參數 src Array 源緩沖區。 srcOffset Int32 src 中的字節偏移量,從零開始。 dst Array 目標緩沖區。 dstOffset Int32 dst 中的字節偏移量,從零開始。 count Int32 要復制的字節數。
go語言中實現如下:
func blockCopy(src []byte, srcOffset int, dst []byte, dstOffset, count int) (bool, error) {
srcLen := len(src)
if srcOffset > srcLen || count > srcLen || srcOffset+count > srcLen {
return false, errors.New("源緩沖區 索引超出范圍")
}
dstLen := len(dst)
if dstOffset > dstLen || count > dstLen || dstOffset+count > dstLen {
return false, errors.New("目標緩沖區 索引超出范圍")
}
index := 0
for i := srcOffset; i srcOffset+count; i++ {
dst[dstOffset+index] = src[srcOffset+index]
index++
}
return true, nil
}
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
您可能感興趣的文章:- golang中的空slice案例
- golang-切片slice的創建方式
- Golang::slice和nil的對比分析
- golang語言如何將interface轉為int, string,slice,struct等類型
- Golang中的Slice與數組及區別詳解
- golang中range在slice和map遍歷中的注意事項
- golang slice元素去重操作