2016-04-18 110 views
0

我提供了一些工作,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") 
    } 
} 

回答

0

第一步只是改变你的GetConn声明略微以下几点:

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

这应该履行的ConnPoolInterface接口。您可能需要稍微重新排列代码以避免循环依赖。

+0

感谢答复,但我不能这样做:connpool包不包含任何接口,通过添加它,我们会改变什么,这将成为pool.ConnInterface主packege,不ConnInterface,所以我们仍然有漏依赖 – user2191327

+0

对我来说,似乎是做了正确的方法是把接口在原来执行的位置('connpool')相同的包。或者你无法修改'connpool'软件包?在这种情况下,我不明白你的依赖漏洞的含义。如果您在同一个软件包中混用实现和接口,您可以将这些接口放在它们自己的包中。尽管如此,我并不真正看到这一点。 –

+0

好,我不是很雄辩,我刚添加了新的信息与测试例的问题,希望这将解释为什么我想声明的主要封装接口,感谢您的关注 – user2191327