将局部变量的指针传递给Golang中的通道是否安全?

时间:2016-02-26 10:24:45

标签: pointers go struct stack

我有一个代码块,用于查询AD并检索结果并写入通道。

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的输出。

我怀疑的是, 由于ADElements := []ADElement{}中定义的GetFromAD()是局部变量,因此必须在堆栈中分配,并且当GetFromAD()退出时,必须销毁堆栈的内容,并进一步引用{{1}必须指向无效的内存引用,而我仍然得到GetFromAD()返回的元素的确切数量而没有任何段错误。这是怎么回事?这样做是否安全?

2 个答案:

答案 0 :(得分:3)

是的,它是安全的,因为Go编译器执行转义分析并在堆上分配这些变量。

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

  

存储位置确实会影响编写高效的程序。如果可能,Go编译器将为该函数的堆栈帧中的函数分配本地变量。但是,如果编译器在函数返回后无法证明变量未被引用,则编译器必须在垃圾收集堆上分配变量以避免悬空指针错误。此外,如果局部变量非常大,将它存储在堆而不是堆栈上可能更有意义。

答案 1 :(得分:1)

定义“安全”......

你最终不会释放ADElements的记忆,因为它至少有一个实时参考。

在这种情况下,你应该是完全安全的,因为你只是传递一次切片,然后你似乎没有修改它,但在一般情况下,最好是逐个元素地传递它。 chan ADElement,以避免对切片进行多次非同步访问(或者更具体地说,是支持切片的阵列)。

这也适用于地图,如果您通过频道传递地图,然后继续访问它,您可能会遇到奇怪的问题。