domingo, 18 de noviembre de 2018

Conversión de datos en Go

Los datos son indispensables en nuestros programas. Gracias a las variables y a las constantes podemos almacenar y consultar datos. Pero nuestros programas también realizarán cálculos y transformaciones sobre los datos.

Conversión entre tipos numéricos

Vamos a probar el siguiente programa, el cual suma dos variables de tipo entero:

package main

import "fmt"

func main() {
   var a byte = 64
   var b int32 = 1567890

   fmt.Printf("%v + %v = %v\n", a, b, a+b)
}

A pesar de que las dos variables son de tipo entero, cada una de ellas es de un tipo específico y distinto. Por este motivo, al ejecutar este programa se producirá el siguiente error:

invalid operation: a + b (mismatched types byte and int32)

Tiene todo su sentido: un tipo byte es un entero que solo puede almacenar valores entre 0 y 255, mientras que el tipo int32 tiene un tamaño de cuatro bytes.

Para poder llevar a cabo esta suma, los dos valores deben ser del mismo tipo. Por tanto, habrá que convertir la variable con el tipo más pequeño al tipo más grande.

   fmt.Printf("%v + %v = %v\n", a, b, int32(a)+b)

Para hacer la conversión de un valor a un tipo concreto, basta con escribir el tipo a convertir, seguido de unos paréntesis, los cuales contendrán el valor a convertir.

tipo(valor)

En el siguiente ejemplo vamos a multiplicar un número de tipo byte con otro número de tipo float32. Primero se convertirá el tipo entero a tipo real y se multiplicarán como números reales. Después, se convertirá el tipo real a tipo entero y se multiplicarán como números enteros:

   var a byte = 64
   var pi float32 = 3.141519

   fmt.Printf("%v x %v = %v\n", a, pi, float32(a)*pi)
   fmt.Printf("%v x %v = %v\n", a, pi, a*byte(pi))

El resultado, obviamente, será distinto:

64 x 3.141519 = 201.05722
64 x 3.141519 = 192

Conversión a string

En muchas ocasiones necesitaremos utilizar un valor numérico o un valor lógico en formato de cadena de texto, o bien concatenar un número a una cadena, por lo que será necesario convertir a formato string.

En estos casos necesitaremos usar el paquete strconv, que contiene multitud de funciones que facilitan las conversiones entre diferentes tipos.

Las siguientes funciones retornan una cadena texto, proveniente de la conversión de un tipo numérico o de un tipo lógico:

strconv.FormatBool(valorBool)
strconv.FormatFloat(valorFloat64, 'base', decimales, tamaño)
strconv.FormatInt(valorInt, tamaño)
strconv.FormatUint(valorUint, tamaño)
strconv.Itoa(valorInt)

El siguiente ejemplo muestra la conversión de un tipo byte y un tipo float32 a formato de cadena de texto:

var a byte = 64
var pi float32 = 3.141519

var mensaje string = "El valor de PI es " +
   strconv.FormatFloat(float64(pi), 'f', 4, 64)

fmt.Println(mensaje)

mensaje = "El valor de a es " +
   strconv.Itoa(int(a))

fmt.Println(mensaje)

Estos métodos son muy efectivos, aunque pueden ser algo confusos y complejos de utilizar. Por este motivo, existe una forma más sencilla de realizar conversiones a cadenas de texto, a través del método Sprintf() del paquete fmt.

El método Sprintf retorna una cadena formateada en base a los parámetros que se faciliten. El primer parámetro es una cadena de texto con la plantilla a formatear. Los siguientes parámetros se corresponden a los valores a ser utilizados dentro de la plantilla.

En la plantilla se especifica texto con caracteres especiales, los cuales serán sustituidos por los valores contenidos en el resto de parámetros, en el mismo orden en que se especifiquen. Estos caracteres especiales permiten indicar el formato en que se mostrará el valor.

He aquí algunos de los caracteres más utilizados:

%v El valor en el formato por defecto
%T El nombre del tipo del valor
%t La palabra true o false
%d Base 10 (formato decimal, del 0 al 9)
%b Base 2 (formato binario, 0 ó 1)
%o Base 8 (formato octal, del 0 al 7)
%e Notación científica, como -1.234456e+78
%E Notación científica, como -1.234456E+78
%f Punto decimal sin exponente, como 123.456
%F Punto decimal sin exponente, como 123.456

Cuando trabajamos con números reales, podemos especificar también el ancho y la precisión del valor:

%f     Ancho y precisión por defecto
%9f    Ancho 9 caracteres, precisión por defecto
%.2f   Ancho por defecto, precisión de 2
%9.2f  Ancho 9 caracteres, precisión de 2
%9.f   Ancho 9 caracteres, precisión de 0

El ejemplo anterior se podría simplificar de esta manera:

mensaje = fmt.Sprintf("El valor de PI es %.4f", pi)
fmt.Println(mensaje)

mensaje = fmt.Sprintf("El valor de a es %d", a)
fmt.Println(mensaje)

Conversión de string a número

Con una cadena de texto no es posible realizar operaciones matemáticas, aunque dicha cadena contenga un número.

var num1, num2 string = "20", "32"
fmt.Println("num1 + num2 = ", num1+num2)

El ejemplo anterior dará como resultado la concatenación de dos cadenas de texto, no la suma de dos números:

num1 + num2 =  2032

Para obtener la suma de los números, será preciso convertir primero las cadenas en números para poder realizar las operaciones matemáticas. Pero es imprescindible que las cadenas contengan números válidos y que la conversión se realice al formato numérico válido correspondiente.

Para realizar estas conversiones, el paquete strconv dispone de varias funciones, dependiendo del tipo de dato a ser convertido:

varBool, err := strconv.ParseBool("false")
varFloat, err := strconv.ParseFloat("3.141519", 64)
varInt, err := strconv.ParseInt("-365", 10, 64)
varInt, err := strconv.Atoi("-365")
varUint, err := strconv.ParseUint("47", 10, 64)

Estas funciones retornan dos valores: el valor convertido al tipo correspondiente y un error, en caso de que éste se produzca.

El siguiente ejemplo convierte los valores de cadena a entero, y después realiza la suma de ambos números:

conv1, err := strconv.Atoi(num1)

if err != nil {
   fmt.Println("Error al convertir num1: ", err)
} else {
   conv2, err := strconv.Atoi(num2)

   if err != nil {
      fmt.Println("Error al convertir num2: ", err)
   } else {
      fmt.Println("conv1 + conv2 = ", conv1+conv2)
   }
}

En cada conversión, verificamos (a través de la sentencia if) si hubo algún error en la conversión. Si la variable err no contiene el valor nil (valor nulo), significa que se ha producido un error, y en ese caso informará del error producido.

Si no hubo error en ninguna de las dos conversiones, procederá a visualizar en pantalla la suma de los números obtenidos de la conversión de las dos cadenas de texto.

Enlaces de interés

No hay comentarios:

Publicar un comentario