I have encountered an import cycle problem. I read some blogs but didn't understand them. This is the sample code that I have written.
file1.go
package dir1
type Filo interface {
File2(string) string
}
func File1(message string) string {
var f Filo
importFile2 := f.File2("file 2")
return "Welcome to " + message + " and message from file 2: " + importFile2
}
file2.go
package dir2
import "github.com/ibilalkayy/app/dir1"
func File2(message string) string {
importFile1 := dir1.File1("file 1")
return "Welcome to " + message + " and message from file 1: " + importFile1
}
main.go
package main
import (
"fmt"
"github.com/ibilalkayy/app/dir1"
"github.com/ibilalkayy/app/dir2"
)
func main() {
fmt.Println("Hello world")
first := dir1.File1("file 1")
second := dir2.File2("file 2")
fmt.Println(first)
fmt.Println(second)
}
The desire for an import cycle is usually an indication there is something wrong with the design.
There are 2 general solutions to avoid import cycles:
For example, the following contrived example won't compile due to the import cycle:
package main
import "example.com/base"
import "example.com/other"
func main() {
f := &other.Foo{}
_ = base.Process(f)
}
package base
import "example.com/other"
func Process(f *other.Foo) {
for {
if err := f.Frob(); err != nil {
return err
}
}
}
package other
import "example.com/base"
type Foo int
func (f *foo) Frob(name string) error {
if *f == 0 {
return errors.New("completed")
}
*f--
return base.Process(f)
}
This can be fixed by changing base
to use an interface:
package base
type Frobber interface {
Frob(string) error
}
func Process(f Frobber) error {
for {
if err := f.Frob("some file"); err != nil {
return err
}
}
}
This works since *other.Foo
can to passed to base.Process
without the base
package needing to know anything about the other
package.
Another option is to use function variables:
// Given:
package other
import "example.com/base"
type Foo struct {}
func (f *Foo) Frob(name string) error
package base
import "example.com/other"
func Process(f *Foo) error
// Use this instead:
package base
func Process(fn func(string) error) error
// Which enables using:
package main
import "example.com/other"
func main() {
f := &other.Foo{} // NOTE: This needs to be real an initialised.
Process(f.Frob)
}
The example in the question is fundamentally broken beyond the import cycle. It will run out of stack space due to mutual recursion. Ignoring that, you can get it to compile with an untyped func
. Eg:
func File1(fn func(string) string) string {
return "Welcome to message from file 2: " + fn("some file")
}
// Call with:
func something(name string) string {
return "foo/" + name
}
dir1.File1(something)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.