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

noh*_*hup 5 stack struct pointers go

我有一个代码块,用于查询 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
}
Run Code Online (Sandbox Code Playgroud)

上面的函数返回一个指向[]ADElements.

在我的initialrun函数中,我称这个函数为

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

输出说

*[]somemodules.ADElement
Run Code Online (Sandbox Code Playgroud)

作为 的输出reflect.TypeOf

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

Grz*_*Żur 5

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

查看FAQ - 我如何知道一个变量是分配在堆上还是堆栈上?

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