2017-02-17 85 views
1

我在一個包中有一個耗費時間的方法的結構,並且通過它的工廠函數構造也很費時。因此,在依賴於這個其他結構的包中,我希望能夠在創建後使用假工廠函數和僞結構對其進行測試。由於結構是通過工廠函數構造的,所以我想假冒工廠函數並在測試期間將另一個工廠函數傳遞到我的結構中。返回與接口一起使用的結構的Go函數類型

昂貴的包的一個例子是:

package expensive 

import "fmt" 

type myStruct struct{} 

func (m *myStruct) DoSomething() { 
    fmt.Println("In Do something") 
} 

func (m *myStruct) DoSomethingElse() { 
    fmt.Println("In do something else") 
} 

// CreateInstance is expensive to call 
func CreateInstance() *myStruct { 
    return &myStruct{} 
} 

使用此然後我的主要包裝看起來是這樣的:

package main 

import "play/expensive" 

func main() { 
    thing := structToConstruct{expensive.CreateInstance} 
    thing.performAction() 
} 

type myInterface interface { 
    DoSomething() 
} 

type structToConstruct struct { 
    factoryFunction func() myInterface 
} 

func (s *structToConstruct) performAction() { 
    instance := s.factoryFunction() 
    instance.DoSomething() 
} 

然而,這個代碼與錯誤抱怨:

.\main.go:6: cannot use expensive.CreateInstance (type func() *expensive.myStruct) as type func() myInterface in field value

但是,* expensive.myStruct 確實實現myInterface接口,所以我不明白爲什麼Go會抱怨此設置的類型安全。

因爲我已經@jmaloney guideance之後才意識到,我可能只是包裝器我的函數像這樣在我的主要方法:

wrapper := func() myInterface { 
     return expensive.CreateInstance() 
    } 
    thing := structToConstruct{wrapper} 

,這對當時的作品,但我還是不明白爲什麼我可以」當函數期望返回該接口的實例時,使用一個實現了接口的結構,特別是在此修復程序中不需要類型斷言/轉換時,因爲它只是調用底層工廠函數。

編輯:我已經遇到這個建議,將其添加到該語言。該提案被否決:

https://github.com/golang/go/issues/12754

+0

增加了一個有用的希望解釋我的回答你的問題的更新。 – jmaloney

回答

3

getInstance需要返回myInterface

package main 

import "fmt" 

func main() { 
    var function func() myInterface 

    function = getInstance 

    newSomething := function() 

    newSomething.doSomething() 
} 

type myInterface interface { 
    doSomething() 
} 

type myStruct struct{} 

func (m *myStruct) doSomething() { 
    fmt.Println("doing something") 
} 

func getInstance() myInterface { 
    return &myStruct{} 
} 

Playground example

However, *expensive.myStruct does implement the myInterface interface so I do not understand why Go is complaining about the type safety of this setup.

在你不處理你處理類型Go的界面,例如你的結構簽名。

當您首次聲明您的結構爲factoryFunction func() *myFunction factoryFunction現在總是需要匹配聲明的簽名。

+0

謝謝jmaloney,不幸的是在我的真實代碼中,這是不可能的,因爲「getInstance」函數存在於另一個包中。此外,「myStruct」不僅限於一種方法,因此不希望限制工廠方法只生成此一用例中調用代碼所需的有限接口。 –

+0

您可以提供更多詳情嗎?沒有更多的上下文很難去思考。 – jmaloney

+0

感謝@ jmaloney的反饋,我已經重寫了這個問題和例子,以便更準確地瞭解我的情況,所以希望這會有所幫助。在這樣做的過程中,我也找到了一種方法來實現它,但我仍然不明白爲什麼Go類型系統不會讓我使用返回結構體的函數來做它,所以任何指導都會被讚賞! –

1

看看這可能有幫助,有一個函數返回一個給定結構的接口。

package main 

import "fmt" 

func main() { 
    var instance myInterface 

    // The return value of the getInstance function can be assigned to a variable 
    // of type myInterface 
    instance = getInstance() 

    var function func(*myStruct) myInterface 

    // But the function itself can't be assigned to a variable for a function 
    // that returns a myInterface. You get: 
    // cannot use getInstance (type func() *myStruct) as type func() myInterface in assignment 
    function = getMyInstance 
    r := function(instance.(*myStruct)) 
    r.doSomething() 
} 

type myInterface interface { 
    doSomething() 
} 

type myStruct struct{} 

func (m *myStruct) doSomething() { 
    fmt.Println("Done something") 

} 

func getInstance() *myStruct { 
    return &myStruct{} 
} 

func getMyInstance(myInst *myStruct) myInterface { 
    return myInst 

} 

可在https://play.golang.org/p/h8iJ0i-Xym