如何在以下代码中实现接口?

I have the following code and I want to use interfaces:

Current code:

import (        
    "github.com/dorzheh/deployer/ui/dialog_ui"
    . "github.com/dorzheh/go-dialog"
)

// all methods in https://github.com/dorzheh/deployer/blob/master/ui/dialog_ui/dialog_ui.go#L28
type Pb struct {
    sleep time.Duration
    step  int
}

type DialogUi struct {
    *Dialog //The source is https://github.com/dorzheh/go-dialog/blob/master/dialog.go#L34
    Pb *Pb
}

I am trying to implement interfaces this way:

import (
    "testing"
    // . "github.com/dorzheh/go-dialog"
    //"github.com/dorzheh/deployer/ui/dialog_ui"
)


type PBifaceT interface {
    Step() int
}

type TestDialogUiT struct {
    Pb *PBifaceT
}

func TestUiValidateUser(t *testing.T) {
    x := dialog_ui.TestDialogUiT{}
    PbPb := ImplPBifaceT{}
    x.Pb = PbPb

    parentId := x.Pb.Step()
    t.Logf(fmt.Sprintf("%v", parentId))
}

I've made a playground. As you can see it runs in the following error:

prog.go:23: cannot use PbPb (type ImplPBifaceT) as type *PBifaceT in assignment:
    *PBifaceT is pointer to interface, not interface
prog.go:25: x.Pb.Step undefined (type *PBifaceT is pointer to interface, not interface)

I tried to convert them in this playground:

func NewD() *PBifaceT {
    // var err error
    var res =new(ImplPBifaceT)
    return (*PBifaceT)(res)
}

func main() {
    x := TestDialogUiT{}
    x.Pb = NewD()
    parentId := x.Pb.Step()
    fmt.Sprintf("%v", parentId)

}

The issue:

prog.go:23: cannot convert res (type *ImplPBifaceT) to type *PBifaceT
prog.go:30: x.Pb.Step undefined (type *PBifaceT is pointer to interface, not interface)

Do not use pointer to interface unless you are sure that's what you want, see Pb *PBifaceT inside TestDialogUiT. If you change it to just Pb PBifaceT your playground link just works.

An interface is already a pointer.

Are you sure you need your Pb field as a *PBifaceT.

If you keep it as a

type TestDialogUiT struct {
    Pb *PBifaceT
}

and you do

x := TestDialogUiT{}

PbPb := ImplPBifaceT{}
x.Pb = PBifaceT(PbPb)

parentId := x.Pb.Step()
fmt.Printf("%v", parentId)

It works properly..

Take a look at this playground and see if it can help.

I'd suggest you to take a look at this tutorial and this doc.

I'd suggest you also to read this SO answer which explains a bit of how you shouldn't want to use interface pointers.

Background: In Go you pass around a pointer to something because of two reasons:

1) You want because your struct is really large and you want to avoid copying

2) you need to because the calee wants to modify the original (this is typical for methods with a pointer receiver). Now an interface value is really tiny (just two words) so reason 1 to pass a pointer to an interface value does not apply.

Reason 2 does not apply in most cases as passing a pointer to an interface value will allow you to change the interface value itself, but most often you would like to modify the value stored inside the interface value. This value stored inside the interface value often is a pointer value which allows to change the value of a struct by calling methods on an interface value which wrapps a pointer to this struct. This sounds complicated but isn't: The novice Go programmer just doesn't use pointers to interfaces (as this won't do any good) and the experienced Go programmer doesn't use pointers to interfaces (as it won't do much good) unless he needs to modify an interface value, typically during reflection.

You can use Pb by link, you were just missing pointer reference while assigning.

package main

import (
    "fmt"
)

type PBifaceT interface {
    Step() int
}

type TestDialogUiT struct {
    Pb PBifaceT
}
type ImplPBifaceT struct {
}

func (m *ImplPBifaceT) Step() int {
    return 0
}

func main() {
    x := TestDialogUiT{}
    PbPb := &ImplPBifaceT{}
    x.Pb = PbPb

    parentId := x.Pb.Step()
    fmt.Printf("%v", parentId)
}

Please refer this playground link: https://play.golang.org/p/N7quQFpYU0 Changes were at line 12, 17, 23 & 27.