最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析golang的依賴注入

 更新時間:2022年09月28日 09:15:49   作者:bobo_simpler  
這篇文章主要介紹了淺析golang的依賴注入,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下

前言

如果是做web開發(fā),對依賴注入肯定不陌生,java程序員早就習慣了spring提供的依賴注入,做業(yè)務開發(fā)時非常方便,只關注業(yè)務邏輯即可,對象之間的依賴關系都交給框架。

golang是強類型語言,編譯后是機器碼,所以一般使用 反射 或 代碼生成 解決依賴注入的問題

基于反射的DI

基于反射解決DI問題的框架, 使用比較多的是Uber的 dig 庫

官方的例子:

type Config struct {
        Prefix string
}

//初始化Config函數(shù)
func NewConfig()(*Config, error) {
        // In a real program, the configuration will probably be read from a
        // file.
        var cfg Config
        err := json.Unmarshal([]byte(`{"prefix": "[foo] "}`), &cfg)
        return &cfg, err
}

//初始化logger函數(shù)
func NewLogger(cfg *Config) *log.Logger {
    return log.New(os.Stdout, cfg.Prefix, 0)
}

func Handle() (l *log.Logger) {
    l.Print("You've been invoked")
}

func main() {
    //初始化dig對象
    c := dig.New()

    //Provide方法用來設置依賴的對象
    er := c.Provide(NewConfig)
    if err != nil {
        panic(err)
    }

    //設置依賴的對象
    err = c.Provide(NewLogger)
    if err != nil {
        panic(err)
    }
    
    //執(zhí)行Handle()方法
    //Handle依賴 Config 和 Logger,使用Invoke執(zhí)行方法時會自動注入依賴(依賴的對象要傳入Provide方法中)
    err = c.Invoke(Handle)
    if err != nil {
        panic(err)
    }
    // Output:
    // [foo] You've been invoked
}

dig提供了一個容器(container),所有的依賴項通過Provide方法添加,執(zhí)行某個方法時使用Invoke方法,該方法會自動注入所需要的依賴。

dig使用反射機制解決DI問題,所以代碼執(zhí)行性能上會有損耗

并且因為使用反射所以可能出現(xiàn)編譯時沒有錯誤,執(zhí)行時報空指針

詳情使用方法可以參考官方文檔,dig可以繼承到gin框架中,有興趣的可以看看資料。

筆者不太喜歡這種使用方式,為了依賴注入破壞了代碼原有的調(diào)用方式。

基于代碼生成的DI

wire庫是google出的解決golang DI問題的工具,它可以 自動生成依賴注入的代碼,節(jié)省了手動去處理依賴關系

github地址

wire對原有代碼的侵入度很低,開發(fā)過程中,在依賴注入代碼處調(diào)用Build方法(例子中是初始化controller對象)就可以了

// +build wireinject

package main

import (
    "encoding/json"
    "fmt"
    "github.com/google/wire"
    "net/http"
)

type DataSource struct {
    Operation string
}

func NewDataSource() DataSource {
    return DataSource{Operation: "operation_name"}
}

//==================

type Dao struct {
    DataSource DataSource
}

func NewDao(ds DataSource) *Dao {
    return &Dao{
        DataSource: ds,
    }
}

func (d *Dao) GetItemList() ([]string, error) {
    //TODO 拿到DB對象做查詢操作
    fmt.Printf("db object: %s", d.DataSource.Operation)
    return []string{d.DataSource.Operation, "item1", "item2"}, nil
}

//====================

type Service struct {
    Dao *Dao
}

func NewService(dao *Dao) *Service {
    return &Service{Dao: dao}
}

func (s *Service) GetItemList() ([]string, error) {
    return s.Dao.GetItemList()
}

//=====================

type Controller struct {
    Service *Service
}

func NewController(service *Service) *Controller {
    return &Controller{Service: service}
}

func (c *Controller) GetItemList() ([]string, error) {
    return c.Service.GetItemList()
}

var MegaSet = wire.NewSet(NewDataSource, NewDao, NewService, NewController)

func initializeController() *Controller {
    wire.Build(MegaSet)
    return &Controller{}
}

func getItemList(w http.ResponseWriter, r *http.Request) {
    controller := initializeController()
    itemList, _ := controller.GetItemList()
    output, _ := json.Marshal(itemList)
    fmt.Fprintf(w, string(output))
}

func main() {
    http.HandleFunc("/items", getItemList)
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        panic(err)
    }
}

然后再項目根目錄執(zhí)行wire命令,會生成構建好依賴關系的代碼(以_gen結尾的文件)

// Code generated by Wire. DO NOT EDIT.

//go:generate go run github.com/google/wire/cmd/wire
//+build !wireinject

package main

import (
    "encoding/json"
    "fmt"
    "github.com/google/wire"
    "net/http"
)

// Injectors from main.go:
// 此處是生成的代碼
func initializeController() *Controller {
    dataSource := NewDataSource()
    dao := NewDao(dataSource)
    service := NewService(dao)
    controller := NewController(service)
    return controller
}

// main.go:

type DataSource struct {
    Operation string
}

func NewDataSource() DataSource {
    return DataSource{Operation: "operation_name"}
}

type Dao struct {
    DataSource DataSource
}

func NewDao(ds DataSource) *Dao {
    return &Dao{
        DataSource: ds,
    }
}

func (d *Dao) GetItemList() ([]string, error) {
    fmt.Printf("db object: %s", d.DataSource.Operation)
    return []string{d.DataSource.Operation, "item1", "item2"}, nil
}

type Service struct {
    Dao *Dao
}

func NewService(dao *Dao) *Service {
    return &Service{Dao: dao}
}

func (s *Service) GetItemList() ([]string, error) {
    return s.Dao.GetItemList()
}

type Controller struct {
    Service *Service
}

func NewController(service *Service) *Controller {
    return &Controller{Service: service}
}

func (c *Controller) GetItemList() ([]string, error) {
    return c.Service.GetItemList()
}

var MegaSet = wire.NewSet(NewDataSource, NewDao, NewService, NewController)

func getItemList(w http.ResponseWriter, r *http.Request) {
    controller := initializeController()
    itemList, _ := controller.GetItemList()
    output, _ := json.Marshal(itemList)
    fmt.Fprintf(w, string(output))
}

func main() {
    http.HandleFunc("/items", getItemList)
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        panic(err)
    }
}

關鍵代碼:

//執(zhí)行wire命令前的代碼
func initializeController() *Controller {
    wire.Build(MegaSet)
    return &Controller{}
}

//執(zhí)行后生成的代碼
// Injectors from main.go:
func initializeController() *Controller {
    dataSource := NewDataSource()
    dao := NewDao(dataSource)
    service := NewService(dao)
    controller := NewController(service)
    return controller
}

通過生成代碼解決依賴注入的問題,既能提升開發(fā)效率,又不影響代碼性能,wire更高級的用法可以去github document查看

  • tips: 如果報錯誤 other declaration of xxxx ,請在源文件頭加上 //+build wireinject
  • go-zero框架也是用wire解決DI問題

到此這篇關于淺析golang的依賴注入的文章就介紹到這了,更多相關go依賴注入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 深入解析Go語言中for循環(huán)的寫法

    深入解析Go語言中for循環(huán)的寫法

    這篇文章主要介紹了Go語言中for循環(huán)的寫法,是Golang入門學習中的基礎知識,需要的朋友可以參考下
    2015-10-10
  • 使用Go+GoQuery庫實現(xiàn)頭條新聞采集

    使用Go+GoQuery庫實現(xiàn)頭條新聞采集

    在本文中,我們將介紹如何使用Go語言和GoQuery庫實現(xiàn)一個簡單的爬蟲程序,用于抓取頭條新聞的網(wǎng)頁內(nèi)容,我們還將使用爬蟲代理服務,提高爬蟲程序的性能和安全性,我們將使用多線程技術,提高采集效率,最后,我們將展示爬蟲程序的運行結果和代碼,需要的朋友可以參考下
    2023-10-10
  • 一文詳解go mod依賴管理詳情

    一文詳解go mod依賴管理詳情

    這篇文章主要介紹了一文詳解go mod依賴管理詳情,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下
    2022-07-07
  • go?sync.Once實現(xiàn)高效單例模式詳解

    go?sync.Once實現(xiàn)高效單例模式詳解

    這篇文章主要為大家介紹了go?sync.Once實現(xiàn)高效單例模式詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • Go語言中的函數(shù)式編程實踐

    Go語言中的函數(shù)式編程實踐

    這篇文章主要介紹了Go語言中的函數(shù)式編程實踐,主要講解Go語言中的函數(shù)式編程概念和使用。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • Go?常見設計模式之單例模式詳解

    Go?常見設計模式之單例模式詳解

    單例模式是設計模式中最簡單的一種模式,單例模式能夠確保無論對象被實例化多少次,全局都只有一個實例存在,在Go?語言有多種方式可以實現(xiàn)單例模式,所以我們今天就來一起學習下吧
    2023-07-07
  • Go語言面試題之select和channel的用法

    Go語言面試題之select和channel的用法

    金九銀十面試季到了(PS:貌似今年一年都是面試季),就業(yè)環(huán)境很差,導致從業(yè)人員不得不卷。本文將重點講解一下Go面試進階知識點之select和channel,需要的可以參考一下
    2022-09-09
  • Go語言深度拷貝工具deepcopy的使用教程

    Go語言深度拷貝工具deepcopy的使用教程

    今天給大家推薦的工具是deepcopy,一個可以對指針、接口、切片、結構體、Map都能進行深拷貝的工具,感興趣的小伙伴快跟隨小編一起學習學習
    2022-09-09
  • Go語言同步與異步執(zhí)行多個任務封裝詳解(Runner和RunnerAsync)

    Go語言同步與異步執(zhí)行多個任務封裝詳解(Runner和RunnerAsync)

    這篇文章主要給大家介紹了關于Go語言同步與異步執(zhí)行多個任務封裝(Runner和RunnerAsync)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2018-01-01
  • Go語言reflect包的反射機制基本用法示例

    Go語言reflect包的反射機制基本用法示例

    反射在處理接口和類型斷言、開發(fā)通用功能或者設計框架時尤為重要,本文將深入探索 Go 語言中的反射機制,通過具體的示例展示如何使用?reflect?包,讓你能夠在 Go 項目中有效地利用這一強大的工具
    2023-11-11

最新評論

南阳市| 库伦旗| 柳林县| 光山县| 彭山县| 松溪县| 台东市| 河西区| 郁南县| 龙里县| 乐山市| 德兴市| 奇台县| 定结县| 大埔县| 平果县| 绍兴市| 延安市| 昭通市| 海原县| 邵武市| 隆化县| 汕尾市| 涿鹿县| 佛坪县| 伊金霍洛旗| 镇坪县| 陈巴尔虎旗| 蓬莱市| 惠来县| 道孚县| 天长市| 宝山区| 通化市| 太保市| 商水县| 大同县| 钟祥市| 正安县| 聊城市| 周宁县|