Ícone do site Aprenda Golang

A diferença entre ponteiro e valor nos métodos

Quando escrevemos métodos em Go, uma das decisões importantes é se devemos passar a struct por valor ou por ponteiro. A escolha pode impactar a performance, o comportamento do nosso código e a alocação de memória. Neste post, vamos explorar essa diferença com um exemplo prático e entender em quais situações cada abordagem é mais adequada.

Vamos começar com uma pequena struct e dois métodos: um onde a struct é passada por valor e outro por ponteiro.

package main

import (
    "fmt"
)

type Person struct {
    Name string
    Age  int
}

// Método com struct passada por valor
func (p Person) CelebrateBirthdayValue() {
    p.Age++
}

// Método com struct passada por ponteiro
func (p *Person) CelebrateBirthdayPointer() {
    p.Age++
}

func main() {
    person := Person{Name: "Alice", Age: 30}

    // Passando por valor
    person.CelebrateBirthdayValue()
    fmt.Println("Após CelebrateBirthdayValue:", person.Age) // Saída: 30

    // Passando por ponteiro
    person.CelebrateBirthdayPointer()
    fmt.Println("Após CelebrateBirthdayPointer:", person.Age) // Saída: 31
}

Diferença entre valor e ponteiro

Quando passamos uma struct por valor para um método, o Go cria uma cópia da struct. Qualquer alteração feita na struct dentro do método não afetará a struct original, pois estamos manipulando uma cópia independente.

Por outro lado, quando passamos uma struct por ponteiro, estamos passando o endereço de memória da struct original. Isso significa que qualquer alteração feita na struct dentro do método afetará diretamente a struct original, pois estamos manipulando a mesma instância.

Em resumo:

Heap

Quando uma struct é passada por valor, a cópia criada é alocada na stack, o que geralmente é rápido e eficiente. No entanto, se a struct for grande, essa cópia pode consumir muita memória da stack.

Quando uma struct é passada por ponteiro, o ponteiro em si é alocado na stack, mas a struct original pode estar alocada na heap, especialmente se foi criada usando new ou make, ou se foi capturada por uma função anônima. A utilização da heap é mais custosa em termos de tempo de alocação e coleta de lixo, mas permite a manipulação eficiente de grandes quantidades de dados sem copiar toda a struct.

Quando utilizar cada abordagem

Por valor

Utilizar structs por valor é útil quando:

Exemplo:

func (p Person) GetName() string {
    return p.Name
}

Neste caso, GetName apenas lê o campo Name e retorna uma string, sem modificar o estado da struct.

Por ponteiro

Utilizar structs por ponteiro é benéfico quando:

Exemplo:

func (p *Person) UpdateName(newName string) {
    p.Name = newName
}

Aqui, UpdateName altera diretamente o campo Name da struct original, o que é mais eficiente do que criar uma cópia.

Conclusão

Decidir entre passar uma struct por valor ou por ponteiro ao escrever métodos em Go é uma escolha importante que pode impactar a performance, o comportamento do seu código e a alocação de memória.

Passar por valor é útil para garantir a imutabilidade da struct dentro do método, enquanto passar por ponteiro é essencial para modificar a struct original e otimizar a performance ao lidar com structs maiores.


Faça parte da comunidade!

Receba os melhores conteúdos sobre Go, Kubernetes, arquitetura de software, Cloud e esteja sempre atualizado com as tendências e práticas do mercado.

Livros Recomendados

Abaixo listei alguns dos melhores livros que já li sobre GO.

Sair da versão mobile