2016-04-18 109 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