In golang, I'm having the following compile error:
cannot use m (type MessageImpl) as type Message in assignment:
MessageImpl does not implement Message (missing FirstLine method)
Using the following code:
type Message interface {
FirstLine() string
/* some other method declarations*/
}
type MessageImpl struct {
headers []Header
/* some other fields */
}
type Request struct {
MessageImpl
/* some other fields */
}
type Response struct {
MessageImpl
/* some other fields */
}
func (r Request) FirstLine() string {
var requestLine bytes.Buffer
requestLine.WriteString("...")
// Some more instructions
return requestLine.String()
}
func (m MessageImpl) RenderMessage() string {
var message bytes.Buffer
var msg Message = m // <=== This is the line the compiler moans about
message.WriteString(msg.FirstLine())
// Some more instructions
return message.String()
}
Coming from java language, I'll try to express my intention: Having some interface Message
defining some methods implemented by an abstract class MessageImpl
. Two real classes Request
and Response
should inherit from MessageImpl
(and implement the interface Message
). Both of these define and implement some more internal methods.
How is this done best?
An interface in go is a set of methods, but interfaces are also types. So the go convention is to suffix -er for any interface to indicate whether or not other types compose methods from it.
You need to define an implementation for the type Messege
to receive the FirstLine()
method. It satisfies the Messeger
interface as a result.
Edit: I misunderstood what you were doing with bytes.Buffer
, so the answer is actually a lot simpler.
Edit2: I had to think about this one a bit but it seems you want RenderMessage()
to be a function instead of a method. RenderMessage
has a parameter of type Messeger
which can (so far) either be of type Request
, Response
, or Message
.
You can't define a method receiver for RenderMessage
if the Messager
you're passing can be of variable type, unless you want to have a type switch within RenderMessage
, which somewhat defeats the purpose of using an interface to begin with.
package main
import (
"bytes"
"fmt"
)
type Messager interface {
FirstLine() string
/* some other method declarations*/
}
type Header struct {
Data string
}
type Message struct {
headers []Header
/* some other fields */
}
type Request struct {
/* some fields */
Message
}
type Response struct {
/* some fields */
Message
}
func (r Request) FirstLine() string {
var requestLine bytes.Buffer
requestLine.WriteString("...")
// Some more instructions
return requestLine.String()
}
func (r Response) FirstLine() string {
var requestLine bytes.Buffer
requestLine.WriteString("!!!")
// Some more instructions
return requestLine.String()
}
func (m Message) FirstLine() string {
// whatever this would be
return "???"
}
func RenderMessage(m Messager) string {
var b bytes.Buffer
var msg Messager = m // <=== This is the line the compiler moans about
b.Write([]byte("some text"))
b.WriteString(msg.FirstLine())
// Some more instructions
return b.String()
}
func main() {
header := Request{}
fmt.Println(RenderMessage(header))
resp := Response{}
fmt.Println(RenderMessage(resp))
foo := Message{}
fmt.Println(RenderMessage(foo))
}
Output:
some text...
some text!!!
some text???
I added this since it wasn't defined in your question:
type Header struct {
Data string
}
I also added this line to illustrate the example:
b.Write([]byte("some text"))