【如何解决Go包中循环依赖】

1. 什么是循环依赖

Go 中的循环依赖是指两个或多个包之间相互引用,形成了一个循环依赖关系。这种情况下,包 A 依赖包 B,同时包 B 也依赖包 A,导致两个包之间无法明确地确定编译顺序,从而可能引发编译错误或其他问题。循环依赖是 Go 中需要小心处理的问题,因为它可能导致程序不可编译或产生未定义行为。

2. Go中为什么不容易出现循环依赖

在 Go 中出现循环依赖的情况相对较少,但也可能会发生。这主要是因为 Go 编译器的工作方式以及包管理机制导致的。

  1. 单一源文件编译:Go 编译器在编译源文件时,会先将源文件分解为独立的包单元,然后对每个包单元进行编译。这意味着每个源文件都必须能够独立编译,而不能依赖于其他源文件。因此,如果出现循环依赖,编译器无法解决这种依赖关系,因为它需要单独编译每个包。
  2. 包管理机制:Go 的包管理机制要求每个包都必须明确导入它所依赖的其他包。如果两个或多个包相互依赖,且它们在导入彼此时形成了循环依赖,编译器将无法确定包的加载顺序,因为每个包都依赖于另一个尚未加载的包。

尽管 Go 编译器和包管理机制都能够帮助开发人员避免循环依赖,但仍然有一些情况可能导致循环依赖的出现:

3. 全局存储需要相互依赖的函数

通过map关键字调用

package callback_mgr

import (
	"fmt"
	"reflect"
)

var callBackMap map[string]interface{}

func init() {
	callBackMap = make(map[string]interface{})
}

func RegisterCallBack(key string, callBack interface{}) {
	callBackMap[key] = callBack
}
func CallBackFunc(key string, args ...interface{}) []interface{} {
	if callBack, ok := callBackMap[key]; ok {
		in := make([]reflect.Value, len(args))
		for i, arg := range args {
			in[i] = reflect.ValueOf(arg)
		}
		outList := reflect.ValueOf(callBack).Call(in)
		result := make([]interface{}, len(outList))
		for i, out := range outList {
			result[i] = out.Interface()
		}
		return result
	} else {
		panic(fmt.Errorf("callBack(%s) not found", key))
	}
}

  • callback_mgr 包声明了一个包名 callback_mgr。
  • 导入了两个标准库包:fmt 和 reflect。fmt 用于格式化输出,reflect 用于在运行时进行类型信息的查看和操作。
  • 声明了一个全局变量 callBackMap,它是一个 map,用于存储回调函数,键是字符串类型的标识符,值是接口类型,可以存储任意类型的回调函数。
  • 在 init() 函数中对 callBackMap 进行了初始化,将其设为一个空 map。
  • RegisterCallBack 函数用于注册回调函数。它接受两个参数:key,用于标识回调函数;callBack,实际的回调函数。这个函数将回调函数存储在 callBackMap 中,使用 key 作为键。
  • CallBackFunc 函数用于调用注册的回调函数。它接受一个 key 参数来标识要调用的回调函数,以及一个可变数量的 args 参数,用于传递给回调函数的参数。如果找到了注册的回调函数,则使用 reflect 包动态调用该函数,并将参数传递给它。然后将返回的结果转换为 interface{} 类型并返回。如果未找到注册的回调函数,则会抛出一个带有错误消息的 panic。

3.如何调用

result := callback_mgr.CallBackFunc("methodName", "args....")
//返回值result 将会是一个 []interface{} 类型的切片,需要将其转换成对应的类型
result[0].(structType)

相关推荐

  1. 如何解决Go循环依赖

    2024-03-25 20:28:02       18 阅读
  2. Spring如何解决循环依赖

    2024-03-25 20:28:02       22 阅读
  3. Spring如何解决循环依赖

    2024-03-25 20:28:02       17 阅读
  4. Spring如何解决循环依赖

    2024-03-25 20:28:02       10 阅读
  5. Spring的循环依赖问题如何解决

    2024-03-25 20:28:02       16 阅读
  6. Spring 如何解决 Bean 循环依赖

    2024-03-25 20:28:02       12 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-25 20:28:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-25 20:28:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-25 20:28:02       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-25 20:28:02       20 阅读

热门阅读

  1. Android基础面试题目汇总

    2024-03-25 20:28:02       17 阅读
  2. 2019南京大学计算机考研复试机试题-Stepping Numbers

    2024-03-25 20:28:02       15 阅读
  3. Nginx配置文件中Location指令的匹配优先级

    2024-03-25 20:28:02       17 阅读
  4. 【微服务设计】常见的DDD设计中的经验教训!

    2024-03-25 20:28:02       19 阅读
  5. 计算机网络原理之四种攻击

    2024-03-25 20:28:02       21 阅读
  6. Android中的设计模式

    2024-03-25 20:28:02       18 阅读
  7. 异常的处理(try-catch-finally)

    2024-03-25 20:28:02       15 阅读
  8. C语言空指针常量NULL

    2024-03-25 20:28:02       16 阅读
  9. python内置函数 T

    2024-03-25 20:28:02       20 阅读
  10. 约瑟夫问题---(蓝桥杯)

    2024-03-25 20:28:02       22 阅读
  11. Rancher(v2.6.3)——Rancher部署Nginx(单机版)

    2024-03-25 20:28:02       18 阅读