Go 接口的依赖项注入问题

Go 接口的依赖项注入问题,go,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

我有一个包,它提供了一些关于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包中实现接口,我必须实现其中的每个模拟结构,它看起来像某种混乱):


作为第一步,只需将
GetConn
的声明稍微更改为以下内容:

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

这应该满足
ConnPoolInterface
的接口。您可能需要稍微重新排列代码,以避免此后出现循环依赖关系。

谢谢您的回复,但我不能这样做:connpool包不包含该接口,添加该接口后,我们将不做任何更改,它将成为主包中的pool.connPoice,而不是ConnPoice,因此,我们仍然会有泄漏的依赖项。似乎正确的方法是将接口放在原始实现所在的同一个包中(
connpool
)。或者您无法修改
connpool
包?在这种情况下,我真的不明白你所说的泄漏依赖是什么意思。如果您反对将实现和接口混合在同一个包中,您可以将接口放在它们自己的包中。不过,我并不认为这有什么意义。嗯,我不是很能说会道,我只是在问题中添加了新的信息和测试示例,希望它能解释我为什么要在主包中声明接口,谢谢你的关注抱歉,我真的不理解你的问题。如果要模拟接口,就必须实现它们。对吗?我也许能理解你想做什么。您希望连接池上的所有方法在仍然实现
ConnPoolInterface
的同时获取并返回具体类型的连接。是这样吗?我认为那是不可能的。我仍然认为在connpool中使用接口是正确的做法。毕竟,随着程序的增长,您可能不希望所有内容都在
main
中。对于测试,您可以添加几个助手函数和结构来创建模拟连接池和连接。然后可以在测试中使用这些数据,以减少重复。
func (pool *ConnPool) GetConn() ConnInterface {  // Conn -> ConnInterface
    return Conn{}
}