1️⃣

Clase 1: Introducción a GO


Objetivos
  1. Comprender qué es GO y por qué es un lenguaje popular en el desarrollo de software
  1. Configurar el entorno de desarrollo para trabajar en GO
  1. Aprender la sintaxis básica de GO, incluyendo declaración de variables, tipos de datos y operadores

Contenido de la clase:

1. ¿Qué es GO y por qué utilizarlo?

Go es un lenguaje de programación que se ha desarrollado en Google. Se anunció en 2009 como proyecto de código abierto de Robert Griesemer, Rob Pikes y Ken Thompson. Desde entonces, Go se ha usado para desarrollar otras tecnologías conocidas, como Docker, Kubernetes y Terraform. Aunque Go se usa en gran medida en software del lado servidor y en la nube, es un lenguaje de uso general con una gran cantidad de casos de uso diferentes.

Go es un lenguaje fuertemente tipado, esto significa que las variables en Go deben tener un tipo específico y las operaciones entre variables están restringidas por sus tipos.

Go es un lenguaje compilado, esto significa que se necesita un proceso de compilación antes de ejecutar un programa escrito en Go.

¿Por qué utilizarlo?

  • Sintaxis sencilla: Go se caracteriza por una sintaxis clara y concisa.
  • Eficiencia en la ejecución: Go está diseñado para aprovechar al máximo los recursos de hardware disponibles. El compilador de Go genera código máquina eficiente y el lenguaje incluye características como recolección de basura (garbage collection) y concurrencia nativa, lo que permite aprovechar los múltiples núcleos de las CPUs modernas.
  • Concurrencia: Go proporciona soporte nativa para la concurrencia, lo que facilita la escritura de programas concurrentes y paralelos.
    • Concurrencia

      Te permite estar pendiente de varios procesos, comienzas uno, empiezas otro, ves si el anterior ya terminó, luego crear otro así.

      💡
      Ejemplo: En un banco hay un solo cajero, la persona que esta haciendo su transacción, por algún motivo tiene que esperar por una aprobación, entonces lo hacen esperar a un lado mientras siguen atendiendo a los demás en la fila.
    • Paralelismo

      Es usar varios hilos del procesador para hacer varios procesos a la vez, pero siempre estás esperando que la tarea termine

      💡
      Ejemplo: Resulta que en la otra sede de ese banco, hay 3 cajeros, entonces se van atendiendo de manera paralela.
  • Biblioteca estándar robusta: Go cuenta con una biblioteca estándar extensa y poderosa que cubre una amplica gama de funcionalidades (Manipulación de cadenas, servicios web, etc).
  • Comunidad activa: A pesar de ser relativamente joven, Go ha ganado una comunidad de desarrolladores activa y comprometida.

En resumen, Go es un lenguaje de programación diseñado para ser simple, eficiente y adecuado para la construcción de sistemas escalables y concurrentes.

2. Configuración del entorno de desarrollo
  1. Descarga e instalación de GO:
  • Descarga el instalador adecuado para tu sistema operativo (Windows, macOS o Linux).
  • Ejecuta el instalador y sigue las instrucciones para completar la instalación.
  1. Configuración de las variables de entorno
  • En Windows:
    • Abre el "Panel de control" y busca "Variables de entorno".
    • Haz clic en "Editar las variables de entorno del sistema".
    • En la sección "Variables del sistema", busca la variable "Path" y haz clic en "Editar".
    • Agrega la ruta de instalación de Go (por ejemplo, "C:\Go\bin") al final de la lista de rutas separadas por punto y coma (;).
    • Haz clic en "Aceptar" para guardar los cambios.
    💡
  • En macOS y Linux:
    • Abre una terminal.
    • Abre tu archivo de configuración de shell, como .bash_profile, .bashrc, .zshrc, etc., usando tu editor de texto preferido.
    • Agrega la siguiente línea al archivo: export PATH=$PATH:/usr/local/go/bin.
    • Guarda el archivo y ciérralo.
    • Ejecuta el comando source <nombre del archivo de configuración> para actualizar las variables de entorno en la terminal actual.
    💡

Alternativa:

Extensiones VSC:

Nombre: Go
ID: golang.go
Descripción: Rich Go language support for Visual Studio Code
Editor: Go Team at Google
Vínculo de VS Marketplace:
https://marketplace.visualstudio.com/items?itemName=golang.Go

Nombre: Error Lens
ID: usernamehw.errorlens
Descripción: Improve highlighting of errors, warnings and other language diagnostics.
Versión: 3.11.0
Editor: Alexander
Vínculo de VS Marketplace:
https://marketplace.visualstudio.com/items?itemName=usernamehw.errorlens

3. Sintaxis básica de Go: variables, tipos de datos, constantes y operadores.
  1. Entrada / Salida de datos
  • El paquete fmt es una biblioteca estándar de Go que proporciona funciones para formatear y mostrar datos en la consola, leer la entrada del usuario y trabajar con flujos de entrada y salida.
    • Imprimir en la consola:
      • fmt.Print: Muestra los argumentos pasados en la salida estándar sin un salto de línea al final.
      • fmt.Println: Muestra los argumentos pasados en la salida estándar con un salto de línea al final.
      • fmt.Printf: Muestra una cadena formateada en la salida estándar utilizando especificadores de formato.
      package main
      import "fmt"
      
      func main() {
      	name := "Carlos"
      
      	fmt.Print("Hola. \n")
      	fmt.Println("¡Bienvenido!")
      	fmt.Printf("Hola, %s. \n", name)
      }
    • Lectura de entrada:
      • fmt.Scan: Lee la entrada del usuario desde la entrada estándar y asigna los valores leídos a las variables pasadas como argumentos.
      • fmt.Scanf: Lee la entrada del usuario utilizando especificadores de formato y asigna los valores leídos a las variables pasadas como argumentos.
      • fmt.Scanln: Lee la entrada del usuario desde la entrada estándar, asigna los valores leídos a las variables pasadas como argumentos y espera un salto de línea al final.
      package main
      import "fmt"
      
      func main() {
      	var lastName, username string
      	var age int8
      	fmt.Print("Ingresa tu apellido: ")
      	fmt.Scanln(&lastName)
      	fmt.Print("Ingresa tu username: ")
      	fmt.Scanln(&username)
      	fmt.Println("Ingresa tu edad: ")
      	fmt.Scanf("%d", &age)
      	fmt.Printf("Tu apellido es %s y tu username es %s. Tienes %d años. ", lastName, username, age)
      }
    Es muy útil para imprimir y formatear datos en la consola, leer la entrada del usuario y trabajar con flujos de entrada y salida básicos. Ofrece una variedad de funciones y opciones para adaptarse a diferentes necesidades de formateo y manipulación de datos. Documentación fmt: https://pkg.go.dev/fmt
  1. Variables:
  • Declaración: Para declarar una variable en Go, se utiliza la sintaxis var nombreVariable tipo.
    Ejemplo:
    var age int.
  • Inicialización: Para inicializar una variable en Go, se utiliza el operador = después de la declaración.
    Ejemplo:
    age = 26.
  • Declaración e inicialización en una sola línea: También puedes declarar e inicializar una variable en la misma línea.
    Ejemplo:
    name := "Juan".
package main
import "fmt"

func main() {
	var name string
	var age int

	name = "Carlos"
	age = 26

	lastName := "Cordova"

	fmt.Printf("Mi nombre es %s %s, y mi edad es %d", name, lastName, age)

	/*
		var name, age, isActive = "Carlos", 26, true
		fmt.Println(name, age, isActive)

		var (
			name string = "Carlos"
			age int = 26
			isActive = true
		)
		fmt.Println(name, age, isActive)
	*/
}
  1. Tipos de datos:
  • Números enteros: int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64.
tipotamañorango
int88 bits-128 a 127
int1616 bits-2^15 a 2^15 -1-32,768 - 32,767
int3232 bits-2^31 a 2^31 -1-2,147,383,648 - 2,147,383,647
int6464 bits-2^63 a 2^63 -1
uint88 bits0 a 255
uint1616 bits0 a 2^16 -10 - 65,535
uint3232 bits0 a 2^32 -10 - 4,294,967,295
uint6464 bits0 a 2^64 -1
package main
import "fmt"

func main() {
	var discount int = -100
	fmt.Printf("El tipo de dato de %d es %T \n", discount, discount) // El tipo de dato de -100 es int

	var age uint = 26
	fmt.Printf("El tipo de dato de %d es %T \n", age, age) // El tipo de dato de 26 es uint
}
  • Números de coma flotante: float32, float64.
tipotamañorango
float3232 bits-3.4 x 10^38 a 3.4 x 10^38
float6464 bits-1.8 x 10^308 a 1.8 x 10^308
package main
import "fmt"

func main() {
	var price float32 = 1.5
	fmt.Printf("El tipo de dato de %f es %T \n", price, price) // El tipo de dato de 1.5 es float32
}
  • Números complejos: complex64, complex128.
tipotamañorango
complex6432 bitsfloat32
complex12864 bitsfloat64
package main
import "fmt"

func main() {
	var complejo complex64 =  2 + 2i
	fmt.Printf("El tipo de dato de %v es %T \n", complejo, complejo) // El tipo de dato de (2+2i) es complex64
}
  • Cadenas de texto: string.
package main
import "fmt"

func main() {
	var name string = "Carlos"
	var description string = `Esto es un parrafo,
	que contiene varias líneas
	sin necesidad de usar \n`
	fmt.Printf("El tipo de dato de %s es %T \n", name, name) // El tipo de dato de Carlos es string
	fmt.Printf("El tipo de dato de %s es %T \n", description, description)
}
  • Booleanos: bool (valores true o false).
package main
import "fmt"

func main() {
	var isDeveloper bool = true
	fmt.Printf("El tipo de dato de %t es %T \n", isDeveloper, isDeveloper) // El tipo de dato de true es bool
}
  • Byte: byte (representa un caracter ASCII, se necesita 8 bits para almacenar un valor - uint8)
package main
import "fmt"

func main() {
	// Byte
	var a byte = 97 // a
	var b byte = 'b' // 98
	fmt.Printf("%c\n", a) // a
	fmt.Printf("%c\n", b) // b
	fmt.Printf("El tipo de dato de %v es %T \n", a, a) // El tipo de dato de 97 es uint8
	fmt.Printf("El tipo de dato de %v es %T \n", b, b) // El tipo de dato de 98 es uint8

}
  • Caracteres: rune (representa un carácter Unicode, que es un conjunto más aplio que los caracteres ASCII, se necesita 32bits para almacenar un valor - int32).
package main
import "fmt"

func main() {
	// Rune
	var letter rune = 'a'
	var emoji rune = '🔥'
	fmt.Printf("%c\n", letter) // a
	fmt.Printf("%c\n", emoji) // 🔥
	fmt.Printf("El tipo de dato de %v es %T \n", letter, letter) // El tipo de dato de 97 es int32
	fmt.Printf("El tipo de dato de %v es %T \n", emoji, emoji) // El tipo de dato de 128293 es int32
}
  • Arreglos: [len]tipo (por ejemplo, [5]int define un arreglo de enteros).
package main
import "fmt"

func main() {
	// Array
	var numbers [3]int = [3]int{1, 2, 3}
	fmt.Printf("El tipo de dato de %v es %T \n", numbers, numbers) // El tipo de dato de [1 2 3] es [3]int
}
  • Slices: []tipo (por ejemplo, []int define un slice de enteros).
package main
import "fmt"

func main() {
	// Slice
	var fruits []string = []string{"Apple", "Orange", "Banana"}
	fmt.Printf("El tipo de dato de %v es %T \n", fruits, fruits) // El tipo de dato de [Apple Orange Banana] es []string
}
  • Mapas: map[clave]valor (Representa una colección de pares clave-valor )(por ejemplo, map[string]int define un mapa con claves de tipo cadena y valores enteros).
package main
import "fmt"

func main() {
	// Map
	var countries map[string]string = map[string]string{
		"España": "Madrid",
		"Francia": "Paris",
		"Italia": "Roma",
	}
	fmt.Printf("El tipo de dato de %v es %T \n", countries, countries) // El tipo de dato de map[España:Madrid Francia:Paris Italia:Roma] es map[string]string
}
  • Estructuras: struct (representa una estructura que agrupa diferentes campos con diferentes tipos).
  • Punteros: & (representa la dirección de memoria de un valor existente en el programa).
package main
import "fmt"

func main() {
	// Punteros
	var number uint = 10
	puntero := &number
	fmt.Printf("El tipo de dato de %v es %T \n", puntero, puntero) // El tipo de dato de 0xc00001c030 es *uint

}
  • Interfaces: interface (permite definir conjuntos de métodos).
package main
import "fmt"

func main() {
	// Interface
	type Animal interface {
		Sound() string
	}
}
  1. Constantes
  • Declaración: Para declarar una constante en Go, se utiliza la sintaxis const nombre tipo = valor.
    Ejemplo:
    const pi float64 = 3.1416.
  • Las constantes deben tener un valor que se pueda determinar en tiempo de compilación y no se pueden cambiar posteriormente.
// Constantes
package main
import (
	"fmt"
	"math"
)

func main() {
	const pi = 3.14159265359
	fmt.Println(pi) // 3.14159265359
	const (
    name string = "Carlos"
    age int = 26
  )
  fmt.Println(name) // Carlos
  fmt.Println(age) // 26

	/*
		No se puede asignar un valor devuelto por una llamada a una función,
		El valor de una constante debe conocerse en tiempo de compilación y no de ejecución
		math.Sqrt(n) Calcula la raíz cuadrada.
		var a = math.Sqrt(4)   //allowed
	  const b = math.Sqrt(4) //not allowed
		fmt.Println(a, b)
	*/
}

  1. Operadores
  • Operadores aritméticos:
    • + : Suma dos valores.
    • - : Resta dos valores.
    • * : Multiplica dos valores.
    • / : Divide dos valores.
    • % : Devuelve el resto de la división entera.
// Operadores Aritméticos
package main
import "fmt"

func main() {
	num1 := 20
	num2 := 10

	fmt.Println("Suma:", num1+num2)           // 30
	fmt.Println("Resta:", num1-num2)          // 10
	fmt.Println("Multiplicación:", num1*num2) // 200
	fmt.Println("División:", num1/num2)       // 2
	fmt.Println("Módulo:", num1%num2)         // 0
}
  • Operadores relacionales (Comparación):
    • == : Igualdad, Comprueba si dos valores son iguales.
    • != : Desigualdad, Comprueba si dos valores no son iguales.
    • < : Menor que, Comprueba si el valor de la izquierda es menor que el de la derecha.
    • > : Mayor que, Comprueba si el valor de la izquierda es mayor que el de la derecha.
    • <= : Menor igual que, Comprueba si el valor de la izquierda es menor o igual que el de la derecha.
    • >= : Mayor igual que, Comprueba si el valor de la izquierda es mayor o igual que el de la derecha.
// Operadores Relacionales
package main
import "fmt"

func main() {
	num1 := 50
	num2 := 100
	num3 := 100

	fmt.Println("Igualdad:", num1 == num3)        // false
	fmt.Println("Desigualdad:", num1 != num2)     // true
	fmt.Println("Menor que:", num1 < num2)        // true
	fmt.Println("Mayor que:", num2 > num3)        // false
	fmt.Println("Menor igual que:", num3 <= num2) // true
	fmt.Println("Mayor igual que:", num2 >= num1) // false
}
  • Operadores lógicos:
    • && : Operador lógico "y" (and). Devuelve true si ambos operandos son true.
    • || : Operador lógico "o" (or). Devuelve true si al menos uno de los operandos es true.
    • ! : Operador lógico de negación (not). Invierte el valor de un operando booleano.
// Operadores Lógicos
package main
import "fmt"

func main() {
	num1 := 25
	num2 := 40
	num3 := 55
	num4 := 60

	fmt.Println("Operador && (AND):", num1 < num2 && num4 > num3) // true
	fmt.Println("Operador || (OR):", num2 == num4 || num1 < num3) // true
	fmt.Println("Operador ! (NOT):", !(num1 == num3))             // true
}
  • Operadores de asignación:
    • = : Asigna el valor de la derecha al operando de la izquierda.
    • := : Operador de declaración corta
    • += : Incrementa el operando de la izquierda con el valor de la derecha y asigna el resultado.
    • -= : Decrementa el operando de la izquierda con el valor de la derecha y asigna el resultado.
    • *= : Multiplica el operando de la izquierda por el valor de la derecha y asigna el resultado.
    • /= : Divide el operando de la izquierda por el valor de la derecha y asigna el resultado.
    • %= : Calcula el resto de la división del operando de la izquierda por el valor de la derecha y asigna el resultado.
//Operadores de Asignación
package main
import "fmt"

func main() {
	var name string
	name = "Carlos"
	age := 26

	fmt.Printf("Mi nombre es %s y mi edad es %d \n", name, age)

	age += 1 // Equivalente a age = age + 1
	fmt.Println("Mi edad += 1 :", age) // 27

	age -= 1 // Equivalente a age = age - 1
	fmt.Println("Mi edad -= 1 :", age) // 26

	age *= 2 // Equivalente a age = age * 2
	fmt.Println("Mi edad *= 2 :", age) // 52

	age /= 2 // Equivalente a age = age / 2
	fmt.Println("Mi edad /= 2 :", age) // 26

	age %= 2 // Equivalente a age = age % 2
	fmt.Println("Mi edad %= 2 :", age) // 0
}
  • Operadores de incremento/decremento:
    • ++ : Incrementa en uno el valor del operando.
    • -- : Decrementa en uno el valor del operando.
// Operadores de Incremento/Decremento
package main
import "fmt"

func main() {
	number := 10
	fmt.Println("Mi numero es: ", number)

	number++ // Equivalente a number = number + 1
	fmt.Println(number) // 11

	number-- // Equivalente a number = number - 1
	fmt.Println(number) // 10
}
  • Otros operadores:
    • & : Operador de acceso a dirección de memoria.
    • * : Operador de desreferenciación.
    • . : Operador de acceso a campo.
    • [] : Operador de acceso a índice.
    • () : Operador de llamada a función.
// Otros Operadores
package main
import "fmt"

func main() {
	// Operador de acceso a dirección de memoria
	a := 10
	address := &a // Obtiene la dirección de memoria de una variable
	fmt.Println(address) // 0xc00001c030
	// Operador de desreferenciación
	value := *address // Obtiene el valor almacenado en una dirección de memoria
	fmt.Println(value) // 10

	// Operador de acceso a índice
	numbers := []int{1, 2, 3, 4, 5}
	fmt.Println(numbers[2])
	
	// Operador de llamada a función
	other()
}

func other() {
	fmt.Println("Otra función")
}
// Operador de acceso a campo
package main
import "fmt"

type Person struct {
    name string
    age int
}

func main() {
	person := Person{
	    name: "Carlos",
	    age:   26,
	}
	fmt.Println(person.name)
	fmt.Println(person.age)
}
4. Tarea
  1. Escribe un programa en Go que solicite al usuario el precio original de un producto y el porcentaje de descuento aplicado, y luego calcule y muestre el precio final después del descuento. Utiliza la fórmula: PrecioFinal = PrecioOriginal - (PrecioOriginal * Descuento/100).
// Solución
package main
import "fmt"

func main() {
	var price, discount float64
	fmt.Print("Ingresa el precio original del producto: ")
	fmt.Scanln(&price)
	fmt.Print("Ingresa el porcentaje de descuento: ")
	fmt.Scanln(&discount)

	response := price - (price * discount / 100)
	fmt.Println("El precio final después del descuento es:", response)
}
  1. Escribe un programa en Go que solicite al usuario tres números enteros y luego calcule y muestre el promedio de esos tres números.
// Solución
package main
import "fmt"

func main() {
	var num1, num2, num3 int
	fmt.Println("Ingrese tres números enteros:")
	fmt.Print("Número 1: ")
	fmt.Scanln(&num1)
	fmt.Print("Número 2: ")
	fmt.Scanln(&num2)
	fmt.Print("Número 3: ")
	fmt.Scanln(&num3)

	average := (num1 + num2 + num3) / 3
	fmt.Println("El promedio de los tres números es:", average)
}
5. Recursos