Go语言依赖注入 golang 依赖注入

什么是依赖注入依赖注入的作用是什么意思依赖注入:
依赖注入就是Spring设计思想中重要的一部分,它是指Ioc或DI,是一个重要的面向对象编程的法则来削减计算机程序的耦合问题.控制反转还有一个名字叫做依赖注入(Dependency Injection).简称DI.
IoC 亦称为 “依赖倒置原理”("Dependency Inversion Principle") 。差不多所有框架都使用了“倒置注入(Fowler 2004)技巧,这可说是IoC原理的一项应用 。SmallTalk,C, Java 或各种.NET 语言等面向对象程序语言的程序员已使用了这些原理 。
应用控制反转,对象在被创建的时候 , 由一个调控系统内所有对象的外界实体 , 将其所依赖的对象的引用,传递给它 。也可以说,依赖被注入到对象中 。所以,控制反转是 , 关于一个对象如何获取他所依赖的对象的引用,这个责任的反转 。
依赖注入的作用:
把对象生成放在了XML里定义,所以换一个实现子类将会变成很简单(一般这样的对象都是实现于某种接口的),只要修改XML就可以 。这样甚至可以实现对象的热插拨 。
Go语言与Java之间性能相差多少Java是一门较为成熟的语言,相对于C要简单的多,C里没有内存回收,所以比较麻烦,Java加入了内存自动回收,简单是简单,却变慢了,go语言是一门新兴的语言,现在版本是1.9 ? go语言的性能比Java要好,但由于出现晚,资料较Java少,有些Java的功能go也没有,并且有许多的软件是支持Java但支持go的很少.所以在短期内Java是比go通用的
C语言的最大的优势是时间性能好,只比汇编慢20%~30%,C最大的优势是快且面向对象,Java最大的优势是垃圾回收机制,GO语言的目标是具备以上三者的优势
go依赖注入dig包使用-来自uber公司原文链接:
github:
Dependency Injection is the idea that your components (usuallystructsin go) should receive their dependencies when being created. This runs counter to the associated anti-pattern of components building their own dependencies during initialization. Let’s look at an example.
Suppose you have aServerstruct that requires aConfigstruct to implement its behavior. One way to do this would be for theServerto build its ownConfigduring initialization.
This seems convenient. Our caller doesn’t have to be aware that ourServereven needs access toConfig . This is all hidden from the user of our function.
However, there are some disadvantages. First of all, if we want to change the way ourConfigis built, we’ll have to change all the places that call the building code. Suppose, for example, ourbuildMyConfigSomehowfunction now needs an argument. Every call site would need access to that argument and would need to pass it into the building function.
Also, it gets really tricky to mock the behavior of ourConfig . We’ll somehow have to reach inside of ourNewfunction to monkey with the creation ofConfig .
Here’s the DI way to do it:
Now the creation of ourServeris decoupled from the creation of theConfig . We can use whatever logic we want to create theConfigand then pass the resulting data to ourNewfunction.
Furthermore, ifConfigis an interface, this gives us an easy route to mocking. We can pass anything we want intoNewas long as it implements our interface. This makes testing ourServerwith mock implementations ofConfigsimple.
The main downside is that it’s a pain to have to manually create theConfigbefore we can create theServer . We’ve created a dependency graph here – we must create ourConfigfirst because ofServerdepends on it. In real applications these dependency graphs can become very large and this leads to complicated logic for building all of the components your application needs to do its job.
This is where DI frameworks can help. A DI framework generally provides two pieces of functionality:
A DI framework generally builds a graph based on the “providers” you tell it about and determines how to build your objects. This is very hard to understand in the abstract, so let’s walk through a moderately-sized example.
We’re going to be reviewing the code for an HTTP server that delivers a JSON response when a client makes aGETrequest to/people . We’ll review the code piece by piece. For simplicity sake, it all lives in the same package ( main ). Please don’t do this in real Go applications. Full code for this example can be foundhere .
First, let’s look at ourPersonstruct. It has no behavior save for some JSON tags.
APersonhas anId ,NameandAge . That’s it.
Next let’s look at ourConfig . Similar toPerson , it has no dependencies. UnlikePerson , we will provide a constructor.
Enabledtells us if our application should return real data.DatabasePathtells us where our database lives (we’re using sqlite).Porttells us the port on which we’ll be running our server.
Here’s the function we’ll use to open our database connection. It relies on ourConfigand returns a*sql.DB .
Next we’ll look at ourPersonRepository . This struct will be responsible for fetching people from our database and deserializing those database results into properPersonstructs.
PersonRepositoryrequires a database connection to be built. It exposes a single function calledFindAllthat uses our database connection to return a list ofPersonstructs representing the data in our database.
To provide a layer between our HTTP server and thePersonRepository , we’ll create aPersonService .
OurPersonServicerelies on both theConfigand thePersonRepository . It exposes a function calledFindAllthat conditionally calls thePersonRepositoryif the application is enabled.
Finally, we’ve got ourServer . This is responsible for running an HTTP server and delegating the appropriate requests to ourPersonService .
TheServeris dependent on thePersonServiceand theConfig .
Ok, we know all the components of our system. Now how the hell do we actually initialize them and start our system?
First, let’s write ourmain()function the old fashioned way.
First, we create ourConfig . Then, using theConfig , we create our database connection. From there we can create ourPersonRepositorywhich allows us to create ourPersonService . Finally, we can use this to create ourServerand run it.
Phew, that was complicated. Worse, as our application becomes more complicated, ourmainwill continue to grow in complexity. Every time we add a new dependency to any of our components, we’ll have to reflect that dependency with ordering and logic in themainfunction to build that component.
As you might have guessed, a Dependency Injection framework can help us solve this problem. Let’s examine how.
The term “container” is often used in DI frameworks to describe the thing into which you add “providers” and out of which you ask for fully-build objects. Thediglibrary gives us theProvidefunction for adding providers and theInvokefunction for retrieving fully-built objects out of the container.
First, we build a new container.
Now we can add new providers. To do so, we call theProvidefunction on the container. It takes a single argument: a function. This function can have any number of arguments (representing the dependencies of the component to be created) and one or two return values (representing the component that the function provides and optionally an error).
The above code says “I provide aConfigtype to the container. In order to build it, I don’t need anything else.” Now that we’ve shown the container how to build aConfigtype, we can use this to build other types.
This code says “I provide a*sql.DBtype to the container. In order to build it, I need aConfig . I may also optionally return an error.”
In both of these cases, we’re being more verbose than necessary. Because we already haveNewConfigandConnectDatabasefunctions defined, we can use them directly as providers for the container.
Now, we can ask the container to give us a fully-built component for any of the types we’ve provided. We do so using theInvokefunction. TheInvokefunction takes a single argument – a function with any number of arguments. The arguments to the function are the types we’d like the container to build for us.
The container does some really smart stuff. Here’s what happens:
That’s a lot of work the container is doing for us. In fact, it’s doing even more. The container is smart enough to build one, and only one, instance of each type provided. That means we’ll never accidentally create a second database connection if we’re using it in multiple places (say multiple repositories).
Now that we know how thedigcontainer works, let’s use it to build a better main.
The only thing we haven’t seen before here is theerrorreturn value fromInvoke . If any provider used byInvokereturns an error, our call toInvokewill halt and that error will be returned.
Even though this example is small, it should be easy to see some of the benefits of this approach over our “standard” main. These benefits become even more obvious as our application grows larger.
One of the most important benefits is the decoupling of the creation of our components from the creation of their dependencies. Say, for example, that ourPersonRepositorynow needs access to theConfig . All we have to do is change ourNewPersonRepositoryconstructor to include theConfigas an argument. Nothing else in our code changes.
Other large benefits are lack of global state, lack of calls toinit(dependencies are created lazily when needed and only created once, obviating the need for error-proneinitsetup) and ease of testing for individual components. Imagine creating your container in your tests and asking for a fully-build object to test. Or, create an object with mock implementations of all dependencies. All of these are much easier with the DI approach.
I believe Dependency Injection helps build more robust and testable applications. This is especially true as these applications grow in size. Go is well suited to building large applications and has a great DI tool indig . I believe the Go community should embrace DI and use it in far more applications.
golang反射框架FxFx是一个golang版本的依赖注入框架Go语言依赖注入,它使得golang通过可重用、可组合的模块化来构建golang应用程序变得非常容易,可直接在项目中添加以下内容即可体验Fx效果 。
Fx是通过使用依赖注入的方式替换了全局通过手动方式来连接不同函数调用的复杂度,也不同于其他的依赖注入方式,Fx能够像普通golang函数去使用,而不需要通过使用struct标签或内嵌特定类型 。这样使得Fx能够在很多go的包中很好的使用 。
接下来会提供一些Fx的简单demo,并说明其中的一些定义 。
1、一般步骤
大致的使用步骤就如下 。下面会给出一些完整的demo
2、简单demo
将io.reader与具体实现类关联起来
输出:
3、使用struct参数
前面的使用方式一旦需要进行注入的类型过多,可以通过struct参数方式来解决
输出
如果通过Provide提供构造函数是生成相同类型会有什么问题?换句话也就是相同类型拥有多个值呢Go语言依赖注入?
下面两种方式就是来解决这样的问题 。
4、使用struct参数 Name标签
在Fx未使用Name或Group标签时不允许存在多个相同类型的构造函数,一旦存在会触发panic 。
输出
上面通过Name标签即可完成在Fx容器注入相同类型
5、使用struct参数 Group标签
使用group标签同样也能完成上面的功能
输出
基本上Fx简单应用在上面的例子也做了简单讲解
1、Annotated(位于annotated.go文件) 主要用于采用annotated的方式,提供Provide注入类型
源码中Name和Group两个字段与前面提到的Name标签和Group标签是一样的,只能选其一使用
2、App(位于app.go文件) 提供注入对象具体的容器、LiftCycle、容器的启动及停止、类型变量及实现类注入和两者映射等操作
至于Provide和Populate的源码相对比较简单易懂在这里不在描述
具体源码
3、Extract(位于extract.go文件)
主要用于在application启动初始化过程通过依赖注入的方式将容器中的变量值来填充给定的struct,其中target必须是指向struct的指针 , 并且只能填充可导出的字段(golang只能通过反射修改可导出并且可寻址的字段),Extract将被Populate代替 。具体源码
4、其他
诸如Populate是用来替换Extract的,而LiftCycle和inout.go涉及内容比较多后续会单独提供专属文件说明 。
在Fx中提供的构造函数都是惰性调用,可以通过invocations在application启动来完成一些必要的初始化工作:fx.Invoke(function); 通过也可以按需自定义实现LiftCycle的Hook对应的OnStart和OnStop用来完成手动启动容器和关闭,来满足一些自己实际的业务需求 。
Fx框架源码解析
主要包括app.go、lifecycle.go、annotated.go、populate.go、inout.go、shutdown.go、extract.go(可以忽略,了解populate.go)以及辅助的internal中的fxlog、fxreflect、lifecycle
go有哪些快速开发的web框架推荐五款开快速开发的Web框架 , 希望能够帮助题主,供大家一起交流学习 。
1. 项目名称:基于 Go 的 Web 框架 Faygo
项目简介:Faygo 是一款快速、简洁的 Go Web 框架,可用极少的代码开发出高性能的 Web 应用程序(尤其是API接口) 。只需定义 struct Handler,Faygo 就能自动绑定、验证请求参数并生成在线API文档 。
2. 项目名称:基于 Go 的 Web 开发框架 essgo
项目简介:essgo 是一款 Go 语言开发的简单、稳定、高效、灵活的 web 开发框架 。它的项目组织形式经过精心设计,实现前后端分离、系统与业务分离,完美兼容 MVC 与 MVVC 等多种开发模式 , 非常利于企业级应用与 API 接口的开发 。当然,最值得关注的是它突破性支持运行时路由重建,开发者可在 Admin 后台轻松配置路由 , 并实现启用/禁用模块或操作、添加/移除中间件等Go语言依赖注入!同时,它以 ApiHandler 与 ApiMiddleware 为项目基本组成单元,可实现编译期或运行时的自由搭配组合,也令开发变得更加灵活富有趣味性 。
3. 项目名称:模块化设计的 GoWeb 框架 Macaron
项目简介:Macaron 是一个具有高生产力和模块化设计的 Go Web 框架 。框架秉承了 Martini 的基本思想,并在此基础上做出高级扩展 。
4. 项目名称:基于Go 的轻量级 Web 框架 GoInk
项目简介:HxGo 是基于Go语言依赖注入我以往的 php 开发经验编写的 Go Web 框架 。力求简单直接,符合大众编写习惯,同时性能优良 。HxGo 基于 MVC 的结构模式,实现 REST 支持的自动路由分发 , 简化 HTTP 请求和视图操作 。同时,HxGo 提供简易直接的数据访问层,高效直接操作数据库内容 。
5. 项目名称:简单高效的 Go web 开发框架 Baa
项目简介:Baa 是一个简单高效的 Go web 开发框架 。主要有路由、中间件,依赖注入和HTTP上下文构成 。Baa 不使用 反射和正则,没有魔法的实现 。
特性:
支持静态路由、参数路由、组路由(前缀路由/命名空间)和路由命名;
路由支持链式操作;
路由支持文件/目录服务;
中间件支持链式操作;
支持依赖注入*;
支持 JSON/JSONP/XML/HTML 格式输出;
统一的 HTTP 错误处理;
统一的日志处理;
支持任意更换模板引擎(实现 baa.Renderer 接口即可) 。
【Go语言依赖注入 golang 依赖注入】关于Go语言依赖注入和golang 依赖注入的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站 。

    推荐阅读