Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save arehmandev/25871acbbecaa744d077eff72a20f131 to your computer and use it in GitHub Desktop.

Select an option

Save arehmandev/25871acbbecaa744d077eff72a20f131 to your computer and use it in GitHub Desktop.

Revisions

  1. @josephspurrier josephspurrier revised this gist Jan 1, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion structs_interface.go
    Original file line number Diff line number Diff line change
    @@ -151,7 +151,7 @@ func example3() {

    // *************************************************************************
    // This is where it gets interesting
    // Can also create an instance of either interface by assing in the Dog
    // Can also create an instance of either interface by passing in the Dog
    a := Animal(d)
    l := LandAnimal(d)

  2. @josephspurrier josephspurrier created this gist Jan 1, 2015.
    200 changes: 200 additions & 0 deletions structs_interface.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,200 @@
    // Also available at: https://play.golang.org/p/yTTpB5gB6C

    package main

    import (
    "fmt"
    )

    // *****************************************************************************
    // Example 1 - Struct vs Struct with Embedded Type
    // *****************************************************************************

    // Struct types contain fields. You can create instances of struct types.
    // Struct with 2 fields
    type Person struct {
    Name string // field
    Age int // field
    }

    // Struct with 2 fields
    type Boy1 struct {
    Person Person // field
    FavoriteToy string // field
    }

    // Struct with 2 fields (1 is an embeded type)
    type Boy2 struct {
    Person // anonymous field (embedded type)
    FavoriteToy string // field
    }

    // Struct with 3 fields (1 is an embeded type)
    // Since Boy3 has an Age field, Person.Age is not longer a promoted field
    type Boy3 struct {
    Person // anonymous field (embedded type)
    FavoriteToy string // field
    Age int // field (named the same as Person.Age)
    }

    func example1() {
    // Create an instance of the Boy
    b1 := Boy1{Person{"Jon", 15}, "Corvette"}
    b2 := Boy2{Person{"Jon", 15}, "Corvette"}
    b3 := Boy3{Person{"Jon", 15}, "Corvette", 18}

    // Can ONLY access Age field 1 way
    fmt.Println(b1.Person.Age)
    // Output: 15

    // Can access Age field 2 ways (b2.Age is called a promoted field)
    fmt.Println(b2.Person.Age, b2.Age)
    // Output: 15 15

    // Can access Age field 2 ways (b3.Age is NOT a promoted field)
    fmt.Println(b3.Person.Age, b3.Age)
    // Output: 15 18

    // Can access FavoriteToy field 1 way in both
    fmt.Println(b1.FavoriteToy)
    // Output: Corvette
    fmt.Println(b2.FavoriteToy)
    // Output: Corvette
    }

    // *****************************************************************************
    // Example 2 - Named Type Method Sets
    // *****************************************************************************

    // Create named Person type called Man
    type Man Person

    // Create named Person type called Woman
    type Woman Person

    // Create method increases the age
    // Can ONLY be used with Man type
    func (m *Man) IncreaseAge() {
    m.Age++
    }

    // Create method for only Person that decreases the age
    // Can ONLY be used with Person type (not with Man or Woman)
    // *** Can be used with Boy1 or Boy2
    func (p *Person) DecreaseAge() {
    p.Age--
    }

    func example2() {
    // Create an instance of a Man
    r := Man{"Steve", 35}

    // This method can ONLY be called on a Man. It cannot be called on a Woman
    // or a Person.
    r.IncreaseAge()

    // Since Man is NOT a Person, this will throw a compile-time error
    //r.DecreaseAge()

    // Print 2 fields
    fmt.Println(r.Name, r.Age)
    // Output: Steve 36
    }

    // *****************************************************************************
    // Example 3 - Usage of Interfaces
    // *****************************************************************************

    // Interface with a method set
    type Animal interface {
    Speak() string
    }

    // Named interface is 100% compatible with Animal (not useful though, just good
    // for aliasing third party interfaces)
    type LandAnimal Animal

    // Empty struct
    type Dog struct {
    }

    // Empty struct
    type Cat struct {
    }

    // Create method for the Dog
    func (d Dog) Speak() string {
    return "Woof!"
    }

    // Receives any type that satisfies the Animal interface
    func LeaveAtAnimalShelter(a Animal) {
    fmt.Printf("%T is now at the animal shelter.\n", a)
    }

    // This is invalid because a method cannot receive an interface
    /*func (a Animal) Leave() {
    fmt.Printf("%T is now at the animal shelter.\n", a)
    }*/

    func example3() {
    // Create an instance of a Dog
    d := Dog{}

    // Call the method
    fmt.Println(d.Speak())
    // Output: Woof!

    // Call the function and pass the variable
    LeaveAtAnimalShelter(d)
    // Output: main.Dog is now at the animal shelter.

    // *************************************************************************
    // This is where it gets interesting
    // Can also create an instance of either interface by assing in the Dog
    a := Animal(d)
    l := LandAnimal(d)

    // Can even pass in an interface created from an interface that was passed
    // in the Dog
    p := LandAnimal(a)

    // Can call the method
    fmt.Println(p.Speak())
    // Output: Woof!

    // Can pass any of the instances that are compatible
    LeaveAtAnimalShelter(a)
    // Output: main.Dog is now at the animal shelter.
    LeaveAtAnimalShelter(l)
    // Output: main.Dog is now at the animal shelter.
    LeaveAtAnimalShelter(d)
    // Output: main.Dog is now at the animal shelter.
    LeaveAtAnimalShelter(p)
    // Output: main.Dog is now at the animal shelter.

    /*
    // Create an instance of a Cat
    c := Cat{}
    // This will throw a compile-time error because the Cat does NOT satisfy
    // the requirements to be an Animal.
    LeaveAtAnimalShelter(c)
    // Simple: In order for the Cat to be an Animal, it must have a Speak()
    // method.
    // Explanation: In order for the Cat to implement the Animal interface,
    // it must be associated, at a minimum, with the same method set as the
    // interface.
    */
    }

    // *****************************************************************************
    // Main
    // *****************************************************************************

    func main() {
    example1()
    example2()
    example3()
    }