-2

I'm getting the following error:

./main.go:31: cannot use telegramService (type messaging.TelegramService) as type mypackage.MessagingService in argument to mypackage.RegisterMessagingService:
    messaging.TelegramService does not implement mypackage.MessagingService (wrong type for HandleIncomingMessage method)
        have HandleIncomingMessage(telegram.Message) error
        want HandleIncomingMessage(mypackage.IncomingMessage) error

I have an interface that describes a messaging service like Telegram or WhatsApp, and an interface that describes an incoming message from one of those services:

// IncomingMessage is a message that comes in on a messaging service
type IncomingMessage interface {
    Send() error
}

// MessagingService is a service on which messages can be send (like Telegram or FB Messenger)
type MessagingService interface {
    Start()
    HandleIncomingMessage(IncomingMessage) error
    GetHTTPHandler() http.HandlerFunc
    GetCommands() []MessagingCommand
}

The first implementation of MessagingService is for Telegram. The issue is the HandleIncomingMessage function, which currently doesn't really do anything and just looks like this:

// HandleIncomingMessage will take an incoming message and repond to it
func (s TelegramService) HandleIncomingMessage(msg *telegram.Message) error {

    return nil
}

The issue is that this function accepts a telegram.Message, which the compiler says doesn't comply with the interface. The thing is, that telegram.Message is an implementation of IncomingMessage:

// Message is a Telegram message
type Message struct {
    // Added the line below at some point, but it didn't work without it either
    mypackage.IncomingMessage
    MessageID uint64 `json:"message_id"`
    FirstName string `json:"first_name"`
    Username  string `json:"username"`
    Date      uint64 `json:"date"`
    Text      string `json:"text"`
    Chat      Chat   `json:"chat"`
    From      User   `json:"from"`
}

// Send will take m and send it
func (m Message) Send() error {
    // Do stuff

    return nil
}

Initially IncomingMessage was an empty interface, which is where I first noticed the issue. I tried adding the function Send() which I was going to add anyway, as I thought maybe just giving it any struct wouldnt't work. However, I'm still getting this error.

I don't see any reason why telegram.Message doesn't implement the interface, it's pretty straight forward.

Can anyone explain why this doesn't work?

PS: My package isn't actually called mypackage, changed for clarity

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Roemer
  • 1,336
  • 1
  • 15
  • 39
  • 1
    The method signature is `HandleIncomingMessage(IncomingMessage) error`. You can't use a different signature, but why do you need to at all? – JimB Nov 28 '17 at 18:44
  • 1
    The compiler's complaint is valid. TelegramService is not able to handle *any* IncomingMessage, only some and thus does not satisfy the MessagingService interface. – Peter Nov 28 '17 at 18:48
  • @JimB Thanks sir. If I use IncomingMessage, can I just use it as if it were a telegram.Message? – Roemer Nov 28 '17 at 19:01
  • 1
    @RoemerBakker: I don't understand. If you want it to be an interface, then you use it through its interface methods. You can always assert it to a concrete type, but then why have the interface in the first place? – JimB Nov 28 '17 at 19:04
  • @JimB This function is specific to Telegram. However, I'll be implementing other messaging services along side logic to store incoming message in a database. In this case I want the IncomingMessage to be an interface so that I can write general stuff for the db storage. Though again, those incoming messages will have specific functionality as well – Roemer Nov 28 '17 at 19:07
  • Does it help if you make your methods have a pointer receiver? `func (s *TelegramService) Han..` and `func (m *Message) Send()`. – Graham King Nov 28 '17 at 19:36
  • What does actual error say? Could be related to this https://stackoverflow.com/questions/40823315/go-x-does-not-implement-y-method-has-a-pointer-receiver?noredirect=1&lq=1. As Graham mentions you might need to change just this `func (m *Message) Send() error {` – k1m190r Nov 28 '17 at 22:11

1 Answers1

0

HandleIncomingMessage must take an IncomingMessage argument since that's the way the interface is defined. You can't define an implementation of HandleIncomingMessage that takes some other type as the argument, even if that type implements IncomingMessage. You can define your function to take IncomingMessage and convert that to *telegram.Message using a type assertion:

func (s TelegramService) HandleIncomingMessage(im IncomingMessage) error {
    msg := im.(*telegram.Message)
    return nil
}

I'm assuming you actually want to be using a pointer to telegram.Message. If so, you need to change the definition of the Send method to take a pointer receiver.

Andy Schweig
  • 6,597
  • 2
  • 16
  • 22