Pointer method accepts a value reciver

I made a method to accept only pointers but why i am still able to call it by value reciver?

type User struct {
Name string
Email string
}

 func (u *User) Notify() {
fmt.Println(u.Name)
}

func main() {
     // works fine despite it is a value
bill := User{"Bill", "bill@email.com"}
bill.Notify()


jill := &User{"Jill", "jill@email.com"}
jill.Notify()
}

but when i add an interface

package main


 func (u *User) Notify() error {
log.Printf("User: Sending User Email To %s<%s>\n",
	u.Name,
	u.Email)

return nil
}

type Notifier interface {
Notify() error
}

func SendNotification(notify Notifier) error {
return notify.Notify()
}

 func main() {
user := User{
	Name:  "janet jones",
	Email: "janet@email.com",
}

SendNotification(user)
}

it starts to throw an error like i accept only pointer WHHHHYYY???

https://www.reddit.com/r/golang/comments/8fjpjh/why_mutating_a_value_receiver_accepted_by_a/ discusses the first part of this a bit.

Relevant parts:

If a method takes a pointer receiver then value.Method() is syntactical sugar for (&value).Method()

Vice-versa, if a method takes a value receiver, then pointer.Method() is a syntactic sugar for (*pointer).Method()

In other words you can just write thing.Method() and it almost always works either way.

As to why this sugar doesn’t work for interfaces - I don’t know for sure. You would likely need to ask whoever made that decision when designing the language, but my guess is that it is to avoid confusion.

First, it isn’t clear if SendNotification(user) should pass a copy of user and then call the pointer method on that copy, or if it should pass a pointer instead of what you actually typed. For the former it would seem weird that your “pointer methods” aren’t actually mutating the user you passed into SendNotification and this could confuse people. For the latter the compiler would then be modifying your code to instead pass &user into the SendNotification function which again is very unclear and confusing.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.