Control de Flujo
## Objetivos de Aprendizaje
- Dominar sentencias if, else if, else
- Comprender sentencias switch
- Aprender bucles for y variantes
- Usar defer para limpieza
- Trabajar con goto
## Sentencia if
### if Básico
```go
age := 18
if age >= 18 {
fmt.Println("Adulto")
}
```
### if-else
```go
age := 15
if age >= 18 {
fmt.Println("Adulto")
} else {
fmt.Println("Menor")
}
```
### if-else if-else
```go
score := 85
var grade string
if score >= 90 {
grade = "A"
} else if score >= 80 {
grade = "B"
} else if score >= 70 {
grade = "C"
} else if score >= 60 {
grade = "D"
} else {
grade = "F"
}
fmt.Println("Grade:", grade)
```
### Con Inicialización
```go
if err := doSomething(); err != nil {
fmt.Println("Error:", err)
return
}
```
## Sentencia switch
### switch Básico
```go
day := 3
var dayName string
switch day {
case 1:
dayName = "Lunes"
case 2:
dayName = "Martes"
case 3:
dayName = "Miércoles"
case 4:
dayName = "Jueves"
case 5:
dayName = "Viernes"
case 6:
dayName = "Sábado"
case 7:
dayName = "Domingo"
default:
dayName = "Inválido"
}
fmt.Println(dayName)
```
### Múltiples Valores
```go
month := 4
var days int
switch month {
case 1, 3, 5, 7, 8, 10, 12:
days = 31
case 4, 6, 9, 11:
days = 30
case 2:
days = 28
default:
days = 0
}
```
### Sin Expresión
```go
num := 10
switch {
case num < 0:
fmt.Println("Negativo")
case num == 0:
fmt.Println("Cero")
case num > 0:
fmt.Println("Positivo")
}
```
### fallthrough
```go
score := 75
var grade string
switch {
case score >= 90:
grade = "A"
case score >= 80:
grade = "B"
case score >= 70:
grade = "C"
fallthrough // Continúa al siguiente caso
case score >= 60:
grade = "D"
default:
grade = "F"
}
```
## Bucle for
### for Básico
```go
for i := 0; i < 5; i++ {
fmt.Println(i) // 0, 1, 2, 3, 4
}
```
### Sintaxis Alternativa
```go
i := 0
for i < 5 {
fmt.Println(i)
i++
}
```
### Bucle Infinito
```go
for {
fmt.Println("Para siempre")
if done {
break
}
}
```
### Bucle Range
```go
nums := []int{1, 2, 3, 4, 5}
for i, v := range nums {
fmt.Printf("Índice: %d, Valor: %d\n", i, v)
}
// Ignorar índice
for _, v := range nums {
fmt.Println(v)
}
// Solo índice
for i := range nums {
fmt.Println(i)
}
```
### Iteración de Strings
```go
str := "Hello"
for i, r := range str {
fmt.Printf("Índice: %d, Rune: %c\n", i, r)
}
```
### Iteración de Maps
```go
ages := map[string]int{
"Alice": 30,
"Bob": 25,
}
for key, value := range ages {
fmt.Printf("%s: %d\n", key, value)
}
```
### Iteración de Canales
```go
ch := make(chan int, 5)
ch <- 1
ch <- 2
ch <- 3
close(ch)
for v := range ch {
fmt.Println(v)
}
```
## Equivalente a while
Go no tiene palabra clave `while`. Usa `for` sin inicialización y sentencia post.
```go
n := 1
for n < 100 {
n *= 2
}
fmt.Println("Resultado:", n)
```
## break y continue
### break - Salir del Bucle
```go
for i := 0; i < 10; i++ {
if i == 5 {
break // Sale cuando i es 5
}
fmt.Println(i) // 0, 1, 2, 3, 4
}
```
### continue - Saltar Iteración
```go
for i := 0; i < 5; i++ {
if i == 2 {
continue // Salta cuando i es 2
}
fmt.Println(i) // 0, 1, 3, 4
}
```
### break con Etiqueta
```go
outer:
for i := 0; i < 5; i++ {
for j := 0; j < 5; j++ {
if j == 2 {
break outer // Sale del bucle exterior
}
fmt.Printf("(%d,%d) ", i, j)
}
}
fmt.Println()
```
## Bucles Anidados
```go
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf("(%d,%d) ", i, j)
}
fmt.Println()
}
// Salida:
// (0,0) (0,1) (0,2)
// (1,0) (1,1) (1,2)
// (2,0) (2,1) (2,2)
```
## defer
### defer Básico
```go
func readFile(filename string) {
file, err := os.Open(filename)
if err != nil {
return
}
defer file.Close() // Se ejecuta cuando la función retorna
// Leer archivo...
}
```
### Múltiples defers
```go
func example() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
}
fmt.Println("Principal")
// Salida: Principal, 3, 2, 1 (orden LIFO)
```
### defer con Argumentos
```go
func example() {
x := 10
defer fmt.Println("Diferido:", x) // Imprime 10, no 20
x = 20
fmt.Println("Principal:", x)
}
// Salida: Principal: 20, Diferido: 10
```
### Usos Comunes
```go
// Desbloquear mutex
mu.Lock()
defer mu.Unlock()
// Cerrar conexión de base de datos
db, err := sql.Open(...)
defer db.Close()
// Imprimir entrada/salida de función
func trace(name string) {
fmt.Println("Entrando:", name)
defer fmt.Println("Saliendo:", name)
}
```
## Sentencias return
### Valores de Retorno Nombrados
```go
func rectangleProperties(width, height float64) (area, perimeter float64) {
area = width * height
perimeter = 2 * (width + height)
return // Return desnudo
}
```
### Retorno Anticipado
```go
func findItem(items []int, target int) int {
for i, item := range items {
if item == target {
return i // Retorno anticipado cuando se encuentra
}
}
return -1 // No encontrado
}
```
## Sentencia goto
### Usando goto
```go
func example() {
for i := 0; i < 5; i++ {
if i == 3 {
goto done
}
fmt.Println(i)
}
done:
fmt.Println("Terminado")
}
```
## Patrones Comunes
### Sumar 1 a N
```go
sum := 0
for i := 1; i <= 100; i++ {
sum += i
}
fmt.Println("Suma:", sum)
```
### Buscar en Slice
```go
nums := []int{3, 7, 2, 9, 4}
target := 9
for i, num := range nums {
if num == target {
fmt.Println("Encontrado en índice:", i)
break
}
}
```
### Contar Coincidencias
```go
nums := []int{1, 2, 3, 2, 4, 2, 5}
target := 2
count := 0
for _, num := range nums {
if num == target {
count++
}
}
fmt.Println("Conteo:", count)
```
### Fibonacci
```go
a, b := 0, 1
for i := 0; i < 10; i++ {
fmt.Print(a, " ")
a, b = b, a+b
}
```
## Resumen
- if/else if/else para lógica condicional
- switch para múltiples valores discretos (con múltiples casos)
- for es la única palabra clave de bucle en Go
- Los bucles range iteran sobre slices, maps, strings, canales
- break sale del bucle; continue salta la iteración
- defer ejecuta código cuando la función retorna (orden LIFO)
- Usar break con etiqueta para control de bucles anidados
- goto está disponible pero usar con moderación
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →