golang中,import cycle not allowed,原理真的好解决吗?
In golang, import cycle not allowed, is the principle really a good solution?
我昨天在 github 问题上问过,其中一位贡献者说我应该在这个网站上问,所以我把我的问题贴在 Whosebug 上。
您使用的是哪个版本的 Go (go version
)?
$ go version
go version go1.17.1 windows/amd64
最新版本是否重现此问题?
是
您使用的是什么操作系统和处理器架构 (go env
)?
go env
输出
$ go env
你做了什么?
我写了简单的代码来尝试描述真实世界,但是“不允许导入循环”会编译错误。所以我只能把简单的代码重写成复杂的代码。
“不允许导入循环”是一个正确的原则,但这不是使代码简单的原则,它使代码更复杂。
是临时原则还是永久原则?
是经过多次考虑和讨论后设计的,还是仅出于个人喜好?
我问这个问题,因为我认为在现实世界中,一切事物都自然而然地相互作用。
比如一个老师进了一个教室,很多学生进了一个教室,然后老师选学生a问,然后学生b问老师。这是一个正常的简单要求。
但是在golang中,下面的代码无法编译成功,因为import cycle是不允许的。太奇怪了。
testgo
│ main.go
│
├─classroom
│ ClassRoom.go
│
├─student
│ Student.go
│
└─teacher
Teacher.go
// main.go
package main
import (
"testgo/classroom"
"testgo/student"
"testgo/teacher"
)
func main() {
c := &classroom.ClassRoom{}
t := &teacher.Teacher{}
a := &student.Student{}
b := &student.Student{}
t.Enter(c)
a.Enter(c)
b.Enter(c)
t.Ask(a)
b.Ask(t)
print(c)
}
// classroom/ClassRoom.go
package classroom
import (
"testgo/student"
"testgo/teacher"
)
type ClassRoom struct {
Teacher *teacher.Teacher
Students []*student.Student
}
func (c *ClassRoom) AddTeacher(t *teacher.Teacher) {
c.Teacher = t
}
func (c *ClassRoom) AddStudent(s *student.Student) {
c.Students = append(c.Students, s)
}
// teacher/Teacher.go
package teacher
import (
"testgo/classroom"
"testgo/student"
)
type Teacher struct {
TeacherName string
InClassRoom *classroom.ClassRoom
}
func (t *Teacher) Enter(c *classroom.ClassRoom) {
c.AddTeacher(t)
t.InClassRoom = c
}
func (t *Teacher) Ask(s *student.Student) {
}
// student/Student.go
package student
import (
"testgo/classroom"
"testgo/teacher"
)
type Student struct {
StudentName string
InClassRoom *classroom.ClassRoom
}
func (s *Student) Enter(c *classroom.ClassRoom) {
c.AddStudent(s)
s.InClassRoom = c
}
func (s *Student) Ask(t *teacher.Teacher) {
}
最后会出现如下编译错误
package testgo
imports testgo/classroom
imports testgo/student
imports testgo/classroom: import cycle not allowed
还有更多例子。
在现实世界中,猫捉老鼠,老鼠逃避猫。 package Cat
导入 package Rat
和 package Rat
导入 package Cat
.
在现实世界中,动物吃水果,动物吃水果。 package Animal
导入 package Fruit
和 package Fruit
导入 package Animal
.
在现实世界中,导入循环无处不在。
但是在golang中,导入循环是不允许的。
您希望看到什么?
启用导入循环,就像现实世界一样
你看到了什么?
不允许导入周期
这是一个永恒的原则。循环依赖增加了编译时间,而GO非常注重快速编译时间。
循环依赖的解决方案是在新包中引入新接口。此接口应具有循环依赖结构具有的所有方法,并可由其他循环依赖结构访问。
我找到了关于它的清晰注释https://medium.com/@ishagirdhar/import-cycles-in-golang-b467f9f0c5a0
校长是正确的,深思熟虑的。如果您了解并吸收您的用例,则可以避免循环。例如:- student class 应该只有学生相关的详细信息、姓名、年龄、地址等。class 应该有容量、地址等。应该有一个单独的 class 命名schedule.go 将保存 class、学生和教师的映射。
我昨天在 github 问题上问过,其中一位贡献者说我应该在这个网站上问,所以我把我的问题贴在 Whosebug 上。
您使用的是哪个版本的 Go (go version
)?
$ go version go version go1.17.1 windows/amd64
最新版本是否重现此问题?
是
您使用的是什么操作系统和处理器架构 (go env
)?
go env
输出$ go env
你做了什么?
我写了简单的代码来尝试描述真实世界,但是“不允许导入循环”会编译错误。所以我只能把简单的代码重写成复杂的代码。
“不允许导入循环”是一个正确的原则,但这不是使代码简单的原则,它使代码更复杂。
是临时原则还是永久原则?
是经过多次考虑和讨论后设计的,还是仅出于个人喜好?
我问这个问题,因为我认为在现实世界中,一切事物都自然而然地相互作用。
比如一个老师进了一个教室,很多学生进了一个教室,然后老师选学生a问,然后学生b问老师。这是一个正常的简单要求。
但是在golang中,下面的代码无法编译成功,因为import cycle是不允许的。太奇怪了。
testgo
│ main.go
│
├─classroom
│ ClassRoom.go
│
├─student
│ Student.go
│
└─teacher
Teacher.go
// main.go
package main
import (
"testgo/classroom"
"testgo/student"
"testgo/teacher"
)
func main() {
c := &classroom.ClassRoom{}
t := &teacher.Teacher{}
a := &student.Student{}
b := &student.Student{}
t.Enter(c)
a.Enter(c)
b.Enter(c)
t.Ask(a)
b.Ask(t)
print(c)
}
// classroom/ClassRoom.go
package classroom
import (
"testgo/student"
"testgo/teacher"
)
type ClassRoom struct {
Teacher *teacher.Teacher
Students []*student.Student
}
func (c *ClassRoom) AddTeacher(t *teacher.Teacher) {
c.Teacher = t
}
func (c *ClassRoom) AddStudent(s *student.Student) {
c.Students = append(c.Students, s)
}
// teacher/Teacher.go
package teacher
import (
"testgo/classroom"
"testgo/student"
)
type Teacher struct {
TeacherName string
InClassRoom *classroom.ClassRoom
}
func (t *Teacher) Enter(c *classroom.ClassRoom) {
c.AddTeacher(t)
t.InClassRoom = c
}
func (t *Teacher) Ask(s *student.Student) {
}
// student/Student.go
package student
import (
"testgo/classroom"
"testgo/teacher"
)
type Student struct {
StudentName string
InClassRoom *classroom.ClassRoom
}
func (s *Student) Enter(c *classroom.ClassRoom) {
c.AddStudent(s)
s.InClassRoom = c
}
func (s *Student) Ask(t *teacher.Teacher) {
}
最后会出现如下编译错误
package testgo
imports testgo/classroom
imports testgo/student
imports testgo/classroom: import cycle not allowed
还有更多例子。
在现实世界中,猫捉老鼠,老鼠逃避猫。 package Cat
导入 package Rat
和 package Rat
导入 package Cat
.
在现实世界中,动物吃水果,动物吃水果。 package Animal
导入 package Fruit
和 package Fruit
导入 package Animal
.
在现实世界中,导入循环无处不在。
但是在golang中,导入循环是不允许的。
您希望看到什么?
启用导入循环,就像现实世界一样
你看到了什么?
不允许导入周期
这是一个永恒的原则。循环依赖增加了编译时间,而GO非常注重快速编译时间。
循环依赖的解决方案是在新包中引入新接口。此接口应具有循环依赖结构具有的所有方法,并可由其他循环依赖结构访问。
我找到了关于它的清晰注释https://medium.com/@ishagirdhar/import-cycles-in-golang-b467f9f0c5a0
校长是正确的,深思熟虑的。如果您了解并吸收您的用例,则可以避免循环。例如:- student class 应该只有学生相关的详细信息、姓名、年龄、地址等。class 应该有容量、地址等。应该有一个单独的 class 命名schedule.go 将保存 class、学生和教师的映射。