我有一个代码块,用于查询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()
返回的元素的确切数量而没有任何段错误。这是怎么回事?这样做是否安全?
答案 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
,以避免对切片进行多次非同步访问(或者更具体地说,是支持切片的阵列)。
这也适用于地图,如果您通过频道传递地图,然后继续访问它,您可能会遇到奇怪的问题。