GoScope Explorando e Navegando em Projetos Go

Muitas vezes, quero analisar rapidamente um projeto Go para entender onde funções, variáveis e tipos estão definidos ou chamados. Foi assim que criei duas ferramentas de linha de comando: GoScope e rgs. A primeira faz um escaneamento completo de todos os arquivos .go de um projeto, gerando uma lista de definições e chamadas de funções. A segunda usa essa lista para me permitir navegar de forma interativa até o ponto exato do código.

GoScope

O GoScope percorre todos os arquivos .go de forma recursiva a partir do diretório atual. Ele imprime:

  • Funções, variáveis, constantes e tipos declarados, junto ao arquivo e linha.
  • Chamadas de função no formato Chamadora.Chamada arquivo:linha.

GoScope

O uso é simples:

cd /path/do/seu/projeto
goscope

Não é necessário passar parâmetros. Ele sempre analisa o diretório atual e subdiretórios em busca de definições em Go. Isso facilita a vida em projetos grandes, pois você não precisa se preocupar em apontar cada subpasta ou arquivo manualmente.

Exemplo de saída

Suponha um arquivo main.go com este conteúdo:

package main

import "fmt"

func main() {
    fmt.Println("Hello World")
    PrintNumber(42)
}

func PrintNumber(n int) {
    fmt.Printf("Number: %d\n", n)
}

Ao rodar goscope, você pode ver algo como:

main main.go:5
PrintNumber main.go:10
main.Println main.go:6
main.PrintNumber main.go:7
PrintNumber.Printf main.go:11

Isso ajuda a entender onde cada função é declarada e onde é chamada.

rgs

O rgs é um script que usa o GoScope como base. Ele faz:

  1. Executa goscope para coletar definições e chamadas.
  2. Usa o fzf para criar um filtro interativo.
  3. Ao selecionar um item, abre o arquivo na linha correspondente, usando seu editor definido em $EDITOR.

Para usá-lo:

rgs

Digite uma parte do nome da função ou variável, escolha o resultado e pressione Enter. Você será levado diretamente para o local exato no código. É prático quando há centenas de funções espalhadas em múltiplos arquivos.

script rgs

#!/usr/bin/env bash

RCS_CMD="goscope"
INITIAL_QUERY="${*:-}"

selected=$(FZF_DEFAULT_COMMAND=$RCS_CMD \
    fzf --ansi \
        --bind "change:reload:sleep 0.1; $RCS_CMD || true" \
        --delimiter ' ' \
        --preview 'file=$(echo {2} | cut -d":" -f1); \
line=$(echo {2} | cut -d":" -f2); \
# Calcula o range de linhas: 10 linhas acima (se possível) e 10 abaixo.
start=$(( line > 10 ? line - 10 : 1 )); \
end=$(( line + 10 )); \
bat --color=always --highlight-line "$line" --line-range "$start:$end" "$file"' \
        --preview-window 'up,60%,border-bottom' \
        --query "$INITIAL_QUERY")

if [ -n "$selected" ]; then
    IFS=' ' read -r function file_line <<< "$selected"
    file="${file_line%%:*}"
    line="${file_line#*:}"
    $EDITOR "$file" "+$line"
    echo "$file +$line"
fi

Esse script é apenas um exemplo. Você pode personalizá-lo para seu fluxo de trabalho.

Instalação

  1. Compilando o GoScope:

    go build -o goscope
    mv goscope /usr/local/bin/
    
  2. Instalando o rgs:

    chmod +x rgs
    cp rgs /usr/local/bin/
    

Após isso, rodar goscope ou rgs deve funcionar de qualquer lugar.

Conclusão

O GoScope e o rgs facilitam a manutenção de projetos Go grandes ao fornecer uma visão clara de onde cada elemento está localizado e como é chamado. Essa abordagem é muito útil em times grandes, pois ajuda no onboarding de novos membros e acelera correções de bugs.

Vídeo com a explicação detalhada:

Referências

Cesar Gimenes

Última modificação