iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >go语言控制反转指的是什么
  • 903
分享到

go语言控制反转指的是什么

2023-07-05 00:07:01 903人浏览 独家记忆
摘要

这篇文章主要介绍了Go语言控制反转指的是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇go语言控制反转指的是什么文章都会有所收获,下面我们一起来看看吧。在go语言中,控制反转(ioc)是面向对象编程中的一种

这篇文章主要介绍了Go语言控制反转指的是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇go语言控制反转指的是什么文章都会有所收获,下面我们一起来看看吧。

在go语言中,控制反转(ioc)是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度,就是代码控制权从业务代码“反转”到框架代码。常见的控制反转方式叫做依赖注入,还有一种方式叫“依赖查找”;通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。

控制反转是什么

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

讲得通俗一点,假如我有一个控制器,UserController,它可以Code,Read,Eat ,当然它还有隐式的__construct构造函数,__destruct析构函数,我们知道这些默认函数在特定的情景会自己触发,比如初始化的时候,生命周期结束释放资源的时候,但是我们如果假如这些函数本身都不会自己触发,那么我们作为作者怎么去让他执行。实际上我的控制器还有ArticleController ,YouBadBadController,我怎么去处理。

各干各的 User你干活之前先去构建一下自己,Article你干活之前也去构建一下自己 这个情况短板就很明显了,后面介绍,每个控制器都要去各干各的,实际上都是Controller ,在处理公共行为的时候,其实我们可以借组外部实现和管理。 我们不用默认的魔法函数了,介绍一个具体场景,假如我现在需要每个控制器都要实现并调用一个handle函数。我们怎么合理去完成,假如现在还要执行一个run 方法 ,每个控制器添加完run函数之后,我们是不是还要写他们的调度;

控制反转统一管理 这个操作是不是可以让一个公共的ControllerService帮忙handle就行了,我们现在不考虑继承。

class ControllerService{public functiondo(){->handle(); } //去吧比卡丘; }}

等等,小智不投精灵球怎么去吧,小智呢? 我们需要把控制方带过来

class ControllerService{public $handler;public function __construct($handler){    $this->handler=$handler ;} //通过构造函数带入; }//public function setHandler($handler){     $this->handler->handle(); } //通过setter带入; }public function do(){     $this->handler->handle(); } //去吧比卡丘; }}new ControllerService()->setHandler(new UserController())->do();

这样控制权已经反转给ControllerService了;

Go语言中的interface 反射机制也是Ioc的体现

Golang 控制反转 (IOC)在工程中应用

设计

采用的第三方库

使用起来还是比较简单的,无非就是ReGISterTo, Invoke,但是任何的库都需要结合框架起来才有意义。

一提到松耦合,在GO中很容易就想到接口(interface),所以我们用接口实现的各个层之间的松耦合。

按照传统的mvc框架,一般服务端会有几种分层,Controler层、Service层、Module层 从上到下,如何将Ioc结合在框架中才是值得探讨的事情。

目录

go语言控制反转指的是什么

调用结构:由于没有服务,main函数充当的是Controler、Service是服务层、Module是数据层、Resource是存储层、app是各种接口的定义
main-->Service-->Module-->Resource
为了演示服务之间的调用,我们定义了service1和service2两种服务

实现

各层的接口定义

package apptype Service1 interface {ADDData(string)DelData(string)}type Service2 interface {AddData(string)DelData(string)}type Module interface {DataToSave(string)DataToRemove(string)}type Resource interface {Save(string)Remove(string)}

IOC 初始化

package appimport ("GitHub.com/berkaroad/ioc""github.com/spf13/viper")func GetOrCreateRootContainer() ioc.Container {v := viper.Get("runtime.container")if v == nil {v = ioc.NewContainer()viper.Set("runtime.container", v)}return v.(ioc.Container)}

这里其实怎么实现都行,只是一个单例NewContainer就可以

存储层(自下而上)

package resourceimport ("fmt""github.com/berkaroad/ioc""github.com/zhaoshoucheng/hodgepodge/IoC/app")type ResourceObj struct {name string}func (r *ResourceObj) Save(str string) {fmt.Println(r.name, " Save ", str)}func (r *ResourceObj) Remove(str string) {fmt.Println(r.name, " Remove ", str)}func init() {mo := &ResourceObj{name: "mongo"}// static assert 静态断言类型检测func(t app.Resource) {}(mo)app.GetOrCreateRootContainer().RegisterTo(mo, (*app.Resource)(nil), ioc.Singleton)        //rd := &ResourceObj{name: "redis"} 实现是用的map,所以mong会被覆盖        //app.GetOrCreateRootContainer().RegisterTo(rd, (*app.Resource)(nil), ioc.Singleton)}

RegisterTo是注册过程,在mo对象后续会当作app.Resource接口的实现来使用,其底层实现是一个map

数据层

package moduleimport ("fmt""github.com/berkaroad/ioc""github.com/zhaoshoucheng/hodgepodge/IoC/app")var (rs app.Resource)type ModuleObj struct {}func (mo *ModuleObj) DataToSave(str string) {fmt.Println("ModuleObj DataToSave ", str)rs.Save(str)}func (mo *ModuleObj) DataToRemove(str string) {fmt.Println("ModuleObj DataToRemove ", str)rs.Remove(str)}func init() {mo := &ModuleObj{}// static assert 静态断言类型检测func(t app.Module) {}(mo)app.GetOrCreateRootContainer().RegisterTo(mo, (*app.Module)(nil), ioc.Singleton)app.GetOrCreateRootContainer().Invoke(func(r app.Resource) {rs = r})}

因为我们之前app.Resource已经注册过,所以这里Invoke的时候就可以获取到实现该接口的对象

服务层

package serviceimport ("fmt""github.com/berkaroad/ioc""github.com/zhaoshoucheng/hodgepodge/IoC/app")var (module app.Moduleservice2 app.Service2)type Service1 struct {}func (s1 *Service1) AddData(str string) {service2.AddData(str)fmt.Println("Service1 AddData ", str)module.DataToSave(str)}func (s1 *Service1) DelData(str string) {service2.DelData(str)fmt.Println("Service1 DelData ", str)module.DataToRemove(str)}func init() {s1 := &Service1{}s2 := &Service2{}service2 = s2//static assert 静态断言做类型检查func(t app.Service1) {}(s1)func(t app.Service2) {}(s2)app.GetOrCreateRootContainer().RegisterTo(s1, (*app.Service1)(nil), ioc.Singleton)app.GetOrCreateRootContainer().RegisterTo(s2, (*app.Service2)(nil), ioc.Singleton)app.GetOrCreateRootContainer().Invoke(func(mod app.Module) {module = mod})}

Main

package mainimport ("github.com/zhaoshoucheng/hodgepodge/IoC/app"        _ "github.com/zhaoshoucheng/hodgepodge/IoC/resource"_ "github.com/zhaoshoucheng/hodgepodge/IoC/module"_ "github.com/zhaoshoucheng/hodgepodge/IoC/service")func main() {var s1 app.Service1app.GetOrCreateRootContainer().Invoke(func(service app.Service1) {s1 = service})s1.AddData("IOC Test")}

测试

go语言控制反转指的是什么

思考

我们为什么要用到Ioc呢?个人感觉有几点好处
1.解决各种依赖问题,写GO可能都遇到过循环引用问题,越是复杂的系统就越有可能出现这种混乱的调用现象。
2.实现了很好的扩展性,如果存储层想从Redis切换到mongo,定义一个相同的对象,替换注册对象就可以轻松实现。
3.易使用,随时随地可以通过Invoke获取相应的接口对象。

问题

难道就没有问题吗?
当然有,就是引用顺序的问题,也就是先register 还是先invoke 这个在例子中感觉很简单,但是在工程中很容易出错

_ "github.com/zhaoshoucheng/hodgepodge/IoC/module"_ "github.com/zhaoshoucheng/hodgepodge/IoC/resource"_ "github.com/zhaoshoucheng/hodgepodge/IoC/service"
        _ "github.com/zhaoshoucheng/hodgepodge/IoC/resource"_ "github.com/zhaoshoucheng/hodgepodge/IoC/module"_ "github.com/zhaoshoucheng/hodgepodge/IoC/service"

第一种写法就会崩溃,第二种正确

原因第一种module 的init 先执行,app.Resource的对象还没有注册。所以init的先后顺序很重要

但这个是凭借字节码进行的排序,有时IDE还不让我们改,所以需要一些控制器去处理这种情况。

关于“go语言控制反转指的是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“go语言控制反转指的是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网精选频道。

--结束END--

本文标题: go语言控制反转指的是什么

本文链接: https://www.lsjlt.com/news/348759.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++ 生态系统中流行库和框架的贡献指南
    作为 c++++ 开发人员,通过遵循以下步骤即可为流行库和框架做出贡献:选择一个项目并熟悉其代码库。在 issue 跟踪器中寻找适合初学者的问题。创建一个新分支,实现修复并添加测试。提交...
    99+
    2024-05-15
    框架 c++ 流行库 git
  • C++ 生态系统中流行库和框架的社区支持情况
    c++++生态系统中流行库和框架的社区支持情况:boost:活跃的社区提供广泛的文档、教程和讨论区,确保持续的维护和更新。qt:庞大的社区提供丰富的文档、示例和论坛,积极参与开发和维护。...
    99+
    2024-05-15
    生态系统 社区支持 c++ overflow 标准库
  • c++中if elseif使用规则
    c++ 中 if-else if 语句的使用规则为:语法:if (条件1) { // 执行代码块 1} else if (条件 2) { // 执行代码块 2}// ...else ...
    99+
    2024-05-15
    c++
  • c++中的继承怎么写
    继承是一种允许类从现有类派生并访问其成员的强大机制。在 c++ 中,继承类型包括:单继承:一个子类从一个基类继承。多继承:一个子类从多个基类继承。层次继承:多个子类从同一个基类继承。多层...
    99+
    2024-05-15
    c++
  • c++中如何使用类和对象掌握目标
    在 c++ 中创建类和对象:使用 class 关键字定义类,包含数据成员和方法。使用对象名称和类名称创建对象。访问权限包括:公有、受保护和私有。数据成员是类的变量,每个对象拥有自己的副本...
    99+
    2024-05-15
    c++
  • c++中优先级是什么意思
    c++ 中的优先级规则:优先级高的操作符先执行,相同优先级的从左到右执行,括号可改变执行顺序。操作符优先级表包含从最高到最低的优先级列表,其中赋值运算符具有最低优先级。通过了解优先级,可...
    99+
    2024-05-15
    c++
  • c++中a+是什么意思
    c++ 中的 a+ 运算符表示自增运算符,用于将变量递增 1 并将结果存储在同一变量中。语法为 a++,用法包括循环和计数器。它可与后置递增运算符 ++a 交换使用,后者在表达式求值后递...
    99+
    2024-05-15
    c++
  • c++中a.b什么意思
    c++kquote>“a.b”表示对象“a”的成员“b”,用于访问对象成员,可用“对象名.成员名”的语法。它还可以用于访问嵌套成员,如“对象名.嵌套成员名.成员名”的语法。 c++...
    99+
    2024-05-15
    c++
  • C++ 并发编程库的优缺点
    c++++ 提供了多种并发编程库,满足不同场景下的需求。线程库 (std::thread) 易于使用但开销大;异步库 (std::async) 可异步执行任务,但 api 复杂;协程库 ...
    99+
    2024-05-15
    c++ 并发编程
  • 如何在 Golang 中备份数据库?
    在 golang 中备份数据库对于保护数据至关重要。可以使用标准库中的 database/sql 包,或第三方包如 github.com/go-sql-driver/mysql。具体步骤...
    99+
    2024-05-15
    golang 数据库备份 mysql git 标准库
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作