DMarlon Studio

Lección 20 · 20 de 20

Proyecto: inventario de una tienda · Go

Proyecto final del curso básico de Go: el inventario de una tienda con structs, métodos, errores, slices, bucles y Printf.

Go · Proyecto: inventario de una tienda en DMarlon Studio: el código del ejemplo y su salida en la terminal

Este programa reúne lo visto en el curso. Product es un struct con nombre, precio y existencias, y shop es un slice de productos escrito como literal, sin repetir el tipo en cada elemento.

Value es un método con receptor por valor: solo lee, y devuelve el precio por las existencias. Sell tiene que cambiar las existencias, así que su receptor es un puntero. Si se piden más unidades de las que hay, no toca nada y devuelve un error hecho con fmt.Errorf; si no, resta y devuelve nil.

En main, sales dice cuántas unidades se venden de cada producto, en el mismo orden, y total empieza en 0.0. for i := range shop recorre los índices: con shop[i].Sell(...) el método trabaja sobre el producto del slice y no sobre una copia. El error se comprueba con if err := ...; err != nil: la tetera solo tiene 3 unidades y se piden 4.

Después, p := shop[i] toma el producto ya actualizado y Printf lo escribe en columnas con %-9s, %6.2f, %5d y %9.2f, mientras total va sumando su valor. Lo que queda en el almacén vale 239.40 euros.

En DMarlon Studio, una lógica como esta puede vivir en el servidor Go del destino Web (Go), con la interfaz en el navegador. Y el curso avanzado de Go continúa justo donde termina este.

Código · main.go

package mainimport "fmt"type Product struct {	Name  string	Price float64	Stock int}func (p Product) Value() float64 { return p.Price * float64(p.Stock) }// Sell lowers the stock, or returns an error if there is not enough.func (p *Product) Sell(units int) error {	if units > p.Stock {		return fmt.Errorf("%s: asked for %d, only %d left", p.Name, units, p.Stock)	}	p.Stock -= units	return nil}func main() {	shop := []Product{{"Notebook", 2.5, 40}, {"Pen", 1.2, 100}, {"Mug", 6.95, 12}, {"Teapot", 18, 3}}	sales, total := []int{5, 30, 10, 4}, 0.0 // units sold of each product	for i := range shop {		if err := shop[i].Sell(sales[i]); err != nil {			fmt.Println("Error:", err)		}		p := shop[i]		fmt.Printf("%-9s%6.2f%5d%9.2f\n", p.Name, p.Price, p.Stock, p.Value())		total += p.Value()	}	fmt.Printf("Stock value: %.2f\n", total)}

Salida · go run main.go

Notebook   2.50   35    87.50
Pen        1.20   70    84.00
Mug        6.95    2    13.90
Error: Teapot: asked for 4, only 3 left
Teapot    18.00    3    54.00
Stock value: 239.40

Para recordar

  • Un struct describe los datos; sus métodos, lo que se hace con ellos.
  • Receptor por valor para leer, por puntero para cambiar.
  • Las funciones que pueden fallar devuelven un error.
  • shop[i].Metodo() trabaja sobre el elemento del slice, no sobre una copia.
  • Printf con anchos convierte los datos en una tabla.

Ejercicio

Añada un campo Category y un mapa map[string]float64 que acumule el valor por categoría; escríbalo al final en orden alfabético con sort.Strings.