0Pricing
Go Academy · Aula

Receptores de ponteiro em métodos

Altere o estado de uma struct por meio de receptores de ponteiro

Receptores de ponteiro em métodos é uma aula grátis de Go Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Go Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Go Academy inclui 4 aulas no total.

Recapitulação: Receptor de Valor versus Ponteiro

Um receptor de valor opera sobre uma cópia da estrutura. Um receptor de ponteiro opera sobre o original. Use receptores de ponteiro sempre que um método precisar modificar o estado.

Mutação com Receptor de Ponteiro

Somente um receptor de ponteiro pode alterar a estrutura:

package main
import "fmt"

type Stack struct{ items []int }

func (s *Stack) Push(v int) { s.items = append(s.items, v) }
func (s *Stack) Pop() int {
    n := len(s.items) - 1
    v := s.items[n]
    s.items = s.items[:n]
    return v
}

func main() {
    var st Stack
    st.Push(1); st.Push(2)
    fmt.Println(st.Pop()) // 2
}

Regra de Consistência

Se algum método de um tipo precisar de um receptor de ponteiro, todos os métodos deverão usar receptores de ponteiro. Misturá-los causa problemas para satisfazer interfaces:

package main
import "fmt"

type Counter struct{ n int }

func (c *Counter) Inc()   { c.n++ }   // pointer
func (c *Counter) Val() int { return c.n } // pointer too

func main() {
    c := &Counter{}
    c.Inc(); c.Inc()
    fmt.Println(c.Val()) // 2
}

Satisfação de Interfaces

Um método com receptor de ponteiro está apenas no conjunto de métodos de *T, não de T. Isso afeta a satisfação de interfaces:

package main
import "fmt"

type Writer interface{ Write([]byte) }

type File struct{ name string }
func (f *File) Write(b []byte) { fmt.Println(string(b)) }

func main() {
    var w Writer = &File{"out.txt"} // OK
    // var w Writer = File{} — compile error
    w.Write([]byte("hello"))
}

Obtenção Automática do Endereço

Go obtém automaticamente o endereço ao chamar um método com receptor de ponteiro sobre um valor endereçável:

package main
import "fmt"

type Box struct{ V int }
func (b *Box) Double() { b.V *= 2 }

func main() {
    b := Box{5}
    b.Double()          // Go does (&b).Double()
    fmt.Println(b.V)    // 10
}

Valores Não Endereçáveis

Não é possível chamar métodos com receptor de ponteiro sobre valores não endereçáveis (elementos de mapas e valores retornados por funções que não foram atribuídos a variáveis):

package main

type T struct{ V int }
func (t *T) Set(v int) { t.V = v }

func getT() T { return T{} }

func main() {
    var t T
    t.Set(1)       // OK — t is addressable
    // getT().Set(1) — ERROR: cannot take address of getT()
    _ = t
}

Receptores para Estruturas Grandes

Use sempre receptores de ponteiro para estruturas grandes, a fim de evitar cópias dispendiosas em cada chamada de método:

package main

type Image struct{ pixels [1024][1024]uint8 }

// Value receiver copies 1MB per call!
func (img Image) Bad() uint8 { return img.pixels[0][0] }

// Pointer receiver — zero copy
func (img *Image) Good() uint8 { return img.pixels[0][0] }

func main() { _ = Image{} }

Receptores de Ponteiro Nil

Métodos com receptores de ponteiro podem tratar nil de maneira adequada:

package main
import "fmt"

type List struct{ head *node }
type node struct{ val int; next *node }

func (l *List) Len() int {
    if l == nil { return 0 }
    count := 0
    for n := l.head; n != nil; n = n.next { count++ }
    return count
}

func main() {
    var l *List
    fmt.Println(l.Len()) // 0
}

Incorporação e Receptores de Ponteiro

Ao incorporar um tipo com receptores de ponteiro, a estrutura externa também deverá ser usada como ponteiro para obter os métodos promovidos:

package main
import "fmt"

type Base struct{ V int }
func (b *Base) Set(v int) { b.V = v }

type Derived struct{ Base }

func main() {
    d := &Derived{}
    d.Set(42)           // promoted pointer-receiver method
    fmt.Println(d.V)    // 42
}

Cópia de Mutexes

Nunca copie uma estrutura que contenha um sync.Mutex — use sempre um receptor de ponteiro ou passe por ponteiro. Copiar um mutex bloqueado resulta em um deadlock:

package main
import "sync"

type Safe struct {
    mu sync.Mutex
    v  int
}

// Correct: pointer receiver
func (s *Safe) Set(v int) {
    s.mu.Lock()
    defer s.mu.Unlock()
    s.v = v
}

func main() { _ = Safe{} }

go vet Detecta Erros

Execute go vet ./... para detectar erros comuns relacionados a receptores de ponteiro, como cópias de mutexes e bloqueios. Ele faz parte dos fluxos de go build e das verificações de CI.

Verificação Rápida

Um método com receptor de ponteiro pertence ao conjunto de métodos de quais tipos?

Recapitulação

Principais conclusões:

  • Receptores de ponteiro fazem mutações; receptores de valor não
  • Mantenha todos os métodos de um tipo usando a mesma espécie de receptor
  • Somente *T satisfaz interfaces que exigem métodos com receptores de ponteiro
  • Nunca copie estruturas com mutexes — use receptores de ponteiro

Proposta de Prática

Implemente uma estrutura Queue com os métodos Enqueue(int), Dequeue() (int, bool) e Len() int, todos com receptores de ponteiro e respaldados por uma fatia []int.

Perguntas Frequentes

A aula “Receptores de ponteiro em métodos” é grátis?

Sim — o texto completo de “Receptores de ponteiro em métodos” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Go Academy, atualize para CoddyKit PRO. O curso de Go Academy inclui 4 aulas no total.

O que vou aprender em “Receptores de ponteiro em métodos”?

Altere o estado de uma struct por meio de receptores de ponteiro Você pratica Go Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Go Academy?

Nenhuma experiência prévia é necessária. Go Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Receptores de ponteiro em métodos”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Go Academy?

Sim. Cada aula de Go Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. O que são ponteiros?
  2. Ponteiros e funções
  3. Receptores de ponteiro em métodos
  4. new() e quando usar ponteiros
← Voltar para Go Academy