Trabalho Extra: Implementação em Go (Golang)

Data de Publicação

21/04/2026

Data de Modificação

21/04/2026

Este documento descreve o Trabalho Extra Opcional da disciplina: reimplementar o Sistema de Recomendação Colaborativo em Go (Golang).

NotaTrabalho Extra — +5 Pontos na Nota Final

Esta implementação é opcional e vale +5 pontos extras na nota final da disciplina.
Ela deve ser entregue individualmente e avaliada separadamente do TP1.


Por que fazer este trabalho?

1. Go é diferente de tudo que você já viu

Você já explorou três paradigmas no TP1:

  • Java — Orientado a Objetos, com herança, classes e exceções.
  • Prolog — Declarativo, baseado em fatos e regras lógicas.
  • Lisp/Racket — Funcional, com imutabilidade e funções de alta ordem.

Go não é nenhum dos três. É uma linguagem moderna, compilada e de tipagem estática que propositalmente rejeita a herança clássica e substitui threads por um modelo de concorrência próprio. Para uma disciplina de Conceitos de Linguagens de Programação, esse contraste é exatamente o ponto.

2. Concorrência como primitiva da linguagem

Esta é a principal razão para fazer este trabalho. As duas linguagens resolvem o problema de concorrência de formas filosoficamente opostas.

O modelo de Java: Threads do Sistema Operacional

Em Java, concorrência é feita com threads gerenciadas pelo SO. Cada thread tem uma pilha própria (~1 MB), e a comunicação entre elas é feita via memória compartilhada — o que exige mecanismos de proteção explícitos:

// Java — executar tarefas em paralelo
ExecutorService executor = Executors.newFixedThreadPool(4);

for (int candidatoId : candidatos) {
    final int cid = candidatoId;
    executor.submit(() -> {
        if (ehVizinho(uid, cid)) {
            synchronized (vizinhos) {   // ← proteção obrigatória
                vizinhos.add(cid);
            }
        }
    });
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES);

O problema deste modelo: estado compartilhado é perigoso. Esquecer um synchronized causa race conditions difíceis de reproduzir e depurar. Java oferece volatile, AtomicInteger, ConcurrentHashMap para mitigar isso — mas a complexidade cresce rapidamente.


O modelo de Go: Goroutines + Channels

Go adota uma filosofia diferente, resumida no seu slogan oficial:

“Do not communicate by sharing memory; instead, share memory by communicating.”

Em vez de threads que brigam por acesso a variáveis compartilhadas, Go usa goroutines (muito mais leves que threads — custos na casa de ~2 KB) que se comunicam passando mensagens por channels:

// Go — executar as mesmas tarefas em paralelo
ch := make(chan int, len(candidatos))  // ← channel tipado

for _, cid := range candidatos {
    go func(candidatoID int) {         // ← goroutine: palavra-chave "go"
        if ehVizinho(uid, candidatoID) {
            ch <- candidatoID          // ← enviar resultado pelo channel
        } else {
            ch <- -1
        }
    }(cid)
}

for range candidatos {
    if id := <-ch; id != -1 {          // ← receber do channel
        vizinhos = append(vizinhos, id)
    }
}

Não há synchronized, não há Lock, não há memória compartilhada. O channel é o ponto de sincronização.


Comparação direta

Aspecto Java (Threads) Go (Goroutines)
Custo por unidade ~1 MB (pilha do SO) ~2 KB (gerenciada pelo runtime)
Sincronização synchronized, Lock, volatile Channels (chan)
Comunicação Memória compartilhada Passagem de mensagens
Modelo teórico Monitor / Semáforos CSP (Communicating Sequential Processes)
Quantidade prática Centenas Milhões
ImportanteO que explorar no trabalho

A busca de vizinhos da Fase 3 é um caso ideal: para cada usuário candidato, você pode lançar uma goroutine independente que avalia a vizinhança e envia o resultado por um channel. Não há estado compartilhado — cada goroutine só lê os dados (imutáveis) e escreve no seu próprio resultado.

Compare isso com a versão Java que você já implementou: quantas linhas a mais foram necessárias para garantir thread-safety?

3. OO sem herança — é possível?

Go tem structs e interfaces, mas sem herança. Toda composição é feita de outra forma. Reimplementar o mesmo problema que você modelou em Java com classes e hierarquias, agora sem elas, é um exercício valioso de design de software.

4. O juiz online já está pronto

Go lê de stdin exatamente como Java. Os mesmos problemas do juiz online valem para Go. Não há problema novo para aprender — só a linguagem muda.


O que será avaliado

A entrega tem dois componentes:

1. Código funcional

  • Implementação das três fases (Consultas, Regras de Negócio, Recomendação Colaborativa).
  • Suporte aos três tipos de recomendação: RESTRITO, TOLERANTE e ESPECIALIDADE.
  • Uso obrigatório de goroutines na busca de vizinhos (Fase 3).
  • Leitura via os.Stdin (compatível com o juiz online).

2. Relatório comparativo (mínimo 1 página)

Responda com base na sua experiência de implementação:

  1. O código em Go ficou mais ou menos legível que o Java para este problema? Por quê?
  2. Em quais situações as goroutines trouxeram ganho real? Quando não trouxeram?
  3. Como a ausência de herança impactou a modelagem do problema?
  4. Compare o tratamento de erros em Go (val, err) com exceções em Java (try/catch).

Como começar

Go é uma linguagem minimalista e com instalação simples:

  • 📥 Download: go.dev/dl — disponível para Windows, Mac e Linux.
  • 📖 Tour oficial: tour.golang.org — introdução interativa em ~2 horas.
  • 🔧 Nenhuma IDE necessária — um editor de texto e o terminal bastam.
DicaDica de estudo

Antes de começar a implementar, leia os capítulos do Tour oficial sobre:

  • Structs e Métodos — equivalente às classes de Java.
  • Goroutines e Channels — o coração do diferencial de Go.
  • Interfaces — polimorfismo sem herança.

Submissão

  • Submeta o código no mesmo juiz online utilizado para Java (formato de entrada e saída idêntico).
  • Entregue o relatório comparativo no formato PDF junto com o link da submissão.
  • Prazo: 10 de junho de 2026.
De volta ao topo