piège append()
Salut tout le monde! Bienvenue sur mon blog. ? Si vous êtes ici, vous êtes peut-être entré en contact avec Golang, ou que vous êtes un développeur expérimenté, et vous voulez comprendre le principe de travail interne de la section. Alors commençons!
Le langage GO est très apprécié en raison de sa simplicité et de son efficacité - comme les gens disent souvent: "Le langage Go est de terminer le travail." Pour les développeurs de C, C ou Java et d'autres langues, la grammaire simple et la facilité d'utilisation du langage Go sont rafraîchissantes. Cependant, même dans le langage Go, certaines caractéristiques peuvent confondre les développeurs, en particulier lors du traitement des tranches et des sous-licences. Débournions ces subtilités et comprenons mieux comment éviter les pièges communs de
et tranchés pour partager la mémoire.
append()
Habituellement, lorsque vous avez besoin d'une structure de données pour stocker une série de valeurs, le tranchage est le premier choix en langue go. Leur flexibilité vient d'un tel fait: leur longueur ne fait pas partie de son type. Cette fonctionnalité surmonte les restrictions du tableau, nous permettant de créer une fonction unique qui peut gérer toutes les tranches et permet à la tranche d'augmenter ou de se développer en fonction des besoins. Bien que la tranche ait des similitudes avec le tableau, telles que l'indexation et la longueur, elles ont différentes méthodes de gestion des données. Slice agit comme une référence au tableau sous-jacent, qui stocke en fait les données des tranches. Essentiellement, la tranche offre une vue de certains ou tous les éléments du tableau. Par conséquent, lorsque vous créez une tranche, GO traitera automatiquement le tableau inférieur de la création d'éléments / données en tranches.
La mémoire partagée des tranchés
Le tableau est un bloc de mémoire continu, mais ce qui rend la tranche intéressante, c'est comment ils citent cette mémoire. Décomposons la structure de la tranche:
Lorsque vous créez une tranche, il contient trois composants:
Poèmes pointant vers le tableau sous-jacent
type slice struct { array unsafe.Pointer // 指向底层数组的指针 len int // 切片中的元素数量 cap int // 底层数组的容量 }
<切> la longueur du tranchage (le nombre d'éléments qu'il contient)
len
cap
Avant d'approfondir davantage, essayons de comprendre la capacité de tranchage
. Lorsque vous obtenez des sous-licences à partir du découpage existant de la langue GO, la capacité
package main import "fmt" func main() { // 创建一个具有初始值的切片 original := []int{1, 2, 3, 4, 5} // 创建一个子切片——两个切片共享相同的底层数组! subslice := original[1:3] fmt.Println("未修改的子切片:", subslice) // 输出 => 未修改的子切片: [2 3] // 修改子切片 subslice[0] = 42 fmt.Println("原始切片:", original) // 输出 => 原始切片: [1 42 3 4 5] fmt.Println("修改后的子切片:", subslice) // 输出 => 修改后的子切片: [42 3] }
Lorsque vous créez des tranches à partir de tableaux, la longueur de la tranche est le nombre d'éléments qu'il contenait à l'origine, et sa capacité est le nombre total d'éléments qu'il peut contenir avant de croître.
Lorsque vous obtenez la sous-lisière des tranches existantes:
type slice struct { array unsafe.Pointer // 指向底层数组的指针 len int // 切片中的元素数量 cap int // 底层数组的容量 }
subslice := original[1:4]
<<> La longueur subslice
<<> La capacité subslice
<<> Trap!
Partage de capacité inutilisé append()
La capacité
de la sous-affection comprend des éléments qui n'appartiennent pas à leur longueur mais situés dans la gamme de capacité de tranchage d'origine. Cela signifie que si les sous-licences augmentent, il peut accéder ou modifier ces éléments. append()
<初> pointant initialement vers 2, 3, la capacité est de 4 (elle peut atteindre la fin de la tranche d'origine).
Lorsque vous ajoutez 60, 70 à <追>, il utilise la capacité excédentaire de la tranche d'origine.<<> et
package main import "fmt" func main() { // 创建一个具有初始值的切片 original := []int{1, 2, 3, 4, 5} // 创建一个子切片——两个切片共享相同的底层数组! subslice := original[1:3] fmt.Println("未修改的子切片:", subslice) // 输出 => 未修改的子切片: [2 3] // 修改子切片 subslice[0] = 42 fmt.Println("原始切片:", original) // 输出 => 原始切片: [1 42 3 4 5] fmt.Println("修改后的子切片:", subslice) // 输出 => 修改后的子切片: [42 3] }
subslice
Êtes-vous surpris? subslice
original
subslice
<免> La meilleure pratique pour éviter les pièges
append()
<确> Clarifier la capacité
func main() { // 原始切片 original := []int{1, 2, 3, 4, 5} // 创建一个子切片 subslice := original[1:4] // 指向元素 2, 3, 4 fmt.Println("子切片:", subslice) // 输出 => 子切片: [2 3 4] fmt.Println("子切片的长度:", len(subslice)) // 输出 => 子切片的长度: 3 fmt.Println("子切片的容量:", cap(subslice)) // 输出 => 子切片的容量: 4 }
append()
i. Ceci est important - ce n'est pas seulement un nouveau chef de section, mais un tout nouveau tableau dans la mémoire.
ii. C'est comme une copie d'un fichier au lieu de partager le fichier d'origine.func main() { original := []int{1, 2, 3, 4, 5} subslice := original[1:3] // 指向元素 2, 3 fmt.Println("追加前原始切片:", original) // 输出 => [1 2 3 4 5] fmt.Println("追加前子切片:", subslice) // 输出 => [2 3] fmt.Println("子切片的容量:", cap(subslice)) // 输出 => 4 // 在容量范围内追加到子切片 subslice = append(subslice, 60, 70) // 追加到子切片后打印 fmt.Println("追加后原始切片:", original) // 输出 => [1 2 3 60 70] fmt.Println("追加后子切片:", subslice) // 输出 => [2 3 60 70] }
<将> Lorsque vous passez la tranche à une fonction qui ne devrait pas modifier les données d'origine, considérez la non-variabilité
make([]int, len(subslice))
copy()
Le principal avantage est:
III.
<住> Rappelez-vous:La tranche est une référence au tableau sous-jacent
append()
type slice struct { array unsafe.Pointer // 指向底层数组的指针 len int // 切片中的元素数量 cap int // 底层数组的容量 }
Félicitations pour avoir lu cet article.
N'oubliez pas de partager cette ressource avec d'autres personnes qui peuvent en bénéficier. Suivez-moi pour obtenir plus d'informations.
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!