I'm trying to refactor some golang source code, and I would like to use interfaces but I find huge difficulties (bear with me, I'm a hard-core C/C++ orphan)
I extracted a small sample exhibiting the error I get
package main
import "fmt"
type LogProcessor interface {
Init() int
}
type MyProcessor struct {
a int
}
func (m MyProcessor) Init() int {
return m.a
}
func main() {
t := &(MyProcessor{2})
var p *LogProcessor = &(MyProcessor{4}) //!!!fails!!!
fmt.Println((*t).Init(), (*p).Init())
}
Why is the second assignment failing?
Adding the code modified to demonstrate what I was trying to do. I thought interfaces where more similar to C++ classes. My fault. Still learning
package main
import "fmt"
type LogProcessor interface {
Init() int
}
type MyProcessor struct {
a int
}
func (m *MyProcessor) Init() int {
m.a++
return m.a
}
func main() {
t := &(MyProcessor{2})
m := MyProcessor{4}
var p LogProcessor = &m
fmt.Println(t.Init(), p.Init())
fmt.Println(t.a, m.a)
}
The expression MyProcessor{2}
is a composite literal . It is valid to take the address of a composite literal, and it will be of type *MyProcessor
.
So here:
t := &(MyProcessor{2})
Type of t
will be *MyProcessor
.
Your failing line:
var p *LogProcessor = &(MyProcessor{4}) //!!!fails!!!
The type of the expression on the right hand side is again *MyProcessor
. It's a pointer to a concrete type. The type of p
is *LogProcessor
, it's a pointer to another type. Assignability rules don't apply here, so the value is simply not assignable to the variable p
.
Note that there is an assignability rule:
A value
x
is assignable to a variable of typeT
("x
is assignable toT
") if one of the following conditions applies:
- ...
T
is an interface type andx
implementsT
.
In your example p
's type is not an interface type, but a pointer to interface. You rarely (if ever) need this in go.
Instead if you use "just" the interface type:
var p LogProcessor = &(MyProcessor{4}) // This works!
This works because the concrete type *MyProcessor
implements the interface type LogProcessor
. You also don't need the parenthesis, you may simply use &MyProcessor{4}
.
Then of course you can't dereference p
(as it's not a pointer), so you have to use p.Init()
.
it is failing because you are using a pointer to an interface, if you remove the pointer to LogProcessor for var p it works
package main
import "fmt"
type LogProcessor interface {
Init() int
}
type MyProcessor struct {
a int
}
func (m MyProcessor) Init() int {
return 2
}
func main() {
t := &(MyProcessor{2})
var p LogProcessor = MyProcessor{4} // works without a pointer to the interface type
fmt.Println((*t).Init(), (p).Init())
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.