# #go #import
Вопрос:
Вчера я задал этот вопрос в выпуске github, и один из участников сказал, что я должен задать его на этом сайте, поэтому я просто вставляю свой вопрос в stackoverflow.
Какую версию Go вы используете ( go version
)?
$ go версия go версия go1.17.1 windows / amd64
Воспроизводится ли эта проблема в последней версии?
ДА
Какую операционную систему и архитектуру процессора вы используете ( go env
)?
go env
Вывод
$ go env
Что вы сделали?
Я пишу простой код, чтобы попытаться описать реальный мир, но «Цикл импорта не разрешен» приведет к ошибке компиляции. Поэтому я мог только переписать простой код в сложный код.
«Цикл импорта запрещен» — это правильный принцип, но это не принцип, который упрощает код, он делает код более сложным.
Это временный принцип или постоянный принцип?
Он разработан после многих размышлений и обсуждений или только для личных предпочтений?
Я задаю этот вопрос, потому что я думаю, что в реальном мире все взаимодействует друг с другом естественным образом.
Например, учитель входит в класс, многие ученики входят в класс, затем учитель выбирает ученика a, чтобы спросить, затем ученик b спрашивает учителя. Это обычное простое требование.
Но в golang приведенный ниже код не смог успешно скомпилироваться, потому что цикл импорта не разрешен. Это так странно.
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 := amp;classroom.ClassRoom{}
t := amp;teacher.Teacher{}
a := amp;student.Student{}
b := amp;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 цикл импорта запрещен.
Что вы ожидали увидеть?
включить цикл импорта, как в реальном мире
Что вы увидели вместо этого?
цикл импорта не разрешен
Комментарии:
1. Это постоянный принцип, основанный на тщательном обдумывании. Размещайте взаимозависимые типы в одних и тех же пакетах или используйте интерфейсы для прерывания циклов.
2. Не создавайте крошечные пакеты для отдельных типов.
Ответ №1:
Это правильный и хорошо продуманный принцип. Если вы понимаете и впитываете свой вариант использования, вы можете избежать циклов. Например: — класс student должен иметь только сведения, связанные с учеником, имена, возраст, адрес и т. Д. И т. Д. класс должен иметь такие параметры, как емкость, адрес и т.д. Должен быть отдельный класс с именем schedule .go, который будет содержать отображение класса, ученика и учителя.
Комментарии:
1. Хорошо, спасибо за ответ на вопрос. Поскольку принцип соблюдается, мне придется переписать код, чтобы подчиниться ему, это займет гораздо больше времени, но другого решения нет.
Ответ №2:
Это постоянный принцип. Циклические зависимости увеличивают время компиляции, а GO сильно ориентирован на быстрое время компиляции.
Решением циклической зависимости является введение нового интерфейса в новый пакет. Этот интерфейс должен иметь все методы, которые есть у циклической зависимой структуры, и к которым имеет доступ другая циклическая зависимая структура.
Я нашел четкие заметки об этом https://medium.com/@ishagirdhar/import-cycles-in-golang-b467f9f0c5a0
Комментарии:
1. Хорошо, спасибо за ответ на вопрос. Теперь я знаю, что этот принцип является постоянным. И почти все говорят, что это осторожный принцип. Поэтому я изменю свой код.