1 回答
TA贡献1825条经验 获得超4个赞
为了能够以您想要的方式使用指针,您首先需要实际的指针(即不是nil指针),并且您还需要使用指针间接来能够“共享”对指向值的更新。
例如:
type T struct { F string }
a := &T{"foo"} // non-nil pointer
b := a
fmt.Println(b) // output: {"foo"}
*a = T{"bar"} // pointer indirection
fmt.Println(b) // output: {"bar"}
为了比较,这是您的代码尝试执行的操作:
type T struct { F string }
a := (*T)(nil) // nil pointer
b := a
fmt.Println(b) // output: <nil>
a = &T{"bar"} // plain assignment
fmt.Println(b) // output: <nil>
请注意,即使您使用了指针间接,在nil指针上这样做也是非法的,并且运行时如果遇到这样的操作,将会恐慌。
a := (*T)(nil) // nil pointer
b := a
fmt.Println(b) // output: <nil>
*a = T{"bar"} // pointer indirection on nil, will crash the program
fmt.Println(b)
因此,您的示例不起作用,因为它没有正确初始化指针并且它不使用指针间接,而是使用简单的赋值,它只更新目标变量的指针而不是指向的值。
要正确初始化容器,您应该一步完成:
func NewContainer() *container {
c := &container{a: &A{}}
c.r = &R{a: c.a}
c.a.r = c.r
return c
}
https://play.golang.com/p/hfbqJEVyAHZ
或者,如果你想分两次做,你可以这样做:
func (c *container) NewA() *A {
log.Println("New A received c.r: ", c.r)
a := &A{
r: c.r,
}
if c.a != nil {
*c.a = *a
} else {
c.a = a
}
return a
}
func (c *container) NewR() *R {
if c.a == nil {
c.a = new(A)
}
r := &R{
a: c.a,
}
c.r = r
c.a.r = r
return r
}
https://play.golang.com/p/krmUQOsACdU
但是,正如您所看到的,初始化如此紧密耦合的依赖项的多步骤方法可能会变得不必要地复杂和丑陋,即复杂,即非常容易出错。如果可以的话,避免它。
综上所述,就个人而言,我会认为这种循环依赖是一种气味,并会开始考虑重新设计,但也许这只是我。
- 1 回答
- 0 关注
- 203 浏览
添加回答
举报
