0

I have the following code snippet that does not compile:

func (r *ProviderServer) ListProvider(ctx context.Context, in *emptypb.Empty) (*versioner.ListProvidersResponse, error) {

    providers, err := r.store.FindAll()
    return &versioner.ListProvidersResponse{Providers: providers}, err

}

the compiler complains:

cannot use providers (type *[]versioner.ProviderResponse) as type []*versioner.ProviderResponse in field value

The ListProviderResponse is defined as follows:

type ProviderResponse struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields

    Name        string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
    Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
}

type ListProvidersResponse struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields

    Providers []*ProviderResponse `protobuf:"bytes,1,rep,name=providers,proto3" json:"providers,omitempty"`
}

and the r.store.FindAll():

type ProviderStore interface {
    FindAll() (*[]versioner.ProviderResponse, error)
    ...
}

What am I doing wrong?

softshipper
  • 32,463
  • 51
  • 192
  • 400

1 Answers1

1

Your store method returns a *[]versioner.ProviderResponse which is a pointer to a slice of versioner.ProviderResponse values.

You are attempting to assign providers, which has the above type, to a struct field declared as []*ProviderResponse which is a slice of pointers to versioner.ProviderResponse.

The types don't match, and the compiler is telling you that.

If this is just a typo, then it's an easy fix. If you don't have full control over some of this source code (or if the types are declared exactly as they have to), you can simply remap the store result to the struct field:

providers, err := r.store.FindAll()
if err != nil {
   // 
}
if providers == nil {
   // must check this, since you want to dereference
}

res := make([]*versioner.ProviderResponse, len(*providers))
for i, v := range *providers {
    v2 := v
    res[i] = &v2 // don't address the loop variable
}

return &versioner.ListProvidersResponse{
    Providers: res, // now assigning the correct type
}, err

Why you don't want to address the loop variable (tl;dr because it's reused)

blackgreen
  • 34,072
  • 23
  • 111
  • 129