Golang包循环依赖问题 引用 struct 相互引用
http://www.aidsay.com/golange58c85e5beaae78eafe4be9de8b596e997aee9a298/
Golang使用下面的语法导入一个包:
import (
"pkgname"
)
pkgname其实是一个目录的相对路径,在该目录下所有Golang源文件(.go)声明的包名都必须是其所在的目录名(main包除外),即pkgname目录下每个Golang源文件(.go)都必须有:
package pkgname
包下的源文件名除了后缀“.go”外并不重要。
下面我们看看Golang包循环依赖问题;在项目中,总有分处在不同包的两个模块需要互相调用对方成员的情况出现,例如:
a.go:
package a
import "test/b"
var n = 1
func GetN() int {
return n
}
func Sum() int {
return n + b.GetN()
}
b.go:
package b
import "test/a"
var n = 1
func GetN() int {
return n
}
func Sum() int {
return n + a.GetN()
}
test.go:
package main
import (
"test/a"
"test/b"
"fmt"
)
func main() {
fmt.Println(a.Sum())
fmt.Println(b.Sum())
}
Golang是不支持循环依赖的,所以编译会得到以下错误输出信息:
import cycle not allowed
package test/a
imports test/b
imports test/a
要解决这个问题可以使用接口,我们将上面的代码改写一下并且添加一个用于定义接口的包,代码如下:
er.go:
package er
type A interface {
Sum()int
GetN()int
}
type B interface {
Sum()int
GetN()int
}
a.go:
package a
import "test/er"
var n = 1
func (a *A)GetN()int{
return n
}
func (a *A)Sum()int{
return n + a.b.GetN()
}
/***************************************/
type A struct {
b er.B
}
func NewA()*A{
return new(A)
}
func (a *A)SetB(b er.B){
a.b = b
}
b.go:
package b
import "test/er"
var n = 1
func (b *B)GetN()int{
return n
}
func (b *B)Sum()int{
return n + b.a.GetN()
}
/**************************************/
type B struct {
a er.A
}
func NewB()*B{
return new(B)
}
func (b *B)SetA(a er.A){
b.a = a
}
test.go:
package main
import (
"test/a"
"test/b"
"fmt"
)
func main() {
A := a.NewA()
B := b.NewB()
A.SetB(B)
B.SetA(A)
fmt.Println(A.Sum())
fmt.Println(B.Sum())
}
编译运行:
2
2
上面的代码将模块需要向外暴露的成员用一个类封装起来(门面模式),两模块间成员的引用就变成了两个类间的互相调用,之后对这两个类分别进行抽象(接口),使两个类间的依赖变成对对方接口的依赖,从而避开了类(包)循环依赖的问题。