亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

將結構屬性(切片)傳遞給從中刪除元素的函數時的奇怪行為

將結構屬性(切片)傳遞給從中刪除元素的函數時的奇怪行為

Go
哈士奇WWW 2022-01-10 17:49:44
這些天我開始學習 Go 并陷入嘗試將結構屬性的值(切片)傳遞給函數的過程中。顯然它是作為引用傳遞的(或者它持有指向其切片的指針),并且在函數內部所做的更改會影響它。這是我的代碼,它testFunction應該接收一個切片,刪除它的前 3 個元素并打印更新的值,但不會在外部影響它:package mainimport (    "fmt")type testStruct struct {    testArray []float64}var test = testStruct {    testArray: []float64{10,20,30,40,50},}func main() {    fmt.Println(test.testArray)    testFunction(test.testArray)    fmt.Println(test.testArray)}func testFunction(array []float64) {    for i:=0; i<3; i++ {        array = removeFrom(array, 0)    }    fmt.Println(array)}func removeFrom(array []float64, index int) []float64 {    return append(array[:index], array[index+1:]...)}輸出:[10 20 30 40 50][40 50][40 50 50 50 50]我的問題是:是什么導致第三個fmt.Println打印出這個奇怪的結果?游樂場:https : //play.golang.org/p/G8W3H085Inps:這段代碼只是一個例子。刪除某些東西的第一個元素不是我的目標。我只想知道是什么導致了這種奇怪的行為。
查看完整描述

3 回答

?
慕萊塢森

TA貢獻1810條經驗 獲得超4個贊

通常我們不知道給定的 append 調用是否會導致重新分配,因此我們不能假設原始切片與結果切片引用相同的數組,也不能假設它引用不同的數組。


要正確使用切片,重要的是要記住雖然底層數組的元素是間接的,但切片的指針、長度和容量卻不是。


因此,通常將調用的結果分配給 append 到同一個切片變量:


array = append(array, ...)

總而言之,要獲得所需的結果,請始終記住將 append 函數分配給新的或相同的切片變量。


這是更正且有效的代碼:


package main


import (

    "fmt"

)


type testStruct struct {

    testArray []float64

}


var test = testStruct {

    testArray: []float64{10,20,30,40,50},

}


func main() {

    fmt.Println(test.testArray)

    a := testFunction(test.testArray)

    fmt.Println(a)

}


func testFunction(array []float64)[]float64 {

    for i:=0; i<3; i++ {

        array = removeFrom(array, 0)

    }

    fmt.Println(array)

    return array

}


func removeFrom(array []float64, index int) []float64 {

    return append(array[:index], array[index+1:]...)

}

檢查它的工作代碼Go Playground。


另一種解決方案是通過指針引用傳遞數組參數:


func testFunction(array *[]float64) {

    for i:=0; i<3; i++ {

        *array = removeFrom(*array, 0)

    }

    fmt.Println(*array)

}


查看完整回答
反對 回復 2022-01-10
?
犯罪嫌疑人X

TA貢獻2080條經驗 獲得超4個贊

切片是復合類型。它有一個指向數據、長度和容量的指針。當您將它作為參數傳遞時,您將傳遞這些值、指針、長度和容量;它們總是副本。

在您的情況下,您在調用時修改切片中的數據removeFrom(),您可以這樣做,因為您已將指向原始數據的指針的值復制到 func 中,但長度和容量在該函數范圍之外保持不變那些不是指針。

因此,當您再次打印它時,main()您會看到更改后的值,但它仍然使用原始長度和容量,因為對其他函數范圍內的那些所做的任何更改實際上都是在這些值的副本上。


查看完整回答
反對 回復 2022-01-10
?
呼喚遠方

TA貢獻1856條經驗 獲得超11個贊

這是一篇關于切片的有用博客文章https://blog.golang.org/slices。它特別說明了這一點。

重要的是要理解即使切片包含指針,它本身也是一個值。在幕后,它是一個包含指針和長度的結構值。它不是指向結構的指針。

您看到的原因[40 50 50 50 50]是因為您更改了切片中的值,但您沒有更改切片本身(它是 cap 和 len)


查看完整回答
反對 回復 2022-01-10
  • 3 回答
  • 0 關注
  • 176 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號