Skip to content

Instantly share code, notes, and snippets.

@lucasrpb
Last active December 16, 2016 23:34
Show Gist options
  • Save lucasrpb/e3048a36726da3616974670311c47690 to your computer and use it in GitHub Desktop.
Save lucasrpb/e3048a36726da3616974670311c47690 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
)
type Mutator interface {
Change()
AnotherChange()
}
type Address struct {
Street string
}
type Person struct {
Name string
Age int
Address1 Address
Address2 *Address
}
/**
* Esta função faz exatamente o que você está pensando! não altera a idade, pois é feita uma cópia do objeto pessoa no método
* receiver
*/
func (p Person) NothingChanges() {
// Só para provar para você que é uma cópia vou mostrar o endereço :P
fmt.Printf("[NothingChanges] pointer address: %p\n\n", &p)
p.Age = 28
/*
* Aqui está a armadilha! Cuidado! Mesmo sendo p uma cópia do original, Address2 é um PONTEIRO que teve
* seu endereço copiado! Portanto, se você alterar algo dentro deste método, tenha cuidado!
*/
p.Address2.Street = "Av. das Samambaias"
}
/**
* Esta função sim funciona! Ufa!
*/
func (p *Person) Change(){
fmt.Printf("[Change] pointer address: %p\n", p)
p.Age = 28
}
func (p Person) AnotherChange(){
p.Age = 30
}
func (p *Person) PresentYourself(){
fmt.Printf("%v %v %v %v \n\n", p.Name, p.Age, p.Address1, *p.Address2)
}
func GetMutator1(p interface{}) Mutator {
return p.(Mutator)
}
func main(){
p := Person{
Name: "Lucas",
Age: 27,
Address1: Address{
Street: "Av. Brasil",
},
Address2: &Address{
Street: "Av. Samba",
},
}
fmt.Printf("original pointer address: %p\n", &p)
p.NothingChanges()
p.PresentYourself()
/**
* Também é possível usar o casting desta maneira: m := interface{}(p)
* Neste caso o compilador irá reclamar com um erro como:
* panic: interface conversion: main.Person is not main.Mutator: missing method Change
* Experimente remover o & e compilar! Por que isso acontece?
* Isso acontece porque numa das implementações da interface em Person foi usado ponteiro no
* método receiver e na outra não! Mais dores de cabeça... Solução? SEMPRE FAÇA O CAST PARA INTERFACE
* USANDO &
* No caso de funções como o GetMutator() => m := GetMutator(&p), passe por referência usando &
* Try yourself :P
*/
m := interface{}(&p).(Mutator)
m.Change()
p.PresentYourself()
m.AnotherChange()
p.PresentYourself()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment