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

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

在 Go 中分配切片與重新聲明切片

在 Go 中分配切片與重新聲明切片

Go
長風秋雁 2022-08-24 10:29:38
我試圖使用切片作為隊列數據結構,我想出了這個實現,這導致了一個無限循環。這是因為切片不會使用子切片 進行更新。queuequeue[1:]func badQueue() {    queue := []int{0,1,2,3,4,5}    for len(queue) > 0 {        current, queue := queue[0], queue[1:]        fmt.Println(current, queue)    }}0 [1 2 3 4 5]0 [1 2 3 4 5]0 [1 2 3 4 5]0 [1 2 3 4 5]0 [1 2 3 4 5]...我已經發現這個問題與我正在重新聲明和(with)而不是分配值的事實有關,這解決了這個問題:currentqueue:=func goodQueue() {    queue := []int{0,1,2,3,4,5}    var current int    for len(queue) > 0 {        current, queue = queue[0], queue[1:]        fmt.Println(current, queue)    }}0 [1 2 3 4 5]1 [2 3 4 5]2 [3 4 5]3 [4 5]4 [5]5 []我知道導致問題的原因,但我不完全理解為什么在這種情況下的重新聲明操作與分配的工作方式不同。為什么不使用隊列 () 的子切片重新聲明隊列?queue[1:]謝謝!
查看完整描述

3 回答

?
牛魔王的故事

TA貢獻1830條經驗 獲得超3個贊

因為可以有多個具有相同名稱的變量,只要它們具有不同的作用域即可。內部作用域中的變量將遮蔽外部作用域中的變量。


因此,如果我們分解您的示例


func badQueue() {

    // queue from outer scope, lets call it A

    queue := []int{0,1,2,3,4,5}

    // the only visible queue here is A, so len(queue) will always refer to A

    for len(queue) > 0 {

        // same thing here, the only visible queue is A, so queue[0] and queue[1:]

        // both refer to A

        // We are also declaring new variables, queue and current

        // This queue is now shadowing the outer queue, let's call this one B

        current, queue := queue[0], queue[1:]


        // Here queue will refer to B

        fmt.Println(current, queue)


        // When the current iteration of the loop ends current and queue B is destroyed

        // because they go out of scope and the loop start over with A unchanged

    }

}


查看完整回答
反對 回復 2022-08-24
?
SMILET

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

短聲明情況下的變量的作用域僅限定為循環的主體,即每次新迭代都銷毀和創建。如短變量聲明中引用queue

與常規變量聲明不同,短變量聲明可以重新聲明變量,前提是它們最初是在同一塊(或者如果塊是函數體,則參數列表)中以相同類型聲明的,并且至少有一個非空白變量是新的。因此,重新聲明只能出現在多變量短聲明中。重新聲明不會引入新變量;它只是為原始值分配一個新值。


查看完整回答
反對 回復 2022-08-24
?
qq_笑_17

TA貢獻1818條經驗 獲得超7個贊

要了解它在 Go 中的工作原理,需要兩點:


范圍


Go 使用塊作用域,每個大括號對將創建一個新作用域,如果內部作用域中的標識符具有相同的聲明名稱,則它們將隱藏外部作用域中的標識符。


 func main() {

     var name string = "Golang"

     fmt.Printf("Outer Scope: %s\n", name) // Print "Golang"

     {

         var name string = "Java"

         fmt.Printf("Inner Scope: %s\n", name)   // Print "Java"

     }   

     fmt.Printf("Outer Scope: %s\n", name)  // Print "Golang" again

  }

短變量聲明


Operator是一個復合操作,它將在一個語句中做幾件事:聲明,類型推斷和賦值,基本上你可以把它當作一個語法糖。以下 S1 和 S2 的代碼示例是等效的::=


func main() {

    // S1

    var name string = "Golang" 


    // S2

    name := "Golang"

}

考慮到以上兩點,您的代碼在翻譯后將如下所示:


func badQueue() {

    queue := []int{0,1,2,3,4,5}

    for len(queue) > 0 {

        var current int

        var queue []int

        current, queue = queue[0], queue[1:]

        fmt.Println(current, queue)

    }

}

很明顯,外部不受影響內部循環。queuefor


順便說一句,對于左側的每個變量,編譯器將查找當前塊范圍以嘗試解析標識符,如果之前已經聲明過,編譯器將重用它而不是創建一個新的。但是,如果之前聲明了所有 lhs 變量,編譯器將報告一個錯誤,并顯示消息“:=的左側沒有新變量”。請查看以下代碼::=


func main() {

    var name string

    name, age := "Golang", 10 // reuse the above 'name' and create a new variable 'age'


    var tom, jerry string

    tom, jerry := "Tom", "Jerry" // no new variables on left side of :=

}

新的編譯器實現在這里,適合那些對細節感興趣的人。


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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