Implementation
Interfaces are types that just declare behavior.
When a userdefined type implements the set of methods declared by an interface type, values of the user-defined type can be assigned to values of the interface type.
what interface type values look like & how user-defined type values are stored inside them
Interface values are two-word data structures. (iTable, pointer to the stored value)
A simple view of an interface value after concrete type value assignment
A simple view of an interface value after concrete type pointer assignment
Method sets
Method sets define the rules around interface compliance.
Method sets define the set of methods that are associated with values or pointers of a given type.
The type of receiver used will determine whether a method is associated with a value, pointer, or both.
Method sets as described by the specification
Values | Methods Receivers |
---|---|
T | (t T) |
*T | (t T) and (t *T) |
Why the restriction?
- The answer comes from the fact that it’s not always possible to get the address of a value.
(as contrast, is it always possible to get the value of an address? )
Left value and Right value?
Lvalue: The requirement that the operand on the left side of the assignment operator is modifiable, usually a variable.
Rvalue: Pulls or fetches the value stored in a variable or constant.
// duration is a type with a base type of int.
type duration int
// format pretty-prints the duration value.
func (d *duration) pretty() string {
return fmt.Sprintf("Duration: %d", *d)
}
func main() {
duration(42).pretty()
//cannot call pointer method on duration(42)
//cannot take the address of duration(42)
}
Polymorphism
type notifier interface {
notify()
}
type user struct {
name string; email string
}
func (u *user) notify() {
fmt.Printf("Sending user email to %s<%s>\n",
u.name, u.email)
}
type admin struct {
name string; email string
}
func (a *admin) notify() {
fmt.Printf("Sending admin email to %s<%s>\n",
a.name, a.email)
}
func main() {
bill := user{"Bill", "bill@email.com"}
sendNotification(&bill)
lisa := admin{"Lisa", "lisa@email.com"}
sendNotification(&lisa)
}
// sendNotification accepts values that implement the notifier
// interface and sends notifications.
func sendNotification(n notifier) {
n.notify()
}