Re: [go-nuts] Issue implementing interface method that returns another interface

2023-03-02 Thread Rick Schubert
Thank you for the help @Axel Wagner

On Tuesday, 28 February 2023 at 18:20:54 UTC Axel Wagner wrote:

> You are running into this: https://go.dev/doc/faq#covariant_types
>
> > How could I do that?
>
> You probably have to write a wrapper. Or change the concrete type to 
> return an interface. Or test using the concrete type, instead of using 
> mocks.
>
> On Tue, Feb 28, 2023 at 6:08 PM Rick Schubert  
> wrote:
>
>> I am having a question about how to implement interfaces correctly in Go 
>> when it comes to third-party packages that use chained methods. I have 
>> compiled an example project below for you so that you can understand the 
>> problem.
>>
>>
>> package main
>>
>> import (
>> myAPI "github.com/hashicorp/vault/api"
>> )
>>
>> var myClient *myAPI.Client
>>
>> type MyProvider interface {
>> GetClient() MyAPIClient
>> }
>>
>> type MyAPIClient interface {
>> // I want to do this but it does not work
>> Logical() MyAPILogical
>> // This works though
>> // Logical() *myAPI.Logical
>> }
>>
>> type MyAPILogical interface {
>> Write(path string, data map[string]interface{}) (*myAPI.Secret, error)
>> }
>>
>> type Provider struct {}
>>
>> func PublicFunctionIWantToTest(provider MyProvider) {
>> client := provider.GetClient()
>> // We normally do something here with the 'client' variable, but important
>> // is that we forward it later on
>> privateFunctionThatIsUsedInTheTest(client)
>> }
>>
>> func privateFunctionThatIsUsedInTheTest(client MyAPIClient) 
>> (*myAPI.Secret, error) {
>> return client.Logical().Write(
>> "/here/goes/some/path",
>> map[string]interface{}{
>> "key": "value",
>> },
>> )
>> }
>>
>> func NewProvider() MyProvider {
>> return Provider{}
>> }
>>
>> func (p Provider) GetClient() MyAPIClient {
>> return myClient
>> }
>>
>> // Empty function just so that this example can be built
>> func main() {}
>>
>>
>> As you can see, the package has a chained method Logical().Write() . 
>> Since I want to create tests for PublicFunctionIWantToTest, I want to 
>> pass down all the functionality as interface so that I can use 
>> https://vektra.github.io/mockery/ to create mocks for it.
>>
>> Unfortunately, I am hitting an issue with my MyAPIClient and the 
>> MyAPILogical interface. Since I can see in the package's documentation (
>> https://pkg.go.dev/github.com/hashicorp/vault/a...@v1.8.1#Logical.Write 
>> ) 
>> that the Logical() method returns a Logical instance, I want to make it 
>> so that interface method returns the other interface MyAPILogical (line 
>> 15). This does not work though, there is an error on line 47 in the 
>> GetClient() method saying that I would not implement the interface 
>> correctly. How could I do that?
>>
>> cannot use myClient (variable of type *api.Client) as MyAPIClient value 
>> in return statement: *api.Client does not implement MyAPIClient (wrong type 
>> for method Logical)
>> have Logical() *api.Logical
>> want Logical() MyAPILogicalcompilerInvalidIfaceAssign
>>
>> Thank you kindly
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to golang-nuts...@googlegroups.com.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/golang-nuts/1bf2aef5-14af-4565-8f4c-538a1edeb380n%40googlegroups.com
>>  
>> 
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/6ecb374a-e204-4069-98c8-ed2195f10945n%40googlegroups.com.


Re: [go-nuts] Issue implementing interface method that returns another interface

2023-02-28 Thread 'Axel Wagner' via golang-nuts
You are running into this: https://go.dev/doc/faq#covariant_types

> How could I do that?

You probably have to write a wrapper. Or change the concrete type to return
an interface. Or test using the concrete type, instead of using mocks.

On Tue, Feb 28, 2023 at 6:08 PM Rick Schubert 
wrote:

> I am having a question about how to implement interfaces correctly in Go
> when it comes to third-party packages that use chained methods. I have
> compiled an example project below for you so that you can understand the
> problem.
>
>
> package main
>
> import (
> myAPI "github.com/hashicorp/vault/api"
> )
>
> var myClient *myAPI.Client
>
> type MyProvider interface {
> GetClient() MyAPIClient
> }
>
> type MyAPIClient interface {
> // I want to do this but it does not work
> Logical() MyAPILogical
> // This works though
> // Logical() *myAPI.Logical
> }
>
> type MyAPILogical interface {
> Write(path string, data map[string]interface{}) (*myAPI.Secret, error)
> }
>
> type Provider struct {}
>
> func PublicFunctionIWantToTest(provider MyProvider) {
> client := provider.GetClient()
> // We normally do something here with the 'client' variable, but important
> // is that we forward it later on
> privateFunctionThatIsUsedInTheTest(client)
> }
>
> func privateFunctionThatIsUsedInTheTest(client MyAPIClient)
> (*myAPI.Secret, error) {
> return client.Logical().Write(
> "/here/goes/some/path",
> map[string]interface{}{
> "key": "value",
> },
> )
> }
>
> func NewProvider() MyProvider {
> return Provider{}
> }
>
> func (p Provider) GetClient() MyAPIClient {
> return myClient
> }
>
> // Empty function just so that this example can be built
> func main() {}
>
>
> As you can see, the package has a chained method Logical().Write() .
> Since I want to create tests for PublicFunctionIWantToTest, I want to
> pass down all the functionality as interface so that I can use
> https://vektra.github.io/mockery/ to create mocks for it.
>
> Unfortunately, I am hitting an issue with my MyAPIClient and the
> MyAPILogical interface. Since I can see in the package's documentation (
> https://pkg.go.dev/github.com/hashicorp/vault/api@v1.8.1#Logical.Write)
> that the Logical() method returns a Logical instance, I want to make it
> so that interface method returns the other interface MyAPILogical (line
> 15). This does not work though, there is an error on line 47 in the
> GetClient() method saying that I would not implement the interface
> correctly. How could I do that?
>
> cannot use myClient (variable of type *api.Client) as MyAPIClient value in
> return statement: *api.Client does not implement MyAPIClient (wrong type
> for method Logical)
> have Logical() *api.Logical
> want Logical() MyAPILogicalcompilerInvalidIfaceAssign
>
> Thank you kindly
>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/golang-nuts/1bf2aef5-14af-4565-8f4c-538a1edeb380n%40googlegroups.com
> 
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAEkBMfGwN3GkWvMhBUf0MeNpBtR%2B%2B6zZHxYMF3WKxccdasQbsg%40mail.gmail.com.