带接口的依赖注入问题

时间:2016-04-18 07:43:28

标签: go

我有一些包提供了一些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")
  }
}

1 个答案:

答案 0 :(得分:0)

首先,只需将GetConn的声明稍微更改为以下内容:

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

这应该符合ConnPoolInterface的界面。您可能需要稍微重新排列代码以避免循环依赖。

相关问题