Aujourd'hui c'est le week-end, même si ce n'est qu'un jour. Laissez-moi partager avec vous une petite nouvelle concernant Go1.17. Gagnez chaque jour une compétence pour attirer les poissons !
Dans le langage Go, une tranche contient une référence à son tableau de support, que le tableau existe quelque part en tant que variable indépendante ou qu'il s'agisse simplement d'un tableau anonyme alloué pour prendre en charge le découpage.
La structure de base du découpage est la suivante :
// runtime/slice.go type slice struct { array unsafe.Pointer // 指向底层数组的指针 len int // 长度 cap int // 容量 }
La méthode actuelle de découpage pour prendre en charge les tableaux peut provoquer des fuites de mémoire intéressantes lors du découpage ou produire des changements surprenants dans votre découpage.
Un autre point très important est que dans Go 1.16 et avant, il n'existe aucune méthode sûre pour convertir du type tranche en type tableau, ce qui est assez impuissant.
Nous ne pouvons le faire qu'en appelant la bibliothèque standard Reflect ou Unsafe et en écrivant du code non sécurisé :
(*[10]byte)(unsafe.Pointer(&b[0]))
Évidemment, ce n'est pas élégant. Le responsable ne recommande pas d'utiliser unsafe. Une fois le traitement erroné, cela peut entraîner une issue fatale. erreurs et est relativement incontrôlable.
En fait, dès 2009, peu après la sortie de Go (bien avant la sortie de Go 1.0), certaines personnes ont soulevé des doutes pertinents et espéré résoudre ce problème :
Enfin, dans le prochain Go 1.17, ce sera rendu possible grâce à une série de changements commençant par commit-id #1c268431f4, la spécification mise à jour :
La description de ceci dans la nouvelle spécification est simple :
Conversion d'une tranche en pointeur de tableau renvoie un pointeur vers le tableau sous-jacent de la tranche. Si la longueur de la tranche est inférieure à la longueur du tableau, une panique à l'exécution se produit
- C'est inoffensif et peut fonctionner normalement.
- Si la tranche est plus longue que le tableau, cela signifie que votre tableau ne pourra pas accéder à tous les tableaux de support de la tranche d'origine.
De plus, la spécification fournit de nouveaux exemples, que nous pouvons utiliser dans Go1.17 :
s := make([]byte, 2, 4) s0 := (*[0]byte)(s) // s0 != nil s2 := (*[2]byte)(s) // &s2[0] == &s[0] s4 := (*[4]byte)(s) // panics: len([4]byte) > len(s) var t []string t0 := (*[0]string)(t) // t0 == nil t1 := (*[1]string)(t) // panics: len([1]string) > len(s)
- Conversion de la variable s2 : Elle convertit le tableau sous-jacent de la tranche. Cette conversion n'alloue pas (et ne peut pas) allouer de. nouveau réseau, garantissant ainsi son efficacité.
- Conversion des variables s0 et t0 : Elle convertit un fragment non vide en un tableau de longueur 0. Bien que vous ne puissiez rien faire avec un tableau de longueur 0, vous devez quand même lui donner un pointeur valide, qui est nul.
Il convient de noter qu'il n'existe actuellement aucun moyen de vérifier si un événement de panique se produira en raison de raisons hors limites telles que l'assertion de type. Si vous pensez que votre extrait est trop court et peut provoquer un événement de panique, vous devez alors utiliser if pour préjuger.
Dans le même temps, la bibliothèque standard Reflect sera également mise à jour pour prendre en charge la conversion de tranches en pointeurs de tableau. Si vous utilisez Reflect pour effectuer un travail de conversion associé, il est recommandé de lire les notes de cette soumission.
Avez-vous d'autres réflexions et demandes sur la conversion de type en langage Go, ou avez-vous rencontré des pièges ?
Tout le monde est invité à laisser des messages et à communiquer dans la zone de commentaires.