break y continue ajustan el flujo de los bucles y select, mientras que las etiquetas te permiten apuntar a un for, switch o select externo cuando la lógica anidada de otro modo necesitaría indicadores o condiciones duplicadas.
Usadas con moderación, las etiquetas aclaran la intención; sobreutilizadas, oscurecen la estructura.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
package mainimport "fmt"func main() { for i := 0; i < 5; i++ { if i == 2 { continue // omite imprimir 2 } if i == 4 { break // detente antes de 4 } fmt.Println(i) }}
Cuándo usar esto:
Usa continue para omitir iteraciones irrelevantes sin anidar otro cuerpo de if.
Usa break cuando las iteraciones posteriores no puedan cambiar el resultado (se encontró el objetivo, error).
Usa break etiquetado para salir de una búsqueda en bucles anidados sin booleanos found.
Extrae una función cuando más de una etiqueta o múltiples salidas dificultan la lectura del flujo.
package mainimport ( "fmt" "time")func findPair(matrix [][]int, target int) (int, int, bool) {search: for r, row := range matrix { for c, v := range row { if v == target { return r, c, true } if v < 0 { break search // aborta toda la búsqueda en el centinela } } } return 0, 0, false}func poll(ctxDone <-chan struct{}) { ticker := time.NewTicker(100 * time.Millisecond) defer ticker.Stop()loop: for { select { case <-ctxDone: break loop // sale del for, no solo del select case <-ticker.C: fmt.Println("tick") } } fmt.Println("stopped")}func main() { m := [][]int{{1, 2}, {-1, 9}, {3, 4}} r, c, ok := findPair(m, 9) fmt.Println("found", r, c, ok) done := make(chan struct{}) go func() { time.Sleep(250 * time.Millisecond) close(done) }() poll(done)}
Lo que esto demuestra:
break search etiquetado sale de bucles anidados en un valor centinela.
Devolver (r, c, true) es una alternativa a break etiquetado cuando se necesitan resultados.
break loop en un select dentro de for sale del bucle externo, no solo del select.
continue no se muestra aquí, pero omitiría la siguiente iteración del ticker de manera similar.
// Prefiere el retorno temprano sobre el break etiquetado al calcular un resultadofunc contains(haystack []string, needle string) bool { for _, s := range haystack { if s == needle { return true } } return false}
break solo sale de select - for { select { case <-done: break } } entra en un bucle infinito. Solución: usa break loop con una etiqueta en el for, o return.
continue etiquetado en switch - continue solo apunta a bucles, no a switch. Solución: reestructura o usa return.
Variables de indicador en lugar de etiquetas - Los booleanos found con múltiples niveles de break confunden al lector. Solución: etiqueta una vez o extrae una función.
continue omite la lógica de retraso - Colocar continue antes de la limitación de velocidad causa bucles ajustados. Solución: pon el throttling después de la comprobación de continue o al final del bucle.
Salir de defer - break no cruza los límites de la función. Solución: usa return desde la función auxiliar.
goto como sustituto - Los saltos sin etiqueta perjudican la legibilidad. Solución: prefiere el flujo de control estructurado y las funciones.
Versiones de Stack: Esta página fue escrita para Go 1.26.x (GC por defecto Green Tea, go fix modernizers - verifica el parche en la compilación), chi (última - verifica en la compilación), gin (última - verifica en la compilación), echo (última - verifica en la compilación), google.golang.org/grpc (última - verifica en la compilación), sigs.k8s.io/controller-runtime (última - verifica en la compilación), kubebuilder (última - verifica en la compilación), tinygo (última - verifica los objetivos de la placa en la compilación), wazero (última - verifica en la compilación), y golangci-lint (última - verifica el conjunto de linters en la compilación).
NzA2MjAyfDg5M29pZ2N8b2kuc2VkaXVnZWRvYw==
Revisado por Chris St. John·Última actualización: 19 jul 2026