Last active
December 16, 2016 23:34
-
-
Save lucasrpb/e3048a36726da3616974670311c47690 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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