Maison >développement back-end >Golang >Conversion de type de tranche dans Go

Conversion de type de tranche dans Go

WBOY
WBOYavant
2024-02-10 15:00:20625parcourir

Go 中的切片类型转换

éditeur php Apple vous présente la conversion de type de tranche en langage Go. Dans le langage Go, une tranche est un tableau dynamique souvent utilisé pour stocker et faire fonctionner un groupe d'éléments du même type. La conversion de type de tranche fait référence à la conversion d'un type de tranche en un autre type de tranche, ce qui est très courant dans le développement réel. Cet article présentera en détail les considérations et les applications pratiques de la conversion de type de tranche pour aider les lecteurs à mieux comprendre et utiliser cette fonctionnalité.

Contenu de la question

Je suis très nouveau, j'ai une formation en C++ et je suis tombé sur des problèmes étranges. Le code est le suivant :

package main

import (
"fmt"
"unsafe"
)

func main() {
     arr := []string { "one", "two", "three" }
     address := unsafe.pointer(&arr)
     addptr := (*[]string)(unsafe.pointer(*(*uintptr)(address)))
     fmt.println((*addptr)[0])
}

Ce code échoue avec :

runtime error: growslice: len out of range

Par exemple, si je change le casting en :

addptr := (*[0]string)(unsafe.pointer(*(*uintptr)(address)))

Le code ci-dessus fonctionne très bien.

Je sais qu'il s'agit d'un cast vers un pointeur de tableau et que le tableau doit avoir une taille constante, Mais comment puis-je le convertir en pointeur vers une tranche ?

Pour rendre les choses encore plus confuses, il est possible d'obtenir l'adresse de la tranche et de l'attribuer à un pointeur comme ceci :

func main() {
     arr := []string { "one", "two", "three" }
     var arrPtr *[]string = &arr
     fmt.Println((*arrPtr)[0])
}

Tout fonctionnera bien cette fois, bien que le pointeur soit du même type que celui vers lequel j'ai lancé le pointeur dangereux dans le premier exemple. Quelqu'un peut-il m'aider à comprendre ce qui se passe exactement ici ?

Solution de contournement

Quelques informations : l'en-tête de tranche contient des pointeurs vers le tableau de support, la longueur et la capacité.

Le code dans la première partie de la question convertit l'en-tête de tranche en un pointeur vers l'en-tête de tranche. go vet La commande prévient que le code dans la question peut abuser de unsafe.pointer.

Corrigé en supprimant l'opération de déréférencement supplémentaire afin que le code soit converti d'un pointeur vers l'en-tête de tranche en un pointeur vers l'en-tête de tranche.

arr := []string{"one", "two", "three"}
address := unsafe.pointer(&arr)
addptr := (*[]string)(unsafe.pointer((*uintptr)(address)))
fmt.println((*addptr)[0]) // prints one

Pas besoin de convertir en *uintptr. Simplifié à :

arr := []string{"one", "two", "three"}
address := unsafe.pointer(&arr)
addptr := (*[]string)(unsafe.pointer(address))
fmt.println((*addptr)[0]) // prints one

Aucune farce dangereuse n'est requise. Simplifié à :

arr := []string{"one", "two", "three"}
addptr := &arr
fmt.println((*addptr)[0]) // prints one

Utilisez le code suivant pour convertir le pointeur de tableau de support de la tranche en pointeur de tableau. Le code est fragile car il suppose que le premier mot de l’en-tête de la tranche est un pointeur vers le tableau de sauvegarde.

arr := []string{"one", "two", "three"}
address := unsafe.pointer(&arr)
addptr := (*[1]string)(unsafe.pointer(*(*uintptr)(address)))
fmt.println((*addptr)[0]) // prints one

La conversion uintptr dans l'extrait de code précédent n'est pas nécessaire. Simplifié à :

arr := []string{"one", "two", "three"}
address := unsafe.Pointer(&arr)
addPtr := (*[]string)(address)
fmt.Println((*addPtr)[0]) // prints one

J'espère que cela aide.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer