-4

Edit: For everyone suggesting using a pointer receiver in the function: By changing the method to have a pointer receiver, the structure no longer implements the interface. I have a image at the bottom of my question showing that.

I am trying to make a setter that will mutate the pointer of a variable in a struct with a method implemented from an interface.

package main

import "fmt"

func main() {
    i := 1
    b := BlahImpl {id:&i}

    fmt.Println(b.ID())
    j := 2
    b.SetID(&j)

    fmt.Println(b.ID())
}

type BlahInterface interface {
    SetID(*int)
    ID() int
}

type BlahImpl struct {
    id *int
}

func (b BlahImpl) SetID(i *int) {
    b.id = i
}

func (b BlahImpl) ID() int {
    return *b.id
}

The current output is:

1
1

But I would like:

1
2

When I use pointer receiver I get this error because the struct is no longer implementing the interface. error

k3v
  • 119
  • 1
  • 11

1 Answers1

0

Well, to be honest I do not quite get why it works this way, but this works as you want it to:

package main

import "fmt"

func main() {
    i := 1
    b := BlahImpl{id: &i}

    fmt.Println(b.ID())
    j := 2
    b.SetID(&j)

    fmt.Println(b.ID())
}

type BlahInterface interface {
    SetID(*int)
    ID() int
}

type BlahImpl struct {
    id *int
}

func (b *BlahImpl) SetID(i *int) {
    b.id = i
}

func (b *BlahImpl) ID() int {
    return *b.id
}

The difference is how the structure's methods are defined. I've added * before the name so reference on the structure is passed into the method. It looks like without * the method gets copy of the struct so the modification does not work.

Alex Netkachov
  • 13,172
  • 6
  • 53
  • 85
  • I think by adding the * to the methods you are no longer implementing the interface. – k3v Jul 17 '15 at 21:36
  • 3
    The usual suspect: You cannot modify a value from within non-pointer-receiver methods. The OPs problem has nothing to do with "pointer of a variable". – Volker Jul 17 '15 at 21:37
  • It does have to do with the pointer of a variable because I can change the value of an *int by mutating the deference but I can't do that here because I need to change the reference itself. – k3v Jul 17 '15 at 21:50
  • > I think by adding the * to the methods you are no longer implementing the interface. < In fact, it does, but a bit differently - `b := BlahInterface(&BlahImpl{id: &i})` works well. – Alex Netkachov Jul 17 '15 at 22:08
  • > It does have to do with the pointer of a variable because I can change the value of an *int by mutating the deference but I can't do that here because I need to change the reference itself. < Actually, you cannot change any other struct field as well. Just add normal int and try to change it: http://play.golang.org/p/7L37pHJlbJ – Alex Netkachov Jul 17 '15 at 22:12
  • I'm getting this error when I add an * to the method receiver. http://imgur.com/E0Gg46f – k3v Jul 17 '15 at 23:44
  • I added an image to the OP with this issue. – k3v Jul 17 '15 at 23:51