考虑结构和指针引用示例的以下代码。
package main
import (
"fmt"
"sync"
)
type myStruct struct {
mut *sync.RWMutex
}
type arrayOfMyStruct struct {
structList []myStruct
}
func main() {
k := &sync.RWMutex{}
myStructInstance := myStruct{k}
fmt.Printf("%p", &k) // address 1 -> address of k
fmt.Println("")
fmt.Printf("%p", &*k) // address 2 -> address of what k points to
fmt.Println("")
var listStruct []myStruct
listStruct = append(listStruct, myStructInstance)
test := &arrayOfMyStruct{listStruct}
test.access()
}
func (elem *arrayOfMyStruct) access() {
mystructinstance := &elem.structList[0]
mystructinstance2 := elem.structList[0]
fmt.Println(&mystructinstance.mut) // address 3
fmt.Println(&mystructinstance2.mut) // address 4
}
为什么地址2 3和4不同?他们不应该一样吗?
答案 0 :(得分:1)
这是因为mut
中的myStruct
已经是指针*sync.RWMutex
,所以当你这样做时:
&mystructinstance2.mut
您实际上正在获取一个指向mut
的新指针,该指针是指向**sync.RWMutex
之类的互斥锁的指针。只需删除打印语句中的&
即可。当您使用k := &sync.RWMutex{}
创建互斥锁时,它已经是指针,因此您不应该在该变量之后的任何地方使用&
,否则它将创建指向该指针的新指针。您还可以使用k := new(sync.RWMutex)
创建指向新互斥锁的指针。
您可以在Printf上使用%p
来打印指针地址:
fmt.Printf("%p\n", mystructinstance2.mut)
答案 1 :(得分:1)
地址1是指向互斥锁的指针的地址。地址2是互斥锁的地址。也就是说,互斥体位居住的位置为2点,2位指针位于1位置。使用%T
代替%p
进行打印会显示值的类型不同。
append
实际上复制了你的结构。 struct实例是一个像int
那样的值;当您将结构附加到列表时,实际上是在复制其中每个字段的值。
结构的值语义广泛用于C和Go(并且也存在于例如C#ValueTypes中),但在例如Java,JavaScript或Python中不太常见。它们意味着你有时候不得不考虑事物是否是指针,但是它们可以避免一些错误,因为它意外地在一个地方做了一个改变而在其他地方产生了影响(别名),并且减少了垃圾收集器指针的数量。跟随。
地址3是由append
创建的结构副本中的互斥锁指针的地址。
对mystructinstance2
的分配也会复制该值,因此现在有三个副本浮动。地址4是此新实例中互斥锁指针的地址。
答案 2 :(得分:1)
你想要
k := elem.structList[0].mut
p1 := &*k
或简单地说,
p2 := &*elem.structList[0].mut
例如,
package main
import (
"fmt"
"sync"
)
type myStruct struct {
mut *sync.RWMutex
}
type arrayOfMyStruct struct {
structList []myStruct
}
func main() {
k := &sync.RWMutex{}
myStructInstance := myStruct{k}
fmt.Printf("%p\n", &*k)
var listStruct []myStruct
listStruct = append(listStruct, myStructInstance)
test := &arrayOfMyStruct{listStruct}
test.access()
}
func (elem *arrayOfMyStruct) access() {
k := elem.structList[0].mut
p1 := &*k
fmt.Printf("%p\n", p1)
p2 := &*elem.structList[0].mut
fmt.Printf("%p\n", p2)
}
输出:
0xc4200142c0
0xc4200142c0
0xc4200142c0