日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

依賴注入與控制反轉:優化Go語言REST API客戶端

來源: 責編: 時間:2023-12-09 15:21:28 323觀看
導讀在這篇文章中,我將探討依賴注入(DI)和控制反轉(IoC)是什么,以及它們的重要性。作為示例,我將使用Monibot的REST API客戶端。讓我們開始吧:一個簡單的客戶端實現我們從一個簡單的客戶端實現開始,允許調用者訪問Monibot的REST AP

在這篇文章中,我將探討依賴注入(DI)和控制反轉(IoC)是什么,以及它們的重要性。作為示例,我將使用Monibot的REST API客戶端。讓我們開始吧:LIM28資訊網——每日最新資訊28at.com

一個簡單的客戶端實現

我們從一個簡單的客戶端實現開始,允許調用者訪問Monibot的REST API,具體來說,是為了發送指標值。客戶端的實現可能如下所示:LIM28資訊網——每日最新資訊28at.com

package monibottype Client struct {}func NewClient() *Client {    return &Client{}}func (c *Client) PostMetricValue(value int) {    body := fmt.Sprintf("value=%d", value)    http.Post("https://monibot.io/api/metric", []byte(body))}

這里有一個客戶端,提供了PostMetricValue方法,該方法用于將指標值上傳到Monibot。我們的庫的用戶可能像這樣使用它:LIM28資訊網——每日最新資訊28at.com

import "monibot"func main() {    // 初始化API客戶端    client := monibot.NewClient()    // 發送指標值    client.PostMetricValue(42)}

依賴注入

現在假設我們想對客戶端進行單元測試。當所有HTTP發送代碼都是硬編碼的時候,我們如何測試客戶端呢?對于每次測試運行,我們都需要一個“真實”的HTTP服務器來回答我們發送給它的所有請求。不可取!我們可以做得更好:讓我們將HTTP處理作為“依賴”;讓我們發明一個 Transport 接口:LIM28資訊網——每日最新資訊28at.com

package monibot// Transport傳輸請求。type Transport interface {    Post(url string, body []byte)}

讓我們再發明一個具體的使用HTTP作為通信協議的Transport:LIM28資訊網——每日最新資訊28at.com

package monibot// HTTPTransport是一個使用HTTP協議傳輸請求的Transport。type HTTPTransport struct {}func (t HTTPTransport) Post(url string, data []byte) {    http.Post(url, data)}

然后讓我們重寫客戶端,使其“依賴”于一個Transport 接口:LIM28資訊網——每日最新資訊28at.com

package monibottype Client struct {    transport Transport}func NewClient(transport Transport) *Client {    return &Client{transport}}func (c *Client) PostMetricValue(value int) {    body := fmt.Sprintf("value=%d", value)    c.transport.Post("https://monibot.io/api/metric", []byte(body))}

現在,客戶端將請求轉發到它的Transport依賴。當創建客戶端時,transport(客戶端的依賴項)被“注入”到客戶端中。調用者可以這樣初始化一個客戶端:LIM28資訊網——每日最新資訊28at.com

import "monibot"func main() {    // 初始化API客戶端    var transport monibot.HTTPTransport    client := monibot.NewClient(transport)    // 發送指標值    client.PostMetricValue(42)}

單元測試

現在我們可以編寫一個使用“偽造”Transport的單元測試:LIM28資訊網——每日最新資訊28at.com

// TestPostMetricValue確保客戶端向REST API發送正確的POST請求。func TestPostMetricValue(t *testing.T) {    transport := &fakeTransport{}    client := NewClient(transport)    client.PostMetricValue(42)    if len(transport.calls) != 1 {        t.Fatal("期望1次傳輸調用,但是是%d次", len(transport.calls))    }    if transport.calls[0] != "POST https://monibot.io/api/metric, body=//"value=42//"" {        t.Fatal("錯誤的傳輸調用 %q", transport.calls[0])    }}// 偽造的Transport是單元測試中使用的Transport。type fakeTransport struct {    calls []string}func (f *fakeTransport) Post(url string, body []byte) {    f.calls = append(f.calls, fmt.Sprintf("POST %v, body=%q", url, string(body)))}

添加更多的Transport函數

現在假設我們庫的其他部分,也使用了Transport功能,需要比POST更多的HTTP方法。對于它們,我們必須擴展我們的Transport接口:LIM28資訊網——每日最新資訊28at.com

package monibot// Transport傳輸請求。type Transport interface {    Get(url string) []byte     // 添加,因為health-monitor需要    Post(url string, body []byte)    Delete(url string)         // 添加,因為resource-monitor需要}

現在我們有一個問題。編譯器抱怨我們的fakeTransport不再滿足Transport接口。所以讓我們通過添加缺失的函數來解決它:LIM28資訊網——每日最新資訊28at.com

// 偽造的Transport是單元測試中使用的Transport。type fakeTransport struct {    calls []string}func (f *fakeTransport) Get(url string) []byte {    panic("不使用")}func (f *fakeTransport) Post(url string, body []byte) {    f.calls = append(f.calls, fmt.Sprintf("POST %v, body=%q", url, string(body)))}func (f *fakeTransport) Delete(url string) {    panic("不使用")}

我們做了什么?由于在單元測試中我們不需要新的Get()和Delete()函數,如果它們被調用,我們就拋出異常。這里有一個問題:每次在Transport中添加新函數時,我們都會破壞現有的fakeTransport實現。對于大型代碼庫來說,這將導致維護噩夢。我們能做得更好嗎?LIM28資訊網——每日最新資訊28at.com

控制反轉

問題在于我們的客戶端(和相應的單元測試)依賴于一個它們不能控制的類型。在這種情況下,它是Transport接口。為了解決這個問題,讓我們通過引入一個未導出的接口,該接口僅聲明了我們的客戶端所需的內容,來反轉控制:LIM28資訊網——每日最新資訊28at.com

package monibot// clientTransport傳輸Client的請求。type clientTransport interface {    Post(url string, body []byte)}type Client struct {    transport clientTransport}func NewClient(transport clientTransport) *Client {    return &Client{transport}}func (c *Client) PostMetricValue(value int) {    body := fmt.Sprintf("value=%d", value)    c.transport.Post("https://monibot.io/api/metric", []byte(body))}

現在讓我們將我們的單元測試更改為使用假的clientTransport:LIM28資訊網——每日最新資訊28at.com

// TestPostMetricValue確保客戶端向REST API發送正確的POST請求。func TestPostMetricValue(t *testing.T) {    transport := &fakeTransport{}    client := NewClient(transport)    client.PostMetricValue(42)    if len(f.calls) != 1 {        t.Fatal("期望1次傳輸調用,但是是%d次", len(f.calls))    }    if f.calls[0] != "POST https://monibot.io/api/metric, body=//"value=42//"" {        t.Fatal("錯誤的傳輸調用 %q", f.calls[0])    }}// 偽造的Transport是在單元測試中使用的clientTransport。type fakeTransport struct {    calls []string}func (f *fakeTransport) Post(url string, body []byte) {    f.calls = append(f.calls, fmt.Sprintf("POST %v, body=%q", url, string(body)))}

由于Go的隱式接口實現(如果愿意,可以稱之為'鴨子類型'),我們庫的用戶什么也不需要改變:LIM28資訊網——每日最新資訊28at.com

import "monibot"func main() {    // 初始化API客戶端    var transport monibot.HTTPTransport    client := monibot.NewClient(transport)    // 發送指標值    client.PostMetricValue(42)}

重新審視Transport

如果我們使IoC成為規范(正如我們應該做的那樣),就不再需要導出Transport接口了。為什么呢?因為如果消費者需要一個接口,讓他們在自己的作用域中定義它,就像我們對'clientTransport'做的那樣。LIM28資訊網——每日最新資訊28at.com

不要導出接口。導出具體實現。如果消費者需要接口,讓他們在自己的作用域中定義。LIM28資訊網——每日最新資訊28at.com

總結

在這篇文章中,我展示了如何以及為什么在Go中使用DI和IoC。正確使用DI/IoC可以導致更易于測試和維護的代碼,特別是在代碼庫不斷增長時。雖然代碼示例是用Go編寫的,但這里描述的原則同樣適用于其他編程語言。LIM28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-40651-0.html依賴注入與控制反轉:優化Go語言REST API客戶端

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 一致性哈希:數據分片與負載均衡的黃金法則

下一篇: 微軟:VS Code已成為Java巨頭!

標簽:
  • 熱門焦點
  • 對標蘋果的靈動島 華為帶來實況窗功能

    繼蘋果的靈動島之后,華為也在今天正式推出了“實況窗”功能。據今天鴻蒙OS 4.0的現場演示顯示,華為的實況窗可以更高效的展現出實時通知,比如鎖屏上就能看到外賣、打車、銀行
  • 6月安卓手機性能榜:vivo/iQOO霸占旗艦排行榜前三

    2023年上半年已經正式過去了,我們也迎來了安兔兔V10版本,在新的驍龍8Gen3和天璣9300發布之前,性能榜的榜單大體會以驍龍8Gen2和天璣9200+為主,至于那顆3.36GHz的驍龍8Gen2領先
  • 六大權益!華為8月服務日開啟:手機免費貼膜、維修免人工費

    8月5日消息,一年一度的華為開發者大會2023(Together)日前在松山湖拉開帷幕,與此同時,華為8月服務日也式開啟,到店可享六大專屬權益。華為用戶可在華為商城Ap
  • SpringBoot中使用Cache提升接口性能詳解

    環境:springboot2.3.12.RELEASE + JSR107 + Ehcache + JPASpring 框架從 3.1 開始,對 Spring 應用程序提供了透明式添加緩存的支持。和事務支持一樣,抽象緩存允許一致地使用各
  • 自律,給不了Keep自由!

    來源 | 互聯網品牌官作者 | 李大為編排 | 又耳 審核 | 谷曉輝自律能不能給用戶自由暫時不好說,但大概率不能給Keep自由。近日,全球最大的在線健身平臺Keep正式登陸港交所,努力
  • 消費結構調整丨巨頭低價博弈,拼多多還卷得動嗎?

    來源:征探財經作者:陳香羽隨著流量紅利的退潮,電商的存量博弈越來越明顯。曾經主攻中高端與品質的淘寶天貓、京東重拾“低價”口號。而過去與他們錯位競爭的拼多多,靠
  • 阿里大調整

    來源:產品劉有媒體報道稱,近期淘寶天貓集團啟動了近年來最大的人力制度改革,涉及員工績效、層級體系等多個核心事項,目前已形成一個初步的“征求意見版”:1、取消P序列
  • 英特爾Xe-HP項目終止,將專注Xe-HPC/HPG系列顯卡

    據10 月 31 日消息報道,英特爾高級副總裁兼加速計算系統和圖形事業部總經理 表示,Xe-HP“ Arctic Sound” 系列服務器 GPU 已經應用于 oneAPI devcloud 云服
  • 最薄的14英寸游戲筆記本電腦 Alienware X14已可以購買

    2022年1月份在國際消費電子展(CES2022)上首次亮相的Alienware新品——Alienware X14現在已經可以購買了,這款筆記本電腦被譽為世界上最薄的 14 英寸游戲筆
Top 主站蜘蛛池模板: 唐海县| 惠州市| 沈丘县| 乌兰县| 商都县| 滦南县| 麟游县| 会同县| 顺昌县| 股票| 琼海市| 朔州市| 五家渠市| 巴东县| 安平县| 泉州市| 聂拉木县| 平邑县| 陵川县| 铜陵市| 岳阳县| 清镇市| 宁河县| 建宁县| 洪湖市| 新安县| 济源市| 蕉岭县| 清流县| 赤城县| 北票市| 武强县| 镇安县| 崇礼县| 高雄市| 小金县| 全南县| 麻阳| 阳朔县| 侯马市| 昭平县|