I had ask it in github issue yesterday, and one of the contributors say that I should ask it at this site, so I just paste my question at stackoverflow.
What version of Go are you using (go version
)?
$ go version go version go1.17.1 windows/amd64
Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (go env
)?
go env
Output$ go env
What did you do?
I write simple code to try to describe real world, but "Import cycle not allowed" will compile error. So I could only rewrite the simple code to complex code.
"Import cycle not allowed" is a right principle, but it is not a principle to makes code simple, it makes code more complex.
Is it a temporary principle or a permanent principle?
Is it designed after many consider and discuss, or only for personal preference?
I ask this question, because I think in real world, everything interacts with each other naturally.
For example, a teacher enter a classroom, many students enter a classroom, then teacher choose student a to ask, then the student b ask teacher. It is a normal simple requirement.
But in golang, the below code could not compile success, because import cycle not allowed. It is so strange.
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) {
}
Finally, it will compile error like below
package testgo
imports testgo/classroom
imports testgo/student
imports testgo/classroom: import cycle not allowed
There are more examples.
In real world, Cat catch Rat, Rat escape from Cat. package Cat
import package Rat
, and package Rat
import package Cat
.
In real world, Animal eat Fruit, Fruit be eat by Animal. package Animal
import package Fruit
, and package Fruit
import package Animal
.
In real world, import cycle occur everywhere.
But in golang, import cycle not allowed.
What did you expect to see?
enable import cycle, just like the real world
What did you see instead?
import cycle not allowed
CodePudding user response:
It is a permanent principle. Circular dependencies increase compile time and GO is highly focused on fast compile time.
A solution to circular dependency is introducing a new interface in a new package. This interface should have all the methods that a circular dependent struct have and accessed by other circular dependent struct.
I found a clear notes about it https://medium.com/@ishagirdhar/import-cycles-in-golang-b467f9f0c5a0
CodePudding user response:
It is correct and well thought principal. If you understand and imbibe your use-case, you can avoid cycles. For eg:- student class should only have student related details, names, age, address etc etc. class should have things like capacity, address etc. There should be a separate class named schedule.go which would hold the mapping of class, student and teacher.