简体   繁体   English

接口的依赖项注入问题

[英]issue with dependency injection with interface

I have the package that provides some work with tcp connections, basically something like: 我有提供与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
}

then i try to use it in another package, but wrapping it by interface, because i want substitute this package in test environment with fake connpool 然后我尝试在另一个程序包中使用它,但按接口将其包装起来,因为我想用假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)
}

but it will return error on compile: 但是它将在编译时返回错误:

./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

Is the any way to wrap this dependency by interface without connpool import in every file? 有没有办法在每个文件中没有connpool导入的情况下通过接口包装此依赖项?

I need it just to mock the http requests in my test environment, something like this(if i will implement interfaces in the connpool package i will have to implement every mock struct in it, it look like some kind of mess): 我只需要它来模拟测试环境中的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")
  }
}

As a first step just change your declaration of GetConn slightly to the following: 第一步,将您对GetConn的声明稍微更改为以下内容:

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

That should fulfill the interface of ConnPoolInterface . 那应该满足ConnPoolInterface的接口。 You would probably have to rearrange your code slightly to avoid circular dependencies after that. 您可能必须稍稍重新排列代码,以免之后出现循环依赖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM