Saltar al contenido

pasando un array como argumento en golang

Posteriormente a investigar en varios repositorios y sitios de internet finalmente encontramos la solución que te mostraremos a continuación.

Solución:

Ha definido su función para aceptar un segmento como argumento, mientras intenta pasar un array en la llamada a esa función. Hay dos formas de abordar esto:

  1. Crear una rebanada de la array al llamar a la función. Cambiar la llamada así debería ser suficiente:

    nameReader(a[:])
    
  2. Modifique la firma de la función para tomar una array en lugar de una rebanada. Por ejemplo:

    func nameReader(array [3]name) 
        ...
    
    

    Las desventajas de esta solución son que la función ahora solo puede aceptar un array de longitud 3, y una copia del array se hará al llamarlo.

Puede encontrar más detalles sobre arreglos y cortes, y errores comunes al usarlos aquí: http://openmymind.net/The-Minimum-You-Need-To-Know-About-Arrays-And-Slices-In-Go /

Dado que la respuesta de @ james-henstridge ya cubrió cómo podría hacer que funcione, no duplicaré lo que dijo, pero lo explicaré por qué su respuesta funciona.

En Go, las matrices funcionan de manera un poco diferente que en la mayoría de los demás lenguajes (sí, hay matrices y sectores. Discutiré los sectores más adelante). En Go, las matrices tienen un tamaño fijo, como las usa en su código (entonces, [3]int es de un tipo diferente a [4]int). Además, las matrices son valores. Lo que esto significa es que si copio un array de un lugar a otro, en realidad estoy copiando todos los elementos del array (en lugar de, como en la mayoría de los otros idiomas, simplemente hacer otra referencia al mismo array). Por ejemplo:

a := [3]int1, 2, 3 // Array literal
b := a               // Copy the contents of a into b
a[0] = 0
fmt.Println(a)       // Prints "[0 2 3]"
fmt.Println(b)       // Prints "[1 2 3]"

Sin embargo, como habrás notado, Go también tiene cortes. Las rebanadas son similares a las matrices, excepto en dos key formas. En primer lugar, son de longitud variable (por lo que []int es el tipo de una porción de cualquier número de enteros). En segundo lugar, las rebanadas son referencias. Lo que esto significa es que cuando creo un segmento, se asigna una parte de la memoria para representar el contenido del segmento, y la variable del segmento en sí es solo un puntero a esa memoria. Luego, cuando copio ese segmento, en realidad solo estoy copiando el puntero. Eso significa que si copio el segmento y luego cambio uno de los valores, cambio ese valor para todos. Por ejemplo:

a := []int1, 2, 3 // Slice literal
b := a              // a and b now point to the same memory
a[0] = 0
fmt.Println(a)      // Prints "[0 2 3]"
fmt.Println(b)      // Prints "[0 2 3]"

Implementación

Si esa explicación fue fácilmente comprensible, entonces también podría tener curiosidad por saber cómo se implementa esto (si tuvo problemas para entender eso, dejaría de leer aquí porque los detalles probablemente solo sean confusos).

Debajo del capó, los cortes de Go son en realidad estructuras. Tienen un puntero a la memoria asignada, como mencioné, pero también tienen otros dos key componentes: longitud y capacidad. Si se describiera en términos de Go, se vería así:

type int-slice struct 
    data *int
    len  int
    cap  int

La longitud es la longitud de la rebanada, y está ahí para que pueda pedir len(mySlice), y también para que Go pueda verificar y asegurarse de que no está accediendo a un elemento que no está realmente en el segmento. La capacidad, sin embargo, es un poco más confusa. Así que profundicemos un poco más.

Cuando crea un segmento por primera vez, proporciona una cantidad de elementos que desea que sea el segmento. Por ejemplo, llamando make([]int, 3) le daría una rebanada de 3 ints. Lo que esto hace es asignar espacio en la memoria para 3 entradas y luego devolverle una estructura con un puntero a los datos, la longitud de 3 y la capacidad de 3.

Sin embargo, en Go, puede hacer lo que se llama rebanar. Aquí es básicamente donde se crea un nuevo segmento a partir de un segmento anterior que representa solo una parte del segmento anterior. usas el slc[a:b] sintaxis para hacer referencia a la subsección de slc comenzando en el índice a y terminando justo antes del índice b. Así por ejemplo:

a := [5]int1, 2, 3, 4, 5
b := a[1:4]
fmt.Println(b) // Prints "[2 3 4]"

Lo que hace esta operación de corte bajo el capó es hacer una copia de la estructura que corresponde a a, y para editar el puntero al punto 1 entero hacia adelante en la memoria (porque el nuevo segmento comienza en el índice 1), y edite la longitud para que sea 2 más corta que antes (porque el segmento anterior tenía una longitud de 5, mientras que el nuevo tiene una longitud de 3 ). Entonces, ¿cómo se ve esto en la memoria ahora? Bueno, si pudiéramos visualizar los números enteros dispuestos, se vería así:

  begin     end  // a
  v         v
[ 1 2 3 4 5 ]
    ^     ^
    begin end    // b

Observe cómo todavía hay un int más después del final de b? Bueno, esa es la capacidad. Mira, mientras la memoria se quede para que la usemos, también podríamos usarla toda. Entonces, incluso si solo tiene una rebanada cuya longitud es pequeña, recordará que hay más capacidad en caso de que alguna vez la quiera recuperar. Así por ejemplo:

a := []int1, 2, 3
b := a[0:1]
fmt.Println(b) // Prints "[1]"
b = b[0:3]
fmt.Println(b) // Prints "[1 2 3]"

Mira cómo lo hacemos b[0:3] al final ahi? El largo de b es en realidad menos de 3 en este punto, por lo que la única razón por la que podemos hacer eso es que Go ha realizado un seguimiento del hecho de que, en la memoria subyacente, en realidad tenemos más capacidad reservada. De esa manera, cuando le pidamos que nos devuelva algo, puede complacerlo felizmente.

Un enfoque alternativo

Se podría invocar una función variable en un segmento para ingresar la lista de nombres como argumentos individuales para la función nameReader, por ejemplo:

package main

import "fmt"

type name struct 
    X string


func main() 
    a := [3]name"Abbed", "Ahmed", "Ghassan"
    nameReader(a[:]...)


func nameReader(a ...name) 
    for _, n := range a 
        fmt.Println(n.X)
    

Puntuaciones y comentarios

Si piensas que te ha sido provechoso nuestro post, sería de mucha ayuda si lo compartes con más desarrolladores de esta forma nos ayudas a dar difusión a nuestra información.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *