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 Ratpackage Rat 导入 package Cat.

在现实世界中,动物吃水果,动物吃水果。 package Animal 导入 package Fruitpackage Fruit 导入 package Animal.

在现实世界中,导入循环无处不在。

但是在golang中,导入循环是不允许的。

您希望看到什么?

启用导入循环,就像现实世界一样

你看到了什么?

不允许导入周期

这是一个永恒的原则。循环依赖增加了编译时间,而GO非常注重快速编译时间。

循环依赖的解决方案是在新包中引入新接口。此接口应具有循环依赖结构具有的所有方法,并可由其他循环依赖结构访问。

我找到了关于它的清晰注释https://medium.com/@ishagirdhar/import-cycles-in-golang-b467f9f0c5a0

校长是正确的,深思熟虑的。如果您了解并吸收您的用例,则可以避免循环。例如:- student class 应该只有学生相关的详细信息、姓名、年龄、地址等。class 应该有容量、地址等。应该有一个单独的 class 命名schedule.go 将保存 class、学生和教师的映射。