Skip to content

Instantly share code, notes, and snippets.

@damienstanton
Last active August 29, 2015 14:17
Show Gist options
  • Select an option

  • Save damienstanton/517462a94c999063d71d to your computer and use it in GitHub Desktop.

Select an option

Save damienstanton/517462a94c999063d71d to your computer and use it in GitHub Desktop.
/*
------------------ Object Orientation in Go --------------------------------
Polymorphism
Method Implementation (using value or pointer receivers)
Interfaces
Class Inheritance (Type Embedding)
*/
package main
import "fmt"
// Go type of interface, a named collection of method signatures
type notifier interface {
notify()
}
// Go type of struct, analogous to classes in other languages
type user struct {
name string
email string
}
// Admin type has an "inner type" of user
// Thus admin *extends* user
type admin struct {
user
level string
}
// To implement an interface, simply call a pointer receiver method with the appropriate method signature.
// One might call this "duck method typing"
func (u *user) notify() {
fmt.Printf("User: Sending email to %s<%s>\n", u.name, u.email)
}
/*
------ When to use value vs. pointer receivers -------
| Does the method need to modify the receiver?
\__ the receiver MUST be a pointer
| Does the method need to be passed a copy of the value?
\__ the receiver MUST be a value
| Consistency and efficiency
\__ if some of the methods of the type must have pointer receivers, the rest should too.
\__ if the receiver is large, it is much cheaper to use a pointer receiver.
*/
// changeEmail implements a method with a pointer receiver
func (u *user) changeEmail(email string) {
u.email = email
}
// Implement an interface using a different pointer
func (a *admin) notify() {
fmt.Printf("User: Sending email to administrator %s<%s>\n", a.name, a.email)
}
// sendNotification accepts values that implement the notifier interface
func sendNotification(n notifier) {
n.notify()
}
func main() {
// Values of type user can be used to call methods declared with a value receiver
u := &user{"Brennan", "[email protected]"}
// Pass a pointer of type user to the sender function
sendNotification(u)
// In one statement, create a value of type admin, initializing both the admin's fields
// as well as the inner type(user)'s fields.
ad := admin{
user: user{
name: "Damien Stanton",
email: "[email protected]",
},
level: "sudo",
}
// because only the inner type actually implements the interface, the inner
// type's implementation of the interface is promoted to the outer type...
// ...thus it can be called via the implementation
sendNotification(&ad)
// ...one can also access a method by passing the pointer of an outer type
//to a direct call to that method via the inner type
ad.user.notify()
// ...or the outer type
ad.notify()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment