2016-02-26 50 views
2

我有一個代碼塊,查詢AD和檢索結果並寫入一個通道。在Golang中將一個局部變量的指針傳遞給一個通道是否安全?

func GetFromAD(connect *ldap.Conn, ADBaseDN, ADFilter string, ADAttribute []string, ADPage uint32) *[]ADElement { 

    searchRequest := ldap.NewSearchRequest(ADBaseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, ADFilter, ADAttribute, nil) 
    sr, err := connect.SearchWithPaging(searchRequest, ADPage) 
    CheckForError(err) 
    fmt.Println(len(sr.Entries)) 
    ADElements := []ADElement{} 
    for _, entry := range sr.Entries{ 
     NewADEntity := new(ADElement) //struct 
     NewADEntity.DN = entry.DN 
     for _, attrib := range entry.Attributes { 
      NewADEntity.attributes = append(NewADEntity.attributes, keyvalue{attrib.Name: attrib.Values}) 
     } 
     ADElements = append(ADElements, *NewADEntity) 
    } 
    return &ADElements 
} 

上述函數返回指向[]ADElements的指針。

而且在我initialrun功能,我稱之爲像

ADElements := GetFromAD(connectAD, ADBaseDN, ADFilter, ADAttribute, uint32(ADPage)) 
fmt.Println(reflect.TypeOf(ADElements)) 
ADElementsChan <- ADElements 

此功能,而且輸出表示

*[]somemodules.ADElement 

reflect.TypeOf輸出。

我在這裏的疑問是, 因爲在GetFromAD()定義ADElements := []ADElement{}是一個局部變量,必須在堆棧中分配,而當GetFromAD()退出時,堆棧的內容必須被銷燬,並GetFromAD()進一步引用必須指向無效的內存引用,而我仍然得到GetFromAD()沒有任何段錯誤返回的元素的確切數目。這是如何工作的?這樣做安全嗎?

+3

Go在這裏完全沒有問題。 – Volker

+0

謝謝@Volker。但是我想知道它是如何工作:) – nohup

回答

2

是的,它是安全的,因爲圍棋編譯器執行逃逸分析和堆分配這些變量。

退房FAQ - How do I know whether a variable is allocated on the heap or the stack?

存儲位置確實有編寫高效的程序的影響。如果可能的話,Go編譯器將爲該函數的堆棧幀中的函數分配本地變量。但是,如果編譯器無法證明變量在函數返回後未被引用,則編譯器必須在垃圾回收堆上分配變量以避免指針錯誤。另外,如果局部變量非常大,將其存儲在堆而不是堆棧上可能更有意義。

+0

謝謝。這是完全有道理的,爲什麼它的工作:) – nohup

1

定義「安全」 ...

你會不會最終釋放的ADElements的記憶,因爲有至少一個活的引用。

在這種情況下,你應該是完全安全的,因爲你只有通過切片一次,然後你似乎沒有修改,但在一般情況下,它可能會更好跨越傳遞元素的元素一個chan ADElement,以避免多次非同步訪問切片(或者更具體地說,支持切片的數組)。

這也適用於地圖,如果您通過頻道傳遞地圖,然後繼續訪問地圖,您可能會遇到好奇的問題。

+0

謝謝@Vatine。起初,我在想,函數不知道下游引用,它是如何工作的。弄清楚了。 – nohup

相關問題