關於Golang中range指針數據的坑詳解

這篇文章主要給大家介紹了關於Golang中range指針數據的坑的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨着小編來一起學習學習吧

前言

在Golang中使用 for range 語句進行迭代非常的便捷,但在涉及到指針時就得小心一點了。

下面的代碼中定義了一個元素類型爲 *int 的通道 ch :

package main

import (
 "fmt"
)

func main() {
 ch := make(chan *int, 5)
 
 //sender
 input := []int{1,2,3,4,5}
 
 go func(){
  for _, v := range input {
   ch <- &v
  }
  close(ch)
 }()
 //receiver
 for v := range ch {
  fmt.Println(*v)
 }
}

在上面代碼中,發送方將 input 數組發送給 ch 通道,接收方再從 ch 通道中接收數據,程序的預期輸出應該是:

現在運行一下程序,得到的輸出如下:

很明顯,程序並沒有達到預期的結果,那麼問題出在哪裏呢?我們將代碼稍作修改:

//receiver
  for v := range ch {
    fmt.Println(v)
  }

得到如下輸出:

0x416020
0x416020
0x416020
0x416020
0x416020

可以看到,5次輸出變量 v ( *int )都指向了同一個地址,返回去檢查一下發送部分代碼:

for _, v := range input {
  ch <- &v
}

問題正是出在這裏,在 for range 語句中, v 變量用於保存迭代 input 數組所得的值,但是 v 只被聲明瞭一次,此後都是將迭代 input 出的值賦值給 v , v 變量的內存地址始終未變,這樣再將 v 的地址發送給 ch 通道,發送的都是同一個地址,當然無法達到預期效果。

解決方案:

引入一箇中間變量,每次迭代都重新聲明一個變量 temp ,賦值後再將其地址發送給 ch :

for _, v := range input {
  temp := v
  ch <- &temp
}

抑或直接引用數據的內存(推薦,無需開闢新的內存空間):

for k, _ := range input {
  c <- &input[k]
}

再次運行,就可看到預期的效果。以上方案是用於討論 range 語句帶來的問題,當然,平時還是儘量避免使用指針類型的通道。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對神馬文庫的支持。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章