欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang報(bào)“import cycle not allowed”錯(cuò)誤的2種解決方法

 更新時(shí)間:2018年08月13日 10:59:53   作者:AlbertGou  
這篇文章主要給大家介紹了關(guān)于Golang報(bào)"import cycle not allowed"錯(cuò)誤的2種解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以們下面隨著小編來一起看看吧

前言

相信不少 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)系的難度;

參考文章:

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • 基于Go?goroutine實(shí)現(xiàn)一個(gè)簡單的聊天服務(wù)

    基于Go?goroutine實(shí)現(xiàn)一個(gè)簡單的聊天服務(wù)

    對于聊天服務(wù),想必大家都不會陌生,因?yàn)樵谖覀兊纳钪薪?jīng)常會用到,本文我們用?Go?并發(fā)來實(shí)現(xiàn)一個(gè)聊天服務(wù)器,這個(gè)程序可以讓一些用戶通過服務(wù)器向其它所有用戶廣播文本消息,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • Nunu快速構(gòu)建高效可靠Go應(yīng)用腳手架使用詳解

    Nunu快速構(gòu)建高效可靠Go應(yīng)用腳手架使用詳解

    這篇文章主要為大家介紹了如何使用Nunu快速構(gòu)建高效可靠Go應(yīng)用腳手架詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • Golang?Makefile示例深入講解使用

    Golang?Makefile示例深入講解使用

    一次偶然的機(jī)會,在?github?上看到有人用?Makefile,就嘗試了一下,發(fā)現(xiàn)真的非常合適,Makefile?本身就是用來描述依賴的,可讀性非常好,而且與強(qiáng)大的?shell?結(jié)合在一起,基本可以實(shí)現(xiàn)任何想要的功能
    2023-01-01
  • Go語言聲明一個(gè)多行字符串的變量

    Go語言聲明一個(gè)多行字符串的變量

    這篇文章主要介紹了Go語言聲明一個(gè)多行字符串的變量的方法和示例,非常簡單實(shí)用,有需要的小伙伴可以參考下。
    2015-04-04
  • Go中Vendo機(jī)制的使用

    Go中Vendo機(jī)制的使用

    自Go1.6起,Go語言正式啟用vendor機(jī)制,允許將項(xiàng)目依賴放入項(xiàng)目內(nèi)的vendor目錄,類似私有GOPATH,本文就來介紹一下Vendo機(jī)制的使用,感興趣的可以了解一下
    2024-10-10
  • Go?Redis客戶端使用的兩種對比

    Go?Redis客戶端使用的兩種對比

    這篇文章主要為大家介紹了Go?Redis客戶端使用對比詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • go開源Hugo站點(diǎn)構(gòu)建三步曲之集結(jié)渲染

    go開源Hugo站點(diǎn)構(gòu)建三步曲之集結(jié)渲染

    這篇文章主要為大家介紹了go開源Hugo站點(diǎn)構(gòu)建三步曲之集結(jié)渲染詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Go中的新增對模糊測試的支持

    Go中的新增對模糊測試的支持

    這篇文章主要為大家介紹了Go中的新增對模糊測試的支持,文中還包含了一些功能實(shí)驗(yàn)性測試分析有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2022-03-03
  • golang中defer的使用規(guī)則詳解

    golang中defer的使用規(guī)則詳解

    大家應(yīng)該都知道在golang當(dāng)中,defer代碼塊會在函數(shù)調(diào)用鏈表中增加一個(gè)函數(shù)調(diào)用。下面這篇文章主要給大家介紹了關(guān)于golang中defer的使用規(guī)則,文中介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。
    2017-07-07
  • Go語言簡介和環(huán)境配置

    Go語言簡介和環(huán)境配置

    Go語言保證了既能到達(dá)靜態(tài)編譯語言的安全和性能,又達(dá)到了動態(tài)語言開發(fā)速度和易維護(hù)性,有人形容Go語言:Go=?C?+?Python?,?說明Go語言既有C靜態(tài)語言程序的運(yùn)行速度,又能達(dá)到Python動態(tài)語言的快速開發(fā),這篇文章主要介紹了Go介紹和環(huán)境配置,需要的朋友可以參考下
    2022-07-07

最新評論