23 - Punteros - Parámetros de una función de tipo punteros a int, float32, float64 y string

Hemos visto que cuando llamamos a una función y le pasamos un tipo de dato string, int, float32 o float64 lo que sucede es que se hace una copia de dicha variable en el parámetro de la función.

Ahora veremos el primer uso real de punteros en el lenguaje Go. Cuando uno quiere modificar una variable string, int, float32 o float64 en una función lo que hacemos es pasar la dirección de la variable y que lo reciba un puntero.

Problema 1:

Confeccionar una función que reciba como parámetros las direcciones de dos variables enteras y le cargue a lo apuntado por dichas variables dos enteros.

Programa: ejercicio111.go

package main

import "fmt"

func cargar(pe1 *int, pe2 *int) {
    *pe1 = 100
    *pe2 = 200
}


func main() {
    var x1, x2 int
    cargar(&x1, &x2)
    fmt.Println(x1, x2)
}

En este problema necesitamos desarrollar una función que cargue dos enteros. Como sabemos si le pasamos las variables definidas en la main lo que sucede es que se hace una copia, entonces lo que le pasamos a la función son las dos direcciones de dichas variables enteras (antecedemos el caracter & al nombre de la variable entera para indicar que le pasamos su dirección):

func main() {
    var x1, x2 int
    cargar(&x1, &x2)

Como a la función le pasamos la dirección de variables enteras los parámetros deben ser de tipo puntero:

func cargar(pe1 *int, pe2 *int) {

Dentro de la función utilizamos los punteros para acceder a los contenidos de las variables pasadas:

    *pe1 = 100
    *pe2 = 200
}

Cuando le asignamos a lo apuntado por el puntero pe1 el valor 100 en realidad estamos accediendo al espacio reservado a la variable x1:

    *pe1=100;

Importante

Después de avanzar en este curso del lenguaje Go podemos entender completamente porque es la siguiente sintaxis para cargar un entero por teclado:

var x1 int
fmt.Scan(&x1)

El & significa que le pasamos la dirección de la variable x1 para que la función por medio de un puntero cargue un entero en x1.

Problema 2:

Elaborar una función que se le pase la dirección de una variable entera e incremente en 1 lo apuntado por dicha variable.

Programa: ejercicio112.go

package main

import "fmt"

func incrementar(pe *int) {
    *pe=*pe+1
}

func main() {
    x := 0
    fmt.Println(x) // 0
    incrementar(&x)
    fmt.Println(x) // 1
    incrementar(&x)
    fmt.Println(x) // 2
    incrementar(&x)
    fmt.Println(x) // 3
}

En este caso implementamos una función que se le pase la dirección de una variable entera y le incremente en 1 su contenido. Cada vez que llamamos la función el contenido de la variable x se incrementa en 1:

    x := 0
    fmt.Println(x) // 0
    incrementar(&x)
    fmt.Println(x) // 1
    incrementar(&x)
    fmt.Println(x) // 2
    incrementar(&x)
    fmt.Println(x) // 3

La función recibe una dirección de una variable entera y mediante este puntero modifica lo apuntado:

func incrementar(pe *int) {
    *pe=*pe+1
}

Es importante decir si queremos utilizar el operador ++ para incrementar en 1 lo apuntado por pe debemos utilizar la sintaxis:

func incrementar(pe *int) {
    *pe++
}

Problema 3:

Implementar una función que intercambie el contenido de dos variables enteras, utilizar punteros para solucionarlo.

Programa: ejercicio113.go

package main

import "fmt"

func intercambiar(pe1 *int, pe2 *int) {
     aux := *pe1
    *pe1 = *pe2
    *pe2 = aux
}

func main() {
    x1 := 10
    x2 := 20
    fmt.Println(x1, x2)
    intercambiar(&x1, &x2)
    fmt.Println(x1, x2)
}

Si necesitamos modificar el contenido de dos variables enteras en una función le pasamos sus direcciones y procedemos a modificar lo apuntado, como son enteros los que tenemos que intercambiar definimos una variable auxiliar de tipo int:

func intercambiar(pe1 *int, pe2 *int) {
     aux := *pe1
    *pe1 = *pe2
    *pe2 = aux
}

Cuando llamamos a la función le pasamos las direcciones de las variables enteras para que puedan moficarlas:

func main() {
    x1 := 10
    x2 := 20
    fmt.Println(x1, x2)
    intercambiar(&x1, &x2)
    fmt.Println(x1, x2)
}

Problema propuesto

  • Definir un vector de 5 elementos de tipo entero en la función main.
    Implementar una función que retorne el mayor y el menor elemento del vector por medio de dos parámetros de tipo puntero:
    func mayorMenor(vec [5]int, pmayor *int, pmenor *int) {
    
Solución
ejercicio113.go

package main

import "fmt"

func mayorMenor(vec [5]int, pmayor *int, pmenor *int) {
    *pmayor = vec[0]
    *pmenor = vec[0]
    for f := 1; f < len(vec); f++ {
        if vec[f] > *pmayor {
            *pmayor=vec[f]
        } else {
            if vec[f] < *pmenor {
                *pmenor=vec[f]
            }
        }
    }
}


func main() {
    vec := [5]int{10, 22, 3, 44, 12}
    var ma, me int
    mayorMenor(vec, &ma, &me)
    fmt.Println("Mayor elemento del vector:", ma)
    fmt.Println("Menor elemento del vector:", me)
}