簡體   English   中英

接口的依賴項注入問題

[英]issue with dependency injection with interface

我有提供與tcp連接一起工作的軟件包,基本上是這樣的:

package connpool

import (
    "io/ioutil"
    "net/http"
)

type ConnPool struct{}

func (pool *ConnPool) GetConn() Conn {
    return Conn{}
}

func (pool *ConnPool) ReleaseConnection(conn Conn)  {

}

type Conn struct{}

func (c Conn) FetchUrl(url string) ([]byte, error) {
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        return []byte{}, err
    }
    client := &http.Client{}
    resp, _ := client.Do(req)
    defer resp.Body.Close()
    body, _ := ioutil.ReadAll(resp.Body)
    return body, nil
}

然后我嘗試在另一個程序包中使用它,但按接口將其包裝起來,因為我想用假connpool在測試環境中替換此程序包

package main

import (
    "connpool"
    "fmt"
)

func onlyDependencyOnConnPool() *connpool.ConnPool {
    return &connpool.ConnPool{}
}

type ConnPoolInterface interface {
    GetConn() ConnInterface
    ReleaseConnection(ConnInterface)
}

type ConnInterface interface {
    FetchUrl(string) ([]byte, error)
}

type Fetcher struct{}

func (f Fetcher) Fetch(cPool ConnPoolInterface) error {
    conn := cPool.GetConn()
    defer cPool.ReleaseConnection(conn)
    body, err := conn.FetchUrl("http://localhost:9200")
    fmt.Println("body: ", string(body))
    return err
}

func main() {
    pool := onlyDependencyOnConnPool()
    f := Fetcher{}
    f.Fetch(pool)
}

但是它將在編譯時返回錯誤:

./main.go:34: cannot use pool (type *connpool.ConnPool) as type ConnPoolInterface in argument to f.Fetch:
    *connpool.ConnPool does not implement ConnPoolInterface (wrong type for GetConn method)
        have GetConn() connpool.Conn
        want GetConn() ConnInterface

有沒有辦法在每個文件中沒有connpool導入的情況下通過接口包裝此依賴項?

我只需要它來模擬測試環境中的http請求,就像這樣(如果我要在connpool包中實現接口,則我必須在其中實現每個模擬結構,看起來就像是一團糟):

package main

import(
  "testing"
)

type FakeConnPool struct{}

func (pool *FakeConnPool) GetConn() FakeConn {
    return FakeConn{}
}

func (pool *FakeConnPool) ReleaseConnection(conn FakeConn)  {
}

type FakeConn struct{}

func (c FakeConn) FetchUrl(url string) ([]byte, error) {
  println(url)
  body := []byte(`{"status" : 200}`)
    return body, nil
}

func changeDependency() ConnPoolInterface {
  return &FakeConnPool{}
}
func TestBaz(t *testing.T)  {
  pool := changeDependency()
    f := Fetcher{}
    err := f.Fetch(pool)
  if err != nil {
    t.Errorf("error")
  }
}

第一步,將您對GetConn的聲明稍微更改為以下內容:

func (pool *ConnPool) GetConn() ConnInterface {  // Conn -> ConnInterface
    return Conn{}
}

那應該滿足ConnPoolInterface的接口。 您可能必須稍稍重新排列代碼,以免之后出現循環依賴。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM