← Go EspañolChapter 05 of 13

Funciones

## Objetivos de Aprendizaje - Definir y llamar funciones - Retornar múltiples valores - Usar funciones variádicas - Comprender closures - Pasar funciones como valores - Usar panic y recover ## Funciones Básicas ### Declaración ```go func greet(name string) { fmt.Println("Hola,", name) } func main() { greet("Alice") // Hola, Alice } ``` ### Con Valor de Retorno ```go func add(a, b int) int { return a + b } func main() { result := add(3, 5) fmt.Println(result) // 8 } ``` ### Múltiples Parámetros ```go func greet(firstName, lastName string) { fmt.Printf("Hola, %s %s\n", firstName, lastName) } ``` ## Múltiples Valores de Retorno ### Retornos Múltiples Básicos ```go func divide(a, b float64) (float64, float64) { quotient := a / b remainder := a - quotient*b return quotient, remainder } func main() { q, r := divide(10, 3) fmt.Printf("Cociente: %.2f, Resto: %.2f\n", q, r) } ``` ### Valores de Retorno Nombrados ```go func rectangleProperties(width, height float64) (area, perimeter float64) { area = width * height perimeter = 2 * (width + height) return // Return desnudo } ``` ### Ignorar Valores de Retorno ```go quotient, _ := divide(10, 3) // Ignorar resto ``` ## Manejo de Errores ### Retornar Errores ```go func safeDivide(a, b float64) (float64, error) { if b == 0 { return 0, errors.New("división por cero") } return a / b, nil } func main() { result, err := safeDivide(10, 0) if err != nil { fmt.Println("Error:", err) return } fmt.Println("Resultado:", result) } ``` ### Tipos de Error Personalizados ```go type DivisionError struct { Dividend float64 Divisor float64 } func (e *DivisionError) Error() string { return fmt.Sprintf("no se puede dividir %.2f por cero", e.Dividend) } func safeDivide(a, b float64) (float64, error) { if b == 0 { return 0, &DivisionError{Dividend: a, Divisor: b} } return a / b, nil } ``` ## Funciones Variádicas ### Variádica Básica ```go func sum(nums ...int) int { total := 0 for _, n := range nums { total += n } return total } func main() { fmt.Println(sum(1, 2, 3)) // 6 fmt.Println(sum(1, 2, 3, 4, 5)) // 15 fmt.Println(sum()) // 0 } ``` ### Operador Spread ```go nums := []int{1, 2, 3, 4, 5} fmt.Println(sum(nums...)) // 15 ``` ### Múltiples Variádicas ```go func concat(separator string, values ...string) string { result := "" for i, v := range values { if i > 0 { result += separator } result += v } return result } func main() { fmt.Println(concat("-", "a", "b", "c")) // a-b-c } ``` ## Closures ### Closure Básico ```go func main() { add := func(a, b int) int { return a + b } fmt.Println(add(3, 5)) // 8 } ``` ### Closure con Estado ```go func counter() func() int { count := 0 return func() int { count++ return count } } func main() { next := counter() fmt.Println(next()) // 1 fmt.Println(next()) // 2 fmt.Println(next()) // 3 } ``` ### Closure para Caché ```go func memoize(f func(int) int) func(int) int { cache := make(map[int]int) return func(n int) int { if result, ok := cache[n]; ok { return result } result = f(n) cache[n] = result return result } } ``` ## Funciones como Valores ### Pasar Función como Argumento ```go func apply(nums []int, fn func(int) int) []int { result := make([]int, len(nums)) for i, n := range nums { result[i] = fn(n) } return result } func main() { nums := []int{1, 2, 3, 4, 5} doubled := apply(nums, func(n int) int { return n * 2 }) fmt.Println(doubled) // [2 4 6 8 10] } ``` ### Retornar Función ```go func multiplier(factor int) func(int) int { return func(n int) int { return n * factor } } func main() { double := multiplier(2) triple := multiplier(3) fmt.Println(double(5)) // 10 fmt.Println(triple(5)) // 15 } ``` ## Funciones Anónimas ### IIFE (Invocada Inmediatamente) ```go result := func() int { sum := 0 for i := 1; i <= 10; i++ { sum += i } return sum }() fmt.Println(result) // 55 ``` ### Parámetros Nombrados ```go func operate(a, b int, op func(int, int) int) int { return op(a, b) } func main() { result := operate(10, 5, func(x, y int) int { return x + y }) fmt.Println(result) // 15 } ``` ## Recursión ### Recursión Básica ```go func factorial(n int) int { if n <= 1 { return 1 } return n * factorial(n-1) } func main() { fmt.Println(factorial(5)) // 120 } ``` ### Fibonacci Recursivo ```go func fibonacci(n int) int { if n <= 1 { return n } return fibonacci(n-1) + fibonacci(n-2) } ``` ## Métodos ### Receptor de Valor ```go type Rectangle struct { Width, Height float64 } func (r Rectangle) Area() float64 { return r.Width * r.Height } func main() { r := Rectangle{Width: 10, Height: 5} fmt.Println(r.Area()) // 50 } ``` ### Receptor de Puntero ```go func (r *Rectangle) Scale(factor float64) { r.Width *= factor r.Height *= factor } func main() { r := Rectangle{Width: 10, Height: 5} r.Scale(2) fmt.Println(r.Width, r.Height) // 20 10 } ``` ## panic y recover ### panic ```go func criticalSection() { defer fmt.Println("Limpieza") panic("¡Algo salió mal!") fmt.Println("Esto no se imprimirá") } func main() { criticalSection() fmt.Println("Esto tampoco se imprimirá") } ``` ### recover ```go func safeCall() { defer func() { if r := recover(); r != nil { fmt.Println("Recuperado de:", r) } }() panic("¡Algo salió mal!") } func main() { safeCall() fmt.Println("El programa continúa...") } ``` ### Cuándo Usar panic - Reservado para situaciones verdaderamente irrecuperables - Errores de programación (ej. desreferencia de puntero nil) - No para condiciones de error esperadas (usar retornos de error) ## Resumen - Las funciones se declaran con la palabra clave `func` - Múltiples valores de retorno para manejo de errores - Funciones variádicas aceptan argumentos variables con `...` - Los closures son funciones que capturan su entorno - Las funciones son ciudadanos de primera clase (pueden pasarse como valores) - Los métodos son funciones con parámetros receptor - panic/recover para situaciones excepcionales, no errores normales

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →