2026-04-10

Escribir Go en GoLand ya es una experiencia sólida. Agregarle GitHub Copilot encima deja el combo casi injustamente bueno. Pero hay una trampa: el Copilot genérico tiende a sugerir código que no es idiomático de Go (abuso de interfaces, errores que se tragan, generics donde no van). En esta guía te voy a mostrar la configuración que uso para que Copilot tenga cara de gopher, y los atajos que más tiempo ahorran día a día.
Si también trabajás con front-end, vale la pena mirar mi otra guía: GitHub Copilot en WebStorm: la mejor configuración para turbinar tu día a día.
Para seguir este tutorial, vas a necesitar:
Si todavía estás en una versión vieja de GoLand, actualizá antes. Las versiones anteriores tienen conflicto entre Copilot y el Full Line Code Completion peleando por el Tab.
Cmd + , en Mac / Ctrl + Alt + S en Windows/Linux)GitHub Copilot en la búsquedaEn GoLand 2025+ el plugin GitHub Copilot ya incluye el chat. Si solo ves un plugin llamado GitHub Copilot, ese es el que trae todo junto.
Después del reinicio, el ícono de Copilot aparece en la barra inferior derecha.
Cuando el ícono se pone verde, Copilot está listo para usar.
Este es el paso más importante para quien quiere el Tab funcionando sin sorpresas. GoLand tiene el Full Line Code Completion nativo, que también ocupa el Tab y compite con Copilot. Si quedás con los dos, nunca sabés cuál va a aceptar.
Insert Inline CompletionCmd + Shift + ] (Mac) / Ctrl + Shift + ] (Windows/Linux)Apply completions to Editor (el de Copilot) en el TabEn la práctica, para Go prefiero la opción A: Copilot sabe más sobre el contexto del proyecto entero y el Full Line termina aportando poco.
Andá a Settings > Tools > GitHub Copilot > Completions y ajustá:
| Opción | Valor recomendado | Por qué |
|---|---|---|
| Show completions automatically | Activo | Sugiere mientras escribís |
| Automatically check for updates | Activo | Mantiene el plugin actualizado |
| Enable Copilot | Activo | El control fino está en la sección de lenguajes |
En la sección Languages, mi recomendación para el día a día con Go:
*_gen.go, *.pb.go, mock_*.go): Copilot solo estorba acáSi usás mucho Bazel o Buf, activá también los archivos .bazel, .bzl y buf.yaml.
Abrí el chat con Ctrl + Shift + C o por la barra lateral derecha, en el ícono de Copilot.
Los tres modos disponibles:
Para habilitar el Agent Mode:
Este es el secreto para que Copilot deje de sugerir código JavaScript disfrazado de Go. Las custom instructions son reglas que Copilot lee antes de cada respuesta.
.github/ (si no existe)copilot-instructions.md# Instrucciones para Copilot
Este es un servicio en Go 1.22+ que expone una API HTTP.
## Stack
- Go 1.22 (standard library preferida siempre que se pueda)
- Router: net/http con el ServeMux nuevo (sin frameworks externos)
- Base de datos: PostgreSQL vía pgx/v5 (sin ORM)
- Logging: log/slog estructurado en JSON
- Tests: testing estándar + testify para assertions
## Patrones idiomáticos obligatorios
- Nunca tragarse errores: siempre retornar o loguear con contexto
- Usar errors.Is / errors.As, nunca comparar errores con ==
- Nunca usar panic en código de producción, solo en init o main
- Pointer receivers solo cuando necesitás mutar o el struct es grande
- Funciones que retornan error deben retornar (T, error), nunca al revés
- Nunca nombrar variables con err genéricos cuando hay más de un error en el scope
- Usar context.Context como primer parámetro en cualquier función que toque I/O
## Tests
- Siempre usar table-driven tests
- Subtests vía t.Run con nombres descriptivos
- Usar t.Helper() en funciones auxiliares de test
- Usar t.Cleanup en vez de defer cuando sea apropiado
- Mocks solo para interfaces de I/O externo, nunca para lógica interna
## Concurrencia
- Nunca crear goroutines sin un plan claro de término (context o WaitGroup)
- Channels con buffer solo con justificación clara
- Proteger estado compartido con sync.Mutex, no con canales si es un lock simple
- Preferir errgroup.Group para fan-out con error
## Qué nunca hacer
- Nunca usar init() para lógica de negocio
- Nunca usar variables globales mutables
- Nunca retornar nil para slice o map cuando el caller espera iterar (retornar vacío)
- Nunca ignorar el retorno de Close() en archivos y conexiones
Guardá, reiniciá el chat y vas a sentir la diferencia en la primera sugerencia.
Para reglas que valen para todos los proyectos Go:
A partir de la versión 2026.2 Copilot también lee AGENTS.md y CLAUDE.md anidados. Si ya usás Claude Code, aprovechá el mismo archivo: Settings > Tools > GitHub Copilot > Customizations > Enable nested AGENTS.md and CLAUDE.md.
| Acción | Mac | Windows/Linux |
|---|---|---|
| Aceptar sugerencia completa | Tab | Tab |
| Rechazar sugerencia | Esc | Esc |
| Aceptar línea por línea | Shift + Option + → | Shift + Alt + → |
| Próxima sugerencia | Shift + Option + ] | Shift + Alt + ] |
| Sugerencia anterior | Shift + Option + [ | Shift + Alt + [ |
| Forzar sugerencia (llamarla manualmente) | Shift + Option + \ | Shift + Alt + \ |
| Abrir panel de sugerencias (10 opciones) | Cmd + Shift + A > Open Copilot | Ctrl + Shift + A > Open Copilot |
Importante para quienes usan teclado ABNT2: el estándar oficial de Copilot es
Option + ],Option + [yOption + \, pero en el teclado brasileño esas combinaciones generan caracteres tipográficos («,», entre otros) y nunca llegan a Copilot. La solución es agregarShifta la combinación (quedaShift + Option + ...), que es lo que dejé en la tabla de arriba. Si usás teclado US, podés usar el estándar sin elShift.
| Acción | Mac | Windows/Linux |
|---|---|---|
| Abrir inline chat en el cursor | Ctrl + Shift + I | Ctrl + Shift + G |
| Ejecutar prompt | Enter | Enter |
| Cancelar | Esc | Esc |
Con el inline chat seleccionás una función, apretás Ctrl + Shift + I, escribís “escribí table-driven tests para esta función” y Copilot genera directo en el archivo de test.
| Acción | Mac | Windows/Linux |
|---|---|---|
| Abrir ventana de chat | Ctrl + Shift + C | Ctrl + Shift + C |
| Nueva conversación | Cmd + N dentro del chat | Ctrl + N dentro del chat |
| Enfocar campo de input | Cmd + L | Ctrl + L |
| Adjuntar archivo al contexto | #nombre-del-archivo.go | Igual |
En Settings > Keymap, buscá copilot y vas a ver que el plugin solo expone algunas acciones bindables (copilot.chat.show, copilot.chat.inline, copilot.openCopilot, copilot.applyInlays, copilot.cycleNextInlays, copilot.cyclePrevInlays y copilot.requestCompletions). Las funcionalidades tipo “explain”, “fix”, “generate tests” no son acciones del plugin: son slash commands que escribís dentro del chat (mirá la próxima sección).
Lo que dejo en mi keymap:
| Acción del plugin | Atajo custom |
|---|---|
copilot.chat.show (abrir ventana de chat) | Cmd + Shift + K |
copilot.chat.inline (abrir inline chat en el cursor) | Cmd + Shift + I |
copilot.openCopilot (tool window de Copilot) | Ctrl + Option + \ |
Si algún atajo entra en conflicto, Keymap te avisa. Cmd + Shift + K por defecto abre Push… de Git en GoLand: yo prefiero disparar Push por el menú y libero esa tecla para Copilot. Si usás Push por atajo, elegí otra combinación (tipo Cmd + Alt + K).
Una vez que el chat está abierto, los slash commands resuelven el resto:
/explain explica la función seleccionada/fix corrige errores reportados por gopls/tests genera table-driven tests/doc genera comentario godoc/simplify propone una versión más idiomáticaEscribí un godoc descriptivo arriba de la función y Copilot implementa en base a él:
// FetchActivePosts retorna los posts publicados en los últimos 30 días,
// ordenados por fecha de publicación descendente, limitados a 10.
// Retorna error si la base de datos no está disponible o si falla la query.
// El contexto se usa para cancelación.
func (r *PostsRepository) FetchActivePosts(ctx context.Context) ([]Post, error) {
// Copilot completa acá siguiendo el patrón del resto del repositorio
}
Cuanto más específico sea el godoc, mejor la sugerencia. Agregar el nombre de archivos relevantes al comentario ayuda todavía más.
Seleccioná la función, apretá Ctrl + Shift + I y escribí:
escribí table-driven tests para esta función, cubriendo el camino feliz, error de base de datos, contexto cancelado y slice vacía. Usá testify/require en las assertions.
Copilot genera el archivo _test.go completo, con t.Run y subtests nombrados.
Si el proyecto todavía usa fmt.Errorf("%v") y querés migrar a %w + errors.Is, abrí el chat en Agent Mode y pedí:
Refactorizá todos los wrappers de error del paquete
internal/servicepara que usen%wy reemplazá las comparaciones con == por errors.Is. Mantené los tests pasando.
Vos revisás los cambios archivo por archivo antes de aceptar.
# para contextualizar el chatEn el chat, escribí #internal/repository/posts.go y #internal/service/posts.go para cargar los archivos como contexto. Te ahorra pegar código.
/tests: genera tests para el código seleccionado/doc: genera comentario godoc/fix: corrige errores reportados por gopls/explain: explica el código seleccionado/simplify: propone una versión más idiomáticaPara Go, /simplify es oro: suele proponer versiones que eliminan loops innecesarios, aprovechan slices de la stdlib y achican el código sin perder legibilidad.
Si usás interfaces para I/O, seleccioná la interfaz, abrí el inline chat y pedí:
generá un mock para esta interfaz usando testify/mock, en el archivo mocks/mock_repository.go
Respeta las custom instructions y genera algo consistente con el resto del proyecto.
Si querés que Copilot use el gopls de tu proyecto como fuente de verdad (go to definition, coverage, go test, go mod tidy), podés configurar un servidor MCP como mcp-gopls. Copilot pasa a consultar el LSP de Go antes de sugerir, lo que reduce mucho la alucinación en proyectos grandes. Es avanzado, pero vale la curva de aprendizaje si trabajás en un monorepo Go.
func(http.Handler) http.Handler).pb.go (son generados, cualquier sugerencia rompe el generator).proto si vas a escribir contratosFull Line Code Completion peleando. Volvé al Paso 3 y aplicá una de las dos soluciones.
Probablemente las custom instructions estén vacías o sean genéricas. Revisá el Paso 6 y detallá los patrones idiomáticos que usás.
Shift + Option + \ (Mac) / Shift + Alt + \ (Windows/Linux)Instalá el plugin GitHub Copilot Chat por separado (algunas versiones todavía vienen separadas).
interface{} o any de másAgregá a las custom instructions: “Evitá any e interface{} excepto cuando realmente no haya un tipo conocido. Preferí tipos concretos o generics tipados.”
.github/copilot-instructions.md creado con reglas idiomáticasCon este setup cerrado, Copilot deja de ser un auto-completador genérico y se vuelve un pair programmer que entiende Go. En una semana de uso vas a estar escribiendo godocs que generan funciones enteras y usando el inline chat para generar table-driven tests sin sacar las manos del teclado.