Java是一門較為成熟的語言,相對于C++要簡單的多,C++里沒有內存回收,所以比較麻煩,Java加入了內存自動回收,簡單是簡單,卻變慢了,go語言是一門新興的語言,現在版本是1.9 ? go語言的性能比Java要好,但由于出現晚,資料較Java少,有些Java的功能go也沒有,并且有許多的軟件是支持Java但支持go的很少.所以在短期內Java是比go通用的
創新互聯公司是一家專業提供回民企業網站建設,專注與成都網站設計、成都網站建設、H5頁面制作、小程序制作等業務。10年已為回民眾多企業、政府機構等服務。創新互聯專業網站制作公司優惠進行中。
C語言的最大的優勢是時間性能好,只比匯編慢20%~30%,C++最大的優勢是快且面向對象,Java最大的優勢是垃圾回收機制,GO語言的目標是具備以上三者的優勢
Fx是一個golang版本的依賴注入框架,它使得golang通過可重用、可組合的模塊化來構建golang應用程序變得非常容易,可直接在項目中添加以下內容即可體驗Fx效果。
Fx是通過使用依賴注入的方式替換了全局通過手動方式來連接不同函數調用的復雜度,也不同于其他的依賴注入方式,Fx能夠像普通golang函數去使用,而不需要通過使用struct標簽或內嵌特定類型。這樣使得Fx能夠在很多go的包中很好的使用。
接下來會提供一些Fx的簡單demo,并說明其中的一些定義。
1、一般步驟
大致的使用步驟就如下。下面會給出一些完整的demo
2、簡單demo
將io.reader與具體實現類關聯起來
輸出:
3、使用struct參數
前面的使用方式一旦需要進行注入的類型過多,可以通過struct參數方式來解決
輸出
如果通過Provide提供構造函數是生成相同類型會有什么問題?換句話也就是相同類型擁有多個值呢?
下面兩種方式就是來解決這樣的問題。
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
原文鏈接:
github:
Dependency Injection is the idea that your components (usually structs in 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 a Server struct that requires a Config struct to implement its behavior. One way to do this would be for the Server to build its own Config during initialization.
This seems convenient. Our caller doesn’t have to be aware that our Server even needs access to Config . 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 our Config is built, we’ll have to change all the places that call the building code. Suppose, for example, our buildMyConfigSomehow function 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 our Config . We’ll somehow have to reach inside of our New function to monkey with the creation of Config .
Here’s the DI way to do it:
Now the creation of our Server is decoupled from the creation of the Config . We can use whatever logic we want to create the Config and then pass the resulting data to our New function.
Furthermore, if Config is an interface, this gives us an easy route to mocking. We can pass anything we want into New as long as it implements our interface. This makes testing our Server with mock implementations of Config simple.
The main downside is that it’s a pain to have to manually create the Config before we can create the Server . We’ve created a dependency graph here – we must create our Config first because of Server depends 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 a GET request 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 found here .
First, let’s look at our Person struct. It has no behavior save for some JSON tags.
A Person has an Id , Name and Age . That’s it.
Next let’s look at our Config . Similar to Person , it has no dependencies. Unlike Person , we will provide a constructor.
Enabled tells us if our application should return real data. DatabasePath tells us where our database lives (we’re using sqlite). Port tells 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 our Config and returns a *sql.DB .
Next we’ll look at our PersonRepository . This struct will be responsible for fetching people from our database and deserializing those database results into proper Person structs.
PersonRepository requires a database connection to be built. It exposes a single function called FindAll that uses our database connection to return a list of Person structs representing the data in our database.
To provide a layer between our HTTP server and the PersonRepository , we’ll create a PersonService .
Our PersonService relies on both the Config and the PersonRepository . It exposes a function called FindAll that conditionally calls the PersonRepository if the application is enabled.
Finally, we’ve got our Server . This is responsible for running an HTTP server and delegating the appropriate requests to our PersonService .
The Server is dependent on the PersonService and the Config .
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 our main() function the old fashioned way.
First, we create our Config . Then, using the Config , we create our database connection. From there we can create our PersonRepository which allows us to create our PersonService . Finally, we can use this to create our Server and run it.
Phew, that was complicated. Worse, as our application becomes more complicated, our main will 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 the main function 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. The dig library gives us the Provide function for adding providers and the Invoke function 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 the Provide function 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 a Config type to the container. In order to build it, I don’t need anything else.” Now that we’ve shown the container how to build a Config type, we can use this to build other types.
This code says “I provide a *sql.DB type to the container. In order to build it, I need a Config . I may also optionally return an error.”
In both of these cases, we’re being more verbose than necessary. Because we already have NewConfig and ConnectDatabase functions 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 the Invoke function. The Invoke function 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 the dig container works, let’s use it to build a better main.
The only thing we haven’t seen before here is the error return value from Invoke . If any provider used by Invoke returns an error, our call to Invoke will 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 our PersonRepository now needs access to the Config . All we have to do is change our NewPersonRepository constructor to include the Config as an argument. Nothing else in our code changes.
Other large benefits are lack of global state, lack of calls to init (dependencies are created lazily when needed and only created once, obviating the need for error-prone init setup) 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 in dig . I believe the Go community should embrace DI and use it in far more applications.
推薦五款開快速開發的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 后臺輕松配置路由,并實現啟用/禁用模塊或操作、添加/移除中間件等!同時,它以 ApiHandler 與 ApiMiddleware 為項目基本組成單元,可實現編譯期或運行時的自由搭配組合,也令開發變得更加靈活富有趣味性。
3. 項目名稱:模塊化設計的 Go Web 框架 Macaron
項目簡介:Macaron 是一個具有高生產力和模塊化設計的 Go Web 框架。框架秉承了 Martini 的基本思想,并在此基礎上做出高級擴展。
4. 項目名稱:基于Go 的輕量級 Web 框架 GoInk
項目簡介:HxGo 是基于我以往的 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語言,go需要依賴注入嗎
文章來源:http://vcdvsql.cn/article4/hshpoe.html
成都網站建設公司_創新互聯,為您提供云服務器、靜態網站、ChatGPT、小程序開發、外貿網站建設、自適應網站
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯