简体   繁体   中英

Assign struct pointer to interface pointer

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 type T (" x is assignable to T ") if one of the following conditions applies:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM