🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

Perguntas da entrevista Go 2026: Goroutines, canais, interfaces e erros

⏱️4 min read  ·  843 words

As perguntas da entrevista Go (Golang) em 2026 cobrem goroutines, canais, interfaces, gerenciamento de memória e padrões de produção. Go é usado no Google, Cloudflare, Docker, Kubernetes e na maioria das empresas nativas da nuvem. Este guia cobre as perguntas mais comuns da entrevista Go.

Conceitos básicos do Go

1. O que torna o Go diferente de outras linguagens?

  • Goroutines: Threads leves (pilha de 2 KB versus threads de sistema operacional de 1 MB)
  • Canais: Primitivas de comunicação de primeira classe (“não se comunique compartilhando memória; compartilhe memória comunicando”)
  • Compilação rápida: Compila em segundos
  • Binário único: vinculado estaticamente, sem dependências de tempo de execução
  • Lixo coletado: Mas com pausas de GC muito baixas
  • Sem herança: Composição via incorporação e interfaces

2. Explique goroutines versus threads do sistema operacional

package main

import (
	"fmt"
	"runtime"
	"sync"
)

func main() {
	// OS threads: ~1MB stack, managed by OS
	// Goroutines: ~2KB stack (grows as needed), managed by Go runtime

	// Can run millions of goroutines on a few OS threads
	runtime.GOMAXPROCS(runtime.NumCPU())  // use all CPU cores

	var wg sync.WaitGroup
	for i := 0; i < 1_000_000; i++ {  // 1 million goroutines!
		wg.Add(1)
		go func(id int) {
			defer wg.Done()
			// Each goroutine does minimal work
		}(i)
	}
	wg.Wait()
	fmt.Println("Done")
}

3. Qual é a diferença entre canais com buffer e sem buffer?

// Unbuffered: sender blocks until receiver ready
ch := make(chan int)
go func() { ch <- 42 }()  // blocks until receive
val := <-ch

// Buffered: sender blocks only when buffer full
buffered := make(chan int, 5)
buffered <- 1  // doesn't block (buffer has space)
buffered <- 2
buffered <- 3
// buffered <- ... (6th send would block)

// Use buffered for:
// - Known number of items to send
// - Decoupling sender/receiver speeds
// - Preventing goroutine leaks in producer patterns

// Use unbuffered for:
// - Guaranteed synchronization
// - Signaling (done channels)

4. Como você evita vazamentos de goroutine?

// LEAK: goroutine blocks forever on channel
func badWorker() {
	ch := make(chan int)
	go func() {
		// This goroutine will block forever if no one sends to ch!
		val := <-ch
		process(val)
	}()
	// ch goes out of scope, goroutine is stuck
}

// FIX: use context for cancellation
func goodWorker(ctx context.Context) {
	ch := make(chan int, 1)
	go func() {
		select {
		case val := <-ch:
			process(val)
		case <-ctx.Done():  // cancelled — exit cleanly
			return
		}
	}()
}

// Always ensure goroutines have a way to exit
// Rules:
// 1. Goroutine started → must have guaranteed exit path
// 2. Use context.Context for cancellation
// 3. Use done channels for signaling completion
// 4. goleak package in tests catches leaks

5. Explique as interfaces Go

// Interface: implicit implementation (no "implements" keyword)
type Writer interface {
	Write(data []byte) (n int, err error)
}

// Any type with Write method satisfies Writer
type FileWriter struct{ path string }
func (f *FileWriter) Write(data []byte) (int, error) {
	// write to file
	return len(data), nil
}

type NetworkWriter struct{ conn net.Conn }
func (n *NetworkWriter) Write(data []byte) (int, error) {
	return n.conn.Write(data)
}

// Function works with any Writer
func sendData(w Writer, data []byte) error {
	_, err := w.Write(data)
	return err
}

// Empty interface (any type)
var anything interface{} = 42
anything = "now a string"
anything = struct{ x int }{x: 1}

// Type assertion
str, ok := anything.(string)
if ok { fmt.Println(str) }

// Type switch
switch v := anything.(type) {
case int:   fmt.Println("int:", v)
case string: fmt.Println("string:", v)
default:    fmt.Printf("unknown: %T
", v)
}

6. O que são adiar, entrar em pânico e recuperar?

// defer: runs at function exit (LIFO order)
func readFile(path string) ([]byte, error) {
	f, err := os.Open(path)
	if err != nil { return nil, err }
	defer f.Close()  // always closes, even on error/panic
	return io.ReadAll(f)
}

// panic: unrecoverable error (like exception)
// recover: catch panic in deferred function
func safeDiv(a, b int) (result int, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("recovered from panic: %v", r)
		}
	}()
	return a / b, nil  // panics if b == 0
}

result, err := safeDiv(10, 0)
// err = "recovered from panic: runtime error: integer divide by zero"

// Rule: use panic only for truly unrecoverable errors
// Use errors for expected error cases

7. Como Go lida com erros?

// Go errors are values, not exceptions
func divide(a, b float64) (float64, error) {
	if b == 0 {
		return 0, fmt.Errorf("cannot divide by zero")
	}
	return a / b, nil
}

// Always check errors
result, err := divide(10, 0)
if err != nil {
	log.Printf("error: %v", err)
	return err
}

// Custom errors
type ValidationError struct {
	Field   string
	Message string
}

func (e *ValidationError) Error() string {
	return fmt.Sprintf("validation error on %s: %s", e.Field, e.Message)
}

// Error wrapping (Go 1.13+)
if err != nil {
	return fmt.Errorf("processing user %d: %w", userID, err)  // %w wraps
}

// Unwrap
var valErr *ValidationError
if errors.As(err, &valErr) {
	fmt.Println("Field:", valErr.Field)
}

Faça uma entrevista de sucesso: entenda profundamente goroutines e canais (o principal diferencial de outras linguagens), saiba quando usar canais com buffer e sem buffer, explique implicitamente a satisfação da interface e demonstre um tratamento limpo de erros com empacotamento. As funções Senior Go também testam padrões de simultaneidade, perfis de desempenho com pprof e implantação de produção.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা