4. Ir a matriz de idiomas, dividir, mapear

formación

Una matriz es una matriz y se define de la siguiente manera:

var arr [n]type

En [n]tipo, n representa la longitud de la matriz y el tipo representa el tipo de elemento de almacenamiento . El funcionamiento de los arrays es similar al de otros lenguajes, y todos se leen o asignan mediante []:

var arr [10]int //  声明了一个 int 类型的数组
arr[0] = 42 //  数组下标是从 0 开始的
arr[1] = 13 //  赋值操作
fmt.Printf("The first element is %d\n", arr[0]) //  获取数据,返回 42
fmt.Printf("The last element is %d\n", arr[9]) // 返回未赋值的最后一个元素,默认返回 0

Dado que la longitud también es parte del tipo de matriz, [3]int y [4]int son tipos diferentes y la matriz no puede cambiar la longitud . La asignación entre matrices es una asignación de valor, es decir, cuando una matriz se pasa a una función como parámetro, lo que se pasa es en realidad una copia de la matriz, no su puntero. Si desea utilizar punteros, debe utilizar el tipo de segmento que se presenta más adelante.

Las matrices se pueden declarar usando otro :=

a := [3]int{
    
    1, 2, 3} //  声明了一个长度为 3 的 int 数组
b := [10]int{
    
    1, 2, 3} //  声明了一个长度为 10 的 int 数组,其中前三个元素初始化为 1 、 2 、 3 ,其它默认为 0
c := [...]int{
    
    4, 5, 6} //  可以省略长度而采用 `...` 的方式, Go 会自动根据元素个数来计算长度

Tal vez dirás, quiero que los valores en la matriz sean matrices, ¿se puede lograr esto? Por supuesto, Go admite matrices anidadas, es decir, matrices multidimensionales. Por ejemplo, el siguiente código declara una matriz bidimensional:

//  声明了一个二维数组,该数组以两个数组作为元素,其中每个数组中又有 4 个 int 类型的元素
doubleArray := [2][4]int{
    
    [4]int{
    
    1, 2, 3, 4}, [4]int{
    
    5, 6, 7, 8}}

//  如果内部的元素和外部的一样,那么上面的声明可以简化,直接忽略内部的类型
easyArray := [2][4]int{
    
    {
    
    1, 2, 3, 4}, {
    
    5, 6, 7, 8}}

rebanada

En muchos escenarios de aplicación, las matrices no pueden satisfacer nuestras necesidades. Cuando definimos inicialmente la matriz, no sabemos qué tan grande se necesita la matriz, por lo que necesitamos una "matriz dinámica". En Go, esta estructura de datos se llama segmento.

Slice no es realmente una matriz dinámica, sino un tipo de referencia. Un sector siempre apunta a una matriz subyacente y un sector se puede declarar como una matriz, excepto que no se requiere la longitud.

// 和声明 array 一样,只是少了长度
var fslice []int
// 接下来我们可以声明一个 slice ,并初始化数据,如下所示:
slice := []byte {
    
    'a', 'b', 'c', 'd'}

Un sector se puede declarar nuevamente desde una matriz o desde un sector existente. El segmento se obtiene a través de la matriz [i: j], donde i es la posición inicial
de la matriz, j es la posición final, pero no incluye la matriz [j] y su longitud es ji.

//  声明一个含有 10 个元素元素类型为 byte 的数组
var ar = [10]byte {
    
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
//  声明两个含有 byte 的 slice
var a, b []byte
// a 指向数组的第 3 个元素开始,并到第五个元素结束,
a = ar[2:5]
// 现在 a 含有的元素 : ar[2] 、 ar[3] 和 ar[4]
// b 是数组 ar 的另一个 slice
b = ar[3:5]
// b 的元素是: ar[3] 和 ar[4]

Preste atención a la diferencia entre la declaración de sector y matriz: cuando se declara una matriz, la longitud de la matriz se indica entre corchetes o la longitud se calcula automáticamente usando..., mientras que al declarar un sector, no hay caracteres entre corchetes
.

rebanada tiene algunas operaciones convenientes

  • La posición inicial predeterminada del segmento es 0, ar[:n] es equivalente a ar[0:n]
  • La segunda secuencia de corte tiene por defecto la longitud de la matriz, ar[n:] es equivalente a ar[n:len(ar)]
  • Si obtiene sectores directamente de una matriz, puede hacer esto como ar[:], porque la primera secuencia predeterminada es 0 y la segunda es la longitud de la matriz, que es equivalente a ar[0:len(ar) ]

El siguiente ejemplo muestra más operaciones de corte:

//  声明一个数组
var array = [10]byte{
    
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}

//  声明两个 slice
var aSlice, bSlice []byte

//  演示一些简便操作
aSlice = array[:3] //  等价于 aSlice = array[0:3] aSlice 包含元素 : a,b,c
aSlice = array[5:] //  等价于 aSlice = array[5:10] aSlice 包含元素 : f,g,h,i,j
aSlice = array[:] //  等价于 aSlice = array[0:10]  这样 aSlice 包含了全部的元素

//  从 slice 中获取 slice
aSlice = array[3:7] // aSlice 包含元素 : d,e,f,g , len=4 , cap=7
bSlice = aSlice[1:3] // bSlice  包含 aSlice[1], aSlice[2]  也就是含有 : e,f
bSlice = aSlice[:3] // bSlice  包含 aSlice[0], aSlice[1], aSlice[2]  也就是含有 : d,e,f
bSlice = aSlice[0:5] //  对 slice 的 slice 可以在 cap 范围内扩展,此时 bSlice 包含: d,e,f,g,h
bSlice = aSlice[:] // bSlice 包含所有 aSlice 的元素 : d,e,f,g

Slice es un tipo de referencia, por lo que cuando una referencia cambia el valor de un elemento en ella, todas las demás referencias cambiarán el valor, como aSlice y bSlice anteriores. Si se modifica el valor de un elemento en aSlice, el valor correspondiente de bSlice también cambiará.

Conceptualmente, un segmento es como una estructura. Esta estructura contiene tres elementos: - un puntero, que apunta a la
posición La longitud de la última posición de la matriz

Array_a := [10]byte{
    
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
Slice_a := Array_a[2:5]

Hay varias funciones integradas útiles para sectores:

  • len obtiene la longitud del corte
  • la tapa obtiene la capacidad máxima de la rebanada
  • append agrega uno o más elementos al segmento y devuelve un segmento del mismo tipo que el segmento
  • La función de copia copia copia elementos del src del segmento de origen al dst de destino y devuelve el número de elementos copiados.

Nota: La función de agregar cambiará el contenido de la matriz a la que hace referencia el segmento, afectando así a otros sectores que hacen referencia a la misma matriz. Pero cuando no queda espacio restante en el segmento (es decir, (cap-len) == 0), se asignará dinámicamente un nuevo espacio de matriz en este momento. El puntero de la matriz de sectores devuelto apuntará a este espacio y el contenido de la matriz original permanecerá sin cambios; otros sectores que hagan referencia a esta matriz no se verán afectados.

mapa

Map es el concepto de diccionario en Python. Su formato es map[keyType]valueType
. Veamos el código a continuación. La lectura y configuración del mapa también son similares al corte. Se opera mediante clave, pero el índice del corte solo puede ser del tipo `int`, y map tiene muchos más tipos, incluidos int, string y todos los tipos con operaciones == y != completamente definidas.

//  声明一个 key 是字符串,值为 int 的字典 , 这种方式的声明需要在使用之前使用 make 初始化
var numbers map[string] int

//  另一种 map 的声明方式
numbers := make(map[string]int)
numbers["one"] = 1 // 赋值
numbers["ten"] = 10 // 赋值
numbers["three"] = 3
fmt.Println(" 第三个数字是 : ", numbers["three"]) //  读取数据
//  打印出来如 : 第三个数字是 : 3

Este mapa es como la tabla que vemos habitualmente. La columna de la izquierda es la clave y la columna de la derecha es el valor.
Hay varios puntos a los que se debe prestar atención al usar el mapa:

  • El mapa está desordenado y el mapa impreso será diferente cada vez, no se puede obtener mediante índice, pero debe obtenerse mediante clave.
  • La longitud del mapa no es fija, es decir, al igual que el sector, también es un tipo de referencia.
  • La función len incorporada también funciona con el mapa y devuelve la cantidad de claves que posee el mapa.
  • El valor del mapa se puede modificar fácilmente. Al usar números ["uno"]=11, puede cambiar fácilmente el valor del diccionario con la clave del uno al 11.

La inicialización del mapa puede inicializar el valor a través de clave: val. Al mismo tiempo, el mapa tiene un método incorporado para determinar si la clave existe.

Eliminar elementos del mapa mediante eliminar:

//  初始化一个字典
rating := map[string]float32 {
    
    "C":5, "Go":4.5, "Python":4.5, "C++":2 }

// map 有两个返回值,第二个返回值,如果不存在 key ,那么 ok 为 false ,如果存在 ok 为 true
csharpRating, ok := rating["C#"]
if ok {
    
    
	fmt.Println("C# is in the map and its rating is ", csharpRating)
} else {
    
    
	fmt.Println("We have no rating associated with C# in the map")
}
delete(rating, "C") //  删除 key 为 C 的元素

Como se mencionó anteriormente, el mapa también es un tipo de referencia. Si dos mapas apuntan a la misma capa inferior al mismo tiempo, uno cambia y el otro cambia en consecuencia:

m := make(map[string]string)
m["Hello"] = "Bonjour"
m1 := m
m1["Hello"] = "Salut" //  现在 m["hello"] 的值已经是 Salut 了

hacer, nuevas operaciones

make se utiliza para la asignación de memoria de tipos integrados (mapa, segmento y canal). new se utiliza para varios tipos de asignación de memoria.

La función incorporada new esencialmente funciona igual que la función del mismo nombre en otros lenguajes: new(T) asigna un espacio de memoria lleno de ceros de tipo T y devuelve su dirección, que es un valor de tipo *T. En términos de Go, devuelve un puntero a un valor cero recién asignado de tipo T. Una cosa es muy importante: new devuelve un puntero.
La función incorporada make(T, args) tiene funciones diferentes a new(T). make solo puede crear sectores, mapas y canales, y devuelve un tipo T con un valor inicial (distinto de cero) en lugar de *T. Básicamente, lo que diferencia a estos tres tipos es que las referencias a estructuras de datos deben inicializarse antes de su uso. Por ejemplo, un segmento es un descriptor de tres elementos que contiene un puntero a los datos (una matriz interna), la longitud y la capacidad; el segmento es nulo hasta que se inicializan estos elementos. Para sectores, mapas y canales, make inicializa las estructuras de datos internas, llenándolas con los valores apropiados.

make devuelve el valor inicializado (distinto de cero).

En cuanto al "valor cero", no se refiere a un valor nulo, sino a un valor predeterminado "antes de que se complete la variable", generalmente 0. A continuación se muestran algunos tipos de "valores cero".

int 0
int8 0
int32 0
int64 0
uint 0x0
rune 0 //rune 的实际类型是 int32
byte 0x0 // byte 的实际类型是 uint8
float32 0 // 长度为 4 byte
float64 0 // 长度为 8 byte
bool false
string ""

Supongo que te gusta

Origin blog.csdn.net/u012534326/article/details/119986218
Recomendado
Clasificación