Ícone do site Tiago Temporin

Diferenças entre structs e classes

No Go, uma struct é um tipo de dado fundamental que agrupa “variáveis” (atributos) sob um único nome, similar a como uma classe agrupa propriedades e métodos em linguagens orientadas a objetos como Java ou C#. No entanto, existem diferenças significativas tanto na sintaxe quanto nos conceitos e funcionalidades oferecidos por structs em Go quando comparada com classes em outras linguagens.

Estrutura e Sintaxe

Struct

Em Go, uma struct é definida usando a palavra-chave struct. A definição de uma struct envolve apenas a declaração de atributos.

type Pessoa struct {
	Nome  string
	Idade int
}

Classe em Java

Uma classe normalmente não é composta somente por propriedades, mas também métodos, visibilidade (public, private, etc.), além de envolver conceitos como herança e polimorfismo.

public class Pessoa {
	
	private String nome;
	private int idade;
	
	public Pessoa(String nome, int idade) {
    this.nome = nome;
    this.idade = idade;
	}

	public String getNome() {
    return nome;
	}

	public void setNome(String nome) {
    this.nome = nome;
	}

	public int getIdade() {
    return idade;
	}

	public void setIdade(int idade) {
    this.idade = idade;
	}
}

Visibilidade

No Go, a visibilidade é controlada pela capitalização do nome dos atributos ou funções. Se uma propriedade ou método começa com uma letra maiúscula, ele é exportado (public) e pode ser acessado de outros pacotes. Se começa com uma letra minúscula, ele é não-exportado (private) e só pode ser acessado dentro do mesmo pacote.

type Pessoa struct {
	Nome  string  // Público (exportado)
	idade int     // Privado (não exportado)
}

Já em linguagem orientadas a objetos, além de existir uma keyword para definir as visibilidades, o mais comum é haver 3 níveis de visibilidade (public, private e protected).

Métodos

No Go, métodos podem ser definidos para qualquer tipo, inclusive para structs. No entanto, Go não agrupa métodos dentro da definição da struct, como se faz em linguagens orientadas a objetos. Em vez disso, métodos são definidos separadamente e associados a um tipo.

func (p *Pessoa) Saudacao() string {
	return "Olá, meu nome é " + p.Nome
}

Na maioria das linguagens orientadas a objetos (p. ex., Java), os métodos são definidos dentro da classe.

public class Pessoa {
	// atributos e métodos
	public String saudacao() {
		return "Olá, meu nome é " + this.nome;
	}
}

Herança

Go não suporta herança tradicional como em linguagens orientadas a objetos. Em vez disso, Go utiliza a composição para reutilização de código. Uma struct pode incluir outra struct, o que permite o acesso aos atributos e métodos da struct “inclusa”.

type Endereco struct {
	Rua   string
	Numero int
}

type Pessoa struct {
	Nome     string
	Idade    int
	Endereco // Composição
}

Em linguagens orientadas a objetos, a herança é uma característica central.

public class Pessoa extends Mamifero {
// atributos e métodos
}

Interfaces

Go usa interfaces para definir comportamentos que tipos (incluindo structs) podem implementar. As interfaces em Go são satisfeitas implicitamente, ou seja, um tipo implementa uma interface simplesmente ao ter os métodos da interface.

type Saudador interface {
	Saudacao() string
}

func (p Pessoa) Saudacao() string {
	return "Olá, meu nome é " + p.Nome
}

Em linguagens orientadas a objetos, as interfaces (ou tipos similares, como “abstract classes” em Java) são declaradas explicitamente e a classe deve mencionar que implementa a interface.

public interface Saudador {
	String saudacao();
}

public class Pessoa implements Saudador {
	public String saudacao() {
		return "Olá, meu nome é " + this.nome;
	}
}

Runtime

Além das diferenças já mencionadas com relação a sintaxe, existem diferenças significativas em como o runtime do Go lida com structs em comparação com como, por exemplo, a JVM (Java Virtual Machine) lida com classes.

Gerenciamento de Memória

Golang:

A memória é gerenciada pelo garbage collector (GC), de uma maneira otimizada para se ter maior performance e menor latência. Go usa uma estratégia de alocação de memória que pode ser dividida em duas partes principais: stack allocation e heap allocation.

func createPessoa() *Pessoa {
	p := Pessoa{Nome: "João", Idade: 30}
	return &p // Pode ser gerenciada pelo heap
}

Java (JVM):

Na JVM, todas as instâncias de objetos são alocadas no heap. Variáveis locais que são primitivas (e.g., int, float) são armazenadas no stack, mas instâncias de classes são sempre heap-allocated.

public Pessoa createPessoa() {
	Pessoa p = new Pessoa("João", 30); // Sempre será alocado no heap
	return p;
}

Desempenho e Otimização

Golang:

func process(p Pessoa) {
// Struct é passada por valor
}

func processPointer(p *Pessoa) {
// Struct é passada por referência (ponteiro)
}

Java (JVM):

public void process(Pessoa p) {
// Objeto é passado por referência
}

Modelo de Concorrência

Golang:

Java (JVM):

Conclusão

Structs em Go e classes em linguagens orientadas a objetos podem parecer semelhantes na superfície, porém, suas funcionalidades, conceitos e práticas divergem significativamente. Go favorece a composição sobre a herança, oferece um modelo simples de visibilidade de membros e utiliza interfaces com implementação implícita, contrastando com a abordagem mais complexa e rica em funcionalidades das classes em linguagens OOP tradicionais.

No quesito execução, o runtime do Go e a JVM lidam de forma bastante diferente com suas respectivas construções (structs e classes). O Go é otimizado para alocação de memória eficiente e concorrência leve utilizando goroutines, enquanto a JVM é conhecida por suas otimizações agressivas em tempo de execução e modelo de thread mais pesado.

Em resumo, essas diferenças refletem as filosofias dos projetos implementados em cada linguagem, o que acabará impactando como os desenvolvedores devem abordar o desempenho e a escalabilidade em suas aplicações.

Até a próxima!


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.

* indicates required