No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Stringers: personalizar el output de Structs

24/36
Recursos

Aportes 20

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

  • La estructura de datos " Struct " tiene un método llamado " String " , que podemos sobrescribir para personalizar la salida a consola de los datos del struct.

Por lo que puedo ver, lo que va entre func y el nombre de la funcion (miPC pc) es lo que asocia a la funcion con la struct, pero no necesariamente con el “objeto” miPC, ahi puede ir cualquier nombre. Ej:

// Stringer
func (juanito pc) String() string {
	return fmt.Sprintf("PC: %s con %dGB RAM y SSD %dGB", juanito.brand, juanito.ram, juanito.disk)
}

y por otro lado, note algo que esta bueno me parece. Como el struct se inicializa con pares clave:valor entre llaves {}, no hace falta que esten en orden, se lo cambie y funciona igual:

type pc struct {
	ram   int
	disk  int
	brand string
}
...
	// con la struct
	miPC := pc{ram: 16, brand: "Dell", disk: 480}
	fmt.Println(miPC) // llama a String

Creo que los stringers es muy parecido a lo que Python tiene para las clases que se llama el método __src__

Hay otra manera:

fmt.Printf("%+v", myPC)

Escribe los campos y los valores, es bastante legible sin sobrescribir el método String

Este es mi codigo de esta clase 👇

package main

import "fmt"

type pc struct {
	ram   int
	os string
	disk  int
}

func (myPC pc) String() string {
	return fmt.Sprintf("Tengo %d GB de RAM, %d GB de Disco y es un sistema %s.", myPC.ram, myPC.disk, myPC.os)
}

func main() {
	myPC := pc{ram: 16, os: "Linux", disk: 100}

	fmt.Println(myPC)
}

Esto esta mas documentado aquí.

https://github.com/fatih/color 🎨 para darle colores a los mensajes en consola

func (myPC PC) String() string {
  str := color.HiYellowString("My [Pc] is/have:")
  str += color.HiMagentaString("\n * brand %s", myPC.brand)
  str += color.HiCyanString("\n * %d GB of RAM", myPC.ram)
  str += color.HiGreenString("\n * %d GB od disk", myPC.disk)
  return str
}

salida:

Brutal.

package main

import "fmt"

type pc struct {
	tarjetagrafica string
	ram            int
	disk           int
}
//Esta funcion trabajara sobre la variable y la struct definidas en su principio.
//Luego se escribira la funcion "String" y despues el tipo de dato que retornara.
func (miPc pc) String() string {
	return fmt.Sprintf("Tengo %dGB de RAM, %dGB de disco y una targeta grafica %s", miPc.ram, miPc.disk, miPc.tarjetagrafica)

}

//con el metodo stringers podremos modificar los output's de las structs en consola.

func main() {
	miPc := pc{ram: 16, tarjetagrafica: "3080ti", disk: 1000}
	fmt.Println(miPc)
//De esta manera personalizaremos nuestro output en consola.
}

Los stringers son parecidos al metódo toString() de Java ☕

Uff!! El famoso toString() de Java ❣️

```js package car import "encoding/json" // Modelo Publico de Car type CarPublic struct { Brand string Model string Year int Seats int } func (c *CarPublic) ToMap() (res map[string]interface{}) { a, err := json.Marshal(c) if err != nil { panic(err) } json.Unmarshal(a, &res) return } ``` Lo que hice fue buscar la manera de convertir el struct en un map. Este método es agnóstico a la estructura del struct, por lo que se puede aplicar a cualquiera sin tener que hardcodear los atributos. Posteriormente, definí en un paquete aparte llamado utils, un método llamado PrintStruct que imprime cada par key:value por línea. ```js func PrintStruct(f map[string]interface{}) { for i, value := range f { fmt.Printf("%s: %v\n", i, value) } } ```

todo esto me recueda a C jaja y viejo y traumatico C o C++ jaja

Si en el editor les sale que es mala practica mezclar valor y puntero y quieres hacerlo con puntero, es de esta forma

package main

import "fmt"

type pc struct {
	ram   int
	disk  int
	brand string
}

func (myPC *pc) String() string {
	return fmt.Sprintf("RAM: %d, Disk: %d, Brand: %s", myPC.ram, myPC.disk, myPC.brand)
}

func main() {
	myPC := pc{ram: 16, disk: 512, brand: "Lenovo"}
	fmt.Println(&myPC)
}

Code Resume

package main

import (
	"curso_golang_platzi/src/mypackage"
	"fmt"
)

func main() {
	var myPc mypackage.Pc
	myPc.SetBrand("MSI")
	myPc.SetRam(16)
	myPc.SetDisk(1000)
	fmt.Println(myPc)
}
package mypackage

import "fmt"

type Pc struct {
	brand string
	ram   uint
	disk  uint
}

func (p Pc) GetBrand() string {
	return p.brand
}

func (p *Pc) SetBrand(brand string) {
	p.brand = brand
}

func (p Pc) GetRam() uint {
	return p.ram
}

func (p *Pc) SetRam(ram uint) {
	p.ram = ram
}

func (p Pc) GetDisk() uint {
	return p.disk
}

func (p *Pc) SetDisk(disk uint) {
	p.disk = disk
}

//Stringers
//This way we overload the print function for our struct
func (p Pc) String() string {
	return fmt.Sprintf("RAM: %d GB, DISK: %d GB, BRAND: %s", p.ram, p.disk, p.brand)
}

func mypackage() {

}

Link de mi repositorio Curso Golang Basico:
https://github.com/JohnHM1/Go
:3
Brutal.

Ahora viendo esta clase mejoraré la funcion que cree en el Reto anterior:

Funcion anterior:

func (myDoctor DoctorPublic) ShowData() string {
	age := strconv.Itoa(myDoctor.Age)
	return "Name:" + myDoctor.Name + " Speciality:" + myDoctor.Speciality + " Age:" + age

}

//Y para mostrarse
fmt.Println(myDoctor.ShowData())

Funcion mejorada:

func (myDoctor DoctorPublic) String() string {
	return fmt.Sprintf("Doctor information: \nNombre: %s \nSpeciality: %s \nAge: %d", myDoctor.Name, myDoctor.Speciality,
		myDoctor.Age)

}
//Para mostrarse
fmt.Println(myDoctor)

La lección en código:

package main

import "fmt"

type computer struct {
	ram   int
	brand string
	disk  int
}

func (myComputer computer) String() string {

	fmt.Println()
	fmt.Println("=========================================================================")
	fmt.Println("... entrando a función sobrescrita de representación string del struct...")
	fmt.Println("-------------------------------------------------------------------------")

	result := fmt.Sprintf("CantidadRam: %d GB, cantidadHD: %d GB, marca: %s",
		myComputer.ram,
		myComputer.disk,
		myComputer.brand)

	fmt.Println("-------------------------------------------------------------------------")
	fmt.Println("... Saliendo a función sobrescrita de representación string del struct...")
	fmt.Println("_________________________________________________________________________")
	fmt.Println()

	return result
}

func main() {

	fmt.Println()
	fmt.Println("============================================================================================")
	fmt.Println("Sobrescribiendo funciones propias de objetos")
	fmt.Println()
	fmt.Println("... ejemplo usando Stringers para cadenas de texto.")
	fmt.Println("============================================================================================")
	fmt.Println()

	myComputer := computer{ram: 16, brand: "msi", disk: 100}

	fmt.Println("Imprimiendo con 'fmt' el struct con su funcion 'string' sobrescrita:")
	fmt.Println("Este es el struct >>>", myComputer)
	fmt.Println()

}
 

Personalización

// Output Anterior:
XYR
16
32
64
128
// Output Actual:
1.RAM: 16GB
2.DISK: 500GB
3.BRAND: XYR

Código usado:

//[...]
func main(){
  myPc := pkg.Pc{Ram: 16, Disk: 500, Brand: "XYR"}
  fmt.Println(myPc.String())
}

Package:

// [...]
type Pc struct {
	Ram, Disk int
	Brand     string
}
func(myPc Pc) String() string{
  return fmt.Sprintf("1.RAM: %dGB\n2.DISK: %dGB \n3.BRAND:  %s", myPc.Ram, myPc.Disk, myPc.Brand)
} 

Interesante

Los stringers nos sirven para modificar la forma en la que se imprime un struct, se hacen de la siguiente manera:

package main

type pc struct {
	ram int
	model string
}

func (myPc pc) String() string {
	return fmt.Sprintf("Es un %s model, y tiene %d RAM")
}

func main() {
	myPc := pc{model: "Asus", ram: 16}
	fmt.Println(myPc)
}

El output de el Println sera de esta forma:

$ go run main.go
Es un Asus model, y tiene 16 RAM

Si no hubieramos creado el stringer el output seria:

$ go run main.go
{16 500 Msi}
// Cuando imprimamos el objeto
func (myPc pc) String() string {
	return fmt.Sprintf("Tengo %d GB RAM, %d GB Disco y es una %s", myPc.ram, myPc.disk, myPc.brand)
}