3️⃣

Clase 3: Funciones, paquetes y manejo de módulos


Objetivos
  1. Comprender la sintaxis y la estructura básica de las funciones en Go, así como aprender a declarar, llamar y utilizar funciones.
  1. Organizar el código en paquetes en Go para crear una estructura lógica y modular.
  1. Familiarizarse con el proceso de importación y uso de paquetes externos en Go.

Contenido de la clase:

1. Declaración y uso de funciones en Go

Las funciones son bloques de código que se utilizan para realizar una tarea específica.

Proporcionan modularidad y reutilización de código al dividir un programa en partes más pequeñas y manejables.

Las funciones se declaran con func seguido del nombre de la función y paréntesis ( ) seguido de llaves { }

  • Declaración de funciones
package main
import "fmt"

func sayHello() {
	fmt.Println("Hello World !!!")
}

func main() {
	sayHello()
}
  • Función con parámetros
package main
import "fmt"

func sum(parameter int) int {
	result := parameter + 1
	return result
}

func main() {
	response :=	myFunction(5)
	fmt.Println(response) // 6
}
  • Retornar múltiples valores
package main
import "fmt"

func calculate(base, height float64) (float64, float64) {
	var area = base * height
	var perimeter = (base + height) * 2
	return area, perimeter
}

func main() {
	base := 10.8
	height := 5.6
	area, perimeter := calculate(base, height)
	fmt.Printf("El área es: %.2f \n", area)
	fmt.Printf("El perímetro es: %.2f", perimeter)
}
  • Identificador en blanco
package main
import "fmt"

func calculate(base, height float64) (float64, float64) {
	var area = base * height
	var perimeter = (base + height) * 2
	return area, perimeter
}

func main() {
	base := 10.8
	height := 5.6
	area, _ := calculate(base, height)
	fmt.Printf("El área es: %.2f \n", area)
}
  • Retornar valores con nombre
package main
import "fmt"

func calculate(base, height float64) (area, perimeter float64) {
	area = base * height
	perimeter = (base + height) * 2
	return // return implicito
}

func main() {
	base := 10.8
	height := 5.6
	area, perimeter := calculate(base, height)
	fmt.Printf("El área es: %.2f \n", area)
	fmt.Printf("El perímetro es: %.2f", perimeter)
}
  • Función Variádica [N número de argumentos]
package main
import "fmt"

// Función variádica que suma un número variable de enteros [elipsis operator]
func sumar(nums ...int) int {
	resultado := 0
	for _, num := range nums {
		resultado += num
	}
	return resultado
}

func main() {
	// Llamada a la función variádica con diferentes números de argumentos
	fmt.Println("Suma:", sumar(1, 2, 3)) // Suma: 6

	// También puedes pasar un slice como argumento variádico
	numeros := []int{1, 2, 3, 4, 5}
	// Utilizamos el operador de elipses `...`
	fmt.Println("Suma:", sumar(numeros...)) // Suma: 15
}
2. Organización de código en paquetes y manejo de módulos.

Hasta ahora solo hemos visto programas de Go que tienen un solo archivo con una función main y un par de funciones más. En un entorno real, este enfoque de escribir todo el código fuente en un solo archivo no es escalable. Se vuelve imposible reutilizar y mantener el código escrito de esta manera. Aquí es donde los paquetes son útiles.

Los paquetes se utilizan para organizar el código, así conseguir una mejor reutilización y legibilidad. Los paquetes son una colección de archivos de origen de Go que residen en el mismo directorio.

Para utilizar un paquete es necesario importar dicho paquete utilizando la palabra clave import.

En go puedes considerar un paquete como todos los archivos que contenga un directorio y un modulo como una colección de paquetes. Para usar el código de un paquete necesitamos importarlo, sin embargo, en Go no existen las importaciones de módulos relativas. Antes de Go 1.8, para importar paquetes (no había modulos) era necesario usar la ruta absoluta, considerando como base la ruta a la que apuntaba la variable de entorno $GOPATH o. A partir de Go 1.11, la manera más sencilla de trabajar con paquetes es usar go mod.

¿Para que sirve un archivo go.mod?

Un archivo de go.mod define un módulo y nos permite establecer el directorio que usaremos como base para importar los paquetes.

¿Qué contiene un archivo go.mod?

El archivo básico de go.mod es muy corto, dentro de este solo se especifíca el nombre del módulo, el cual usaremos para realizar las importanciones y la versión de go.

Crear un archivo go.mod

  1. Variables de entorno en GO
$ go env
  1. Activar GO111MODULE
$ go env -w GO111MODULE=on
  1. Empezar a usar Go Mod en nuestro proyecto
$ go mod init <modulename>
  1. Importar desde nuestro archivo main.go
package main

import (
	"mimodulo/paquete1"
	"mimodulo/paquete2"
)

Ejercicio

  1. Estructura del proyecto
  1. Archivo go.mod
module go-curso-practico

go 1.20
  1. Archivo main.go
package main

import (
	"fmt"
	"go-curso-practico/area"
)

func main() {
	// Datos del rectángulo
	length := 5.0
	width := 3.0
	// Cálculo del área del rectángulo
	rectArea := area.CalculateRectangleArea(length, width)
	fmt.Printf("El área del rectángulo es: %.2f\n", rectArea)

	// Datos del cuadrado
	side := 4.0
	// Cálculo del área del cuadrado
	squareArea := area.CalculateSquareArea(side)
	fmt.Printf("El área del cuadrado es: %.2f\n", squareArea)
}
  1. Archivo area/rectangleArea.go
package area

// Función para calcular el área de un rectángulo
func CalculateRectangleArea(length float64, width float64) float64 {
	return length * width
}
  1. Archivo area/squareArea.go
package area

import "math"

// Función para calcular el área de un cuadrado
func CalculateSquareArea(side float64) float64 {
	return math.Pow(side, 2)
}

Tips

💡
Importar paquetes sin usarlos

Hay ocasiones en donde querremos importar paquetes y no usarlos. Para esto basta con agregar un guión bajo antes de la importación.

package main

import (
  _ "fmt"
)
💡
Alias al importar paquetes

Go también nos permite declarar un alias a la hora de importar un paquete anteponiendo el alias a la ruta de importación.

package main

import alias "ruta/a/paquete"

var result = alias.MyFunction()
💡
Importaciones con punto
Go permite acceder al contenido del paquete de manera directa si importamos usando como alias un punto. De esta manera podemos ignorar el nombre del paquete y acceder directamente a los objetos que contiene
package main

import . "ruta/a/paquete"

var result = MyFunction()
3. Importación y uso de paquetes externos.

go get

Go tiene un manejador de modulos equivalente a pip y npm, python y javascript, respectivamente, llamado get.

Para obtener modulos remotos ejecutamos el comando go get en consola seguido de la ruta de nuestro paquete; soporta cualquier repositorio, no solo github. Desde la versión de go 1.18, go get no compila el código que descarga, sino que se limita a agregar, actualizar o remover dependencias en el archivo go.mod.

$ go get github.com/google/uuid
  1. Archivo go.sum
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
  1. Archivo main.go
package main
import "github.com/google/uuid"

func main() {
	uuid := uuid.New()
	fmt.Println(uuid)
}

go install

Por otro lado, go install no descarga código, sino que compila un modulo e instala el binario en $GOPATH/bin, ignorando el contenido del archivo go.mod cuando se le especifica una versión a través de la linea de comandos.

Go install generalmente se usará para instalar comandos

En resumen, go get se utiliza para descargar y gestionar dependencias de un proyecto, mientras que go installse utiliza para compilar, generar y almacenar programas principales o ejecutables en el GOPATH o en el módulo Go actual. Ambos comandos son útiles para gestionar proyectos y dependencias en Go.


Recursos GO

  1. Go Awesome: Go Awesome es un repositorio de GitHub que contiene una lista curada de bibliotecas y recursos populares en el ecosistema de Go. Proporciona una estructura organizada de categorías, lo que facilita la navegación y la búsqueda de bibliotecas específicas. Las listas de Go Awesome son mantenidas por la comunidad y se pueden contribuir a través de solicitudes de extracción en GitHub. Sin embargo, no proporciona información detallada sobre cada biblioteca y generalmente redirige a otros sitios, como repositorios de GitHub o sitios web oficiales, para obtener más detalles y documentación.
  1. pkg.go.dev: pkg.go.dev es un sitio web oficial de Go mantenido por el equipo de Go de Google. Proporciona una interfaz de búsqueda y exploración de bibliotecas y paquetes en el ecosistema de Go. A diferencia de Go Awesome, pkg.go.dev muestra información más detallada para cada biblioteca, incluyendo documentación, ejemplos de uso, estadísticas de descargas y versiones, entre otros detalles. También cuenta con una interfaz de búsqueda más avanzada y permite filtrar y ordenar resultados en función de diferentes criterios.
4. Tarea
  1. Escribe un programa en Go que calcule el área de un círculo. El programa debe solicitar al usuario que ingrese el radio del círculo y luego mostrar el área calculada en la salida.
// Solución
package main
import (
	"fmt"
	"math"
)

func calculateCircleArea(radius float64) float64 {
	return math.Pi * math.Pow(radius, 2)
}

func main() {
	var radius float64
	fmt.Print("Ingrese el radio del círculo: ")
	fmt.Scanln(&radius)

	area := calculateCircleArea(radius)

	fmt.Printf("El área del círculo con radio %.2f es: %.2f\n", radius, area)
}
  1. Implementa una función en Go que calcule el factorial de un número dado. Luego llama a esa función desde la función main y muestra el resultado en pantalla.
// Solución
package main
import "fmt"

// Función para calcular el factorial de un número
func factorial(n int) int {
	if n == 0 {
		return 1
	}
	return n * factorial(n-1)
}

func main() {
	var num int

	fmt.Print("Ingresa un número: ")
	fmt.Scanln(&num)
	result := factorial(num)
	fmt.Printf("El factorial de %d es %d\n", num, result)
}
5. Recursos