Golang報(bào)“import cycle not allowed”錯(cuò)誤的2種解決方法
前言
相信不少 Gopher 在寫 Golang 程序都遇到過 import cycle not allowed 問題,本人最近研讀 go-ethereum 源碼時(shí),發(fā)現(xiàn)定義 interface 也能解決此問題, 還能解決連分包都不能解決的情況, 并且比分包更加簡單快捷。下面逐個(gè)講解 分包 和 定義接口 這兩種方法。
1. 應(yīng)用場景
假設(shè)有如下使用場景:
A 是應(yīng)用程序的框架級結(jié)構(gòu)體,在 A 包含子模塊 B 和 C 的指針;
B 為了方便的使用應(yīng)用的其他子模塊(比如 C )功能,所以在其結(jié)構(gòu)體包含了 A 的指針;
C 要調(diào)用 A 包中的某個(gè)方法;
2. 代碼實(shí)現(xiàn)
其程序大致如下:
package a 代碼如下:
package a import ( "fmt" "github.com/ggq89/mutualdep/b" "github.com/ggq89/mutualdep/c" ) type A struct { Pb *b.B Pc *c.C } func New(ic int) *A { a := &A{ Pc: c.New(ic), } a.Pb = b.New(a) return a } func Printf(v int) { fmt.Printf("%v", v) }
package b 代碼如下:
package b import ( "github.com/ggq89/mutualdep/a" ) type B struct { Pa *a.A } func New(a *a.A) *B { return &B{ Pa: a, } } func (b *B) DisplayC() { b.Pa.Pc.Show() }
package c 代碼如下:
package c import "github.com/ggq89/mutualdep/a" type C struct { Vc int } func New(i int) *C { return &C{ Vc: i, } } func (c *C) Show() { a.Printf(c.Vc) }
package a 依賴 package b 和 package c,同時(shí) package b 依賴 package a 、 package c 也依賴 package a 。
main 函數(shù)代碼如下:
package main import "github.com/ggq89/mutualdep/a" func main() { a := a.New(3) a.Pb.DisplayC() }
編譯時(shí)就會報(bào)錯(cuò)如下:
import cycle not allowed
package main
imports github.com/ggq89/mutualdep/a
imports github.com/ggq89/mutualdep/b
imports github.com/ggq89/mutualdep/a
3. 定義接口
現(xiàn)在的問題是:
A depends on B
B depends on A
對于 A struct 和 B struct 有彼此的指針這種相互依賴問題,可以使用定義接口的方法解決,具體步驟如下:
在 package b 中 定義 a interface ; 將 b 所有使用到結(jié)構(gòu)體 a 的變量和方法的地方全部轉(zhuǎn)化成 使用接口 a 的方法;在 a interface 中補(bǔ)充缺少的方法;
經(jīng)過上面的步驟處理后, package b 代碼如下:
package b import ( "github.com/ggq89/mutualdep/c" ) type B struct { Pa a } type a interface { GetC() *c.C } func New(a a) *B { return &B{ Pa:a, } } func (b *B) DisplayC() { b.Pa.GetC().Show() }
在 package a 中補(bǔ)充可能缺少的方法;
處理后, package a 中的代碼如下:
package a import ( "fmt" "github.com/ggq89/mutualdep/b" "github.com/ggq89/mutualdep/c" ) type A struct { Pb *b.B Pc *c.C } func New(ic int) *A { a := &A{ Pc:c.New(ic), } a.Pb = b.New(a) return a } func (a *A)GetC() *c.C { return a.Pc } func Printf(v int) { fmt.Printf("%v", v) }
4. 拆分包
再次編譯,提示如下:
import cycle not allowed
package main
imports github.com/ggq89/mutualdep/a
imports github.com/ggq89/mutualdep/b
imports github.com/ggq89/mutualdep/c
imports github.com/ggq89/mutualdep/a
現(xiàn)在是另一個(gè)相互依賴問題:
A depends on C
C depends on A
與前面的相互依賴不同,前面的依賴是由于 A struct 和 B struct 有彼此的指針導(dǎo)致的,屬于硬相互依賴;
而這里是由于 package c 中的方法調(diào)用 package a 中的方法引起的,屬于軟相互依賴;
- 這種相互依賴可以通過將方法拆分到另一個(gè)包的方式來解決;在拆分包的過程中,可能會將結(jié)構(gòu)體的方法轉(zhuǎn)化為普通的函數(shù);
引入 package f , 將方法遷移到 f 中 :
package f import "fmt" func Printf(v int) { fmt.Printf("%v", v) }
方法移動到 package f 后, package a 的代碼如下:
package a import ( "github.com/ggq89/mutualdep/b" "github.com/ggq89/mutualdep/c" ) type A struct { Pb *b.B Pc *c.C } func New(ic int) *A { a := &A{ Pc: c.New(ic), } a.Pb = b.New(a) return a } func (a *A) GetC() *c.C { return a.Pc }
package c隨之改成調(diào)用package f,其代碼如下:
package c import ( "github.com/ggq89/mutualdep/a/f" ) type C struct { Vc int } func New(i int) *C { return &C{ Vc: i, } } func (c *C) Show() { f.Printf(c.Vc) }
現(xiàn)在依賴關(guān)系如下:
A depends on B and C
B depends on C
C depends on F
至此,兩種包相互依賴關(guān)系都得以解決。
5. 總結(jié)
對于軟相互依賴,利用分包的方法就能解決,有些函數(shù)導(dǎo)致的相互依賴只能通過分包解決;分包能細(xì)化包的功能;
對于硬相互依賴只能通過定義接口的方法解決;定義接口能提高包的獨(dú)立性,同時(shí)也提高了追蹤代碼調(diào)用關(guān)系的難度;
參考文章:
- golang不允許循環(huán)import問題(“import cycle not allowed”) : http://www.dbjr.com.cn/article/145536.htm
- golang解決import cycle not allowed的一種思路 : http://www.dbjr.com.cn/article/145539.htm
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
- 如何解決django配置settings時(shí)遇到Could not import settings ''conf.local''
- 詳解golang避免循環(huán)import問題(“import cycle not allowed”)
- golang中import cycle not allowed解決的一種思路
- golang 之import和package的使用
- go各種import的使用方法講解
- 對Golang import 導(dǎo)入包語法詳解
- Golang import 導(dǎo)入包語法及一些特殊用法詳解
- Golang import本地包和導(dǎo)入問題相關(guān)詳解
- golang import自定義包方式
- 解決golang在import自己的包報(bào)錯(cuò)的問題
- 解決goland 導(dǎo)入項(xiàng)目后import里的包報(bào)紅問題
- Golang中 import cycle not allowed 問題的解決方法
- Go基礎(chǔ)教程系列之import導(dǎo)入包(遠(yuǎn)程包)和變量初始化詳解
相關(guān)文章
基于Go?goroutine實(shí)現(xiàn)一個(gè)簡單的聊天服務(wù)
對于聊天服務(wù),想必大家都不會陌生,因?yàn)樵谖覀兊纳钪薪?jīng)常會用到,本文我們用?Go?并發(fā)來實(shí)現(xiàn)一個(gè)聊天服務(wù)器,這個(gè)程序可以讓一些用戶通過服務(wù)器向其它所有用戶廣播文本消息,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06Nunu快速構(gòu)建高效可靠Go應(yīng)用腳手架使用詳解
這篇文章主要為大家介紹了如何使用Nunu快速構(gòu)建高效可靠Go應(yīng)用腳手架詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06go開源Hugo站點(diǎn)構(gòu)建三步曲之集結(jié)渲染
這篇文章主要為大家介紹了go開源Hugo站點(diǎn)構(gòu)建三步曲之集結(jié)渲染詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02