Maison > développement back-end > Golang > le corps du texte

Un article analysant brièvement Slice dans Golang

青灯夜游
Libérer: 2022-12-20 22:38:43
avant
5975 Les gens l'ont consulté

Cet article vous apprendra Golang et parlera de Slice dans les bases du langage Go. J'espère qu'il vous sera utile.

Un article analysant brièvement Slice dans Golang

1. Définition de la tranche

Nous savons d'après la section précédente que parce que la longueur du tableau est fixe et que la longueur du tableau fait partie du type, il y a déjà trois éléments dans le tableau a, et nous ne peut pas continuer Un nouvel élément est ajouté au tableau a. En js, il est normal que nous ajoutions des éléments aux tableaux et à d'autres opérations. Alors, que devons-nous faire avec go ? Cela présentera notre objectif d'aujourd'hui : le découpage. [Recommandation du didacticiel de programmation : Enseignement de la programmation]

Slice est une séquence de longueur variable avec des éléments du même type. Il s'agit d'une couche d'encapsulation basée sur le type de tableau. Il est très flexible et prend en charge l'expansion automatique. Une tranche est un type de référence et sa structure interne contient adresse, longueur et capacité. Les tranches sont généralement utilisées pour opérer rapidement sur une collection de données. 地址长度容量。切片一般用于快速地操作一块数据集合。

声明切片类型的基本语法如下:

var name []T
Copier après la connexion

其中,

  • name:表示变量名
  • T:表示切片中的元素类型
func main() {
   // 声明切片类型
   var a []string              //声明一个字符串切片
   var b = []int{}             //声明一个整型切片并初始化
   var c = []bool{false, true} //声明一个布尔切片并初始化
   var d = []bool{false, true} //声明一个布尔切片并初始化
   fmt.Println(a)              //[]
   fmt.Println(b)              //[]
   fmt.Println(c)              //[false true]
   fmt.Println(a == nil)       //true
   fmt.Println(b == nil)       //false
   fmt.Println(c == nil)       //false
   // fmt.Println(c == d)   //切片是引用类型,不支持直接比较,只能和nil比较
}
Copier après la connexion

2.简单切片表达式

切片的底层就是一个数组,所以我们可以基于数组通过切片表达式得到切片。 切片表达式中的lowhigh表示一个索引范围(左包含,右不包含),也就是下面代码中从数组a中选出1<=索引值<4的元素组成切片s,得到的切片长度=high-low,容量等于得到的切片的底层数组的容量。

func main() {
	a := [5]int{1, 2, 3, 4, 5}
	s := a[1:3]  // s := a[low:high]
	fmt.Printf("s:%v len(s):%v cap(s):%v\n", s, len(s), cap(s))
}



输出:
a[2:]  // 等同于 a[2:len(a)]
a[:3]  // 等同于 a[0:3]
a[:]   // 等同于 a[0:len(a)]
Copier après la connexion

3.完整切片表达式

对于数组,指向数组的指针,或切片a(注意不能是字符串)支持完整切片表达式

a[low : high : max]
Copier après la connexion

上面的代码会构造与简单切片表达式a[low: high]相同类型、相同长度和元素的切片。另外,它会将得到的结果切片的容量设置为max-low。在完整切片表达式中只有第一个索引值(low)可以省略;它默认为0。

func main() {
	a := [5]int{1, 2, 3, 4, 5}
	t := a[1:3:5]
	fmt.Printf("t:%v len(t):%v cap(t):%v\n", t, len(t), cap(t))
}

输出:
t:[2 3] len(t):2 cap(t):4
Copier après la connexion

完整切片表达式需要满足的条件是0 <= low <= high <= max <= cap(a),其他条件和简单切片表达式相同。

4.使用make()函数构造切片

我们上面都是基于数组来创建的切片,如果需要动态的创建一个切片,我们就需要使用内置的make()函数,格式如下:

make([]T, size, cap)
Copier après la connexion

其中:

  • T:切片的元素类型
  • size:切片中元素的数量
  • cap:切片的容量
func main() {
	a := make([]int, 2, 10)
	fmt.Println(a)      //[0 0]
	fmt.Println(len(a)) //2
	fmt.Println(cap(a)) //10
}
Copier après la connexion

上面代码中a的内部存储空间已经分配了10个,但实际上只用了2个。 容量并不会影响当前元素的个数,所以len(a)返回2,cap(a)则返回该切片的容量。

5.判断切片是否为空

切片的本质就是对底层数组的封装,它包含了三个信息:底层数组的指针、切片的长度(len)和切片的容量(cap)。

切片之间是不能比较的,我们不能使用==操作符来判断两个切片是否含有全部相等元素。 切片唯一合法的比较操作是和nil比较。 一个nil值的切片并没有底层数组,一个nil值的切片的长度和容量都是0。但是我们不能说一个长度和容量都是0的切片一定是nil,例如下面的示例:

var s1 []int         //len(s1)=0;cap(s1)=0;s1==nil
s2 := []int{}        //len(s2)=0;cap(s2)=0;s2!=nil
s3 := make([]int, 0) //len(s3)=0;cap(s3)=0;s3!=nil
Copier après la connexion

要检查切片是否为空,请始终使用len(s) == 0来判断,而不应该使用s == nil来判断。

6.切片的赋值拷贝

拷贝前后两个变量共享底层数组,对一个切片的修改会影响另一个切片的内容,这点需要特别注意。

func main() {
	s1 := make([]int, 3) //[0 0 0]
	s2 := s1             //将s1直接赋值给s2,s1和s2共用一个底层数组
	s2[0] = 100
	fmt.Println(s1) //[100 0 0]
	fmt.Println(s2) //[100 0 0]
}
Copier après la connexion

7.切片遍历

切片的遍历方式和数组是一致的,支持索引遍历和for range遍历。

func main() {
	s := []int{1, 3, 5}

	for i := 0; i < len(s); i++ {
		fmt.Println(i, s[i])
	}

	for index, value := range s {
		fmt.Println(index, value)
	}
}
Copier après la connexion

8.append()方法为切片添加元素

Go语言的内建函数append()可以为切片动态添加元素。 可以一次添加一个元素,可以添加多个元素,也可以添加另一个切片中的元素(后面加…)。

func main(){
	var s []int
	s = append(s, 1)        // [1]
	s = append(s, 2, 3, 4)  // [1 2 3 4]
	s2 := []int{5, 6, 7}  
	s = append(s, s2...)    // [1 2 3 4 5 6 7]
}
Copier après la connexion

通过var声明的零值切片可以在append()

La syntaxe de base pour déclarer un type de tranche est la suivante : 🎜
var s []ints = append(s, 1, 2, 3)
Copier après la connexion
Copier après la connexion
🎜Parmi eux, 🎜
  • name : représente le nom de la variable
  • T : représente le type d'élément dans la tranche< /li>
func main() {
	a := []int{1, 2, 3, 4, 5}
	b := a
	fmt.Println(a) //[1 2 3 4 5]
	fmt.Println(b) //[1 2 3 4 5]
	b[0] = 1000
	fmt.Println(a) //[1000 2 3 4 5]
	fmt.Println(b) //[1000 2 3 4 5]
}
Copier après la connexion
Copier après la connexion

🎜2. Expression de tranche simple🎜🎜🎜La couche inférieure de la tranche est un tableau, nous pouvons donc obtenir la tranche via l'expression de tranche basée sur l'expression de tranche. sur le tableau. low et high dans l'expression de découpage représentent une plage d'index (la gauche inclut, la droite n'inclut pas), c'est-à-dire que le code suivant sélectionne 1&lt dans le tableau a ; = Les éléments avec une valeur d'index <4 forment slice s, la tranche obtenue length=high-low, et la capacité est égale à la capacité du tableau sous-jacent de la tranche obtenue. 🎜
copy(destSlice, srcSlice []T)
Copier après la connexion
Copier après la connexion

🎜3. Expression de tranche complète🎜🎜🎜Pour les tableaux, les pointeurs vers des tableaux ou la tranche a (🎜notez qu'il ne peut pas s'agir d'une chaîne🎜) prend en charge les expressions de tranche complètes🎜
func main() {
	// copy()复制切片
	a := []int{1, 2, 3, 4, 5}
	c := make([]int, 5, 5)
	copy(c, a)     //使用copy()函数将切片a中的元素复制到切片c
	fmt.Println(a) //[1 2 3 4 5]
	fmt.Println(c) //[1 2 3 4 5]
	c[0] = 1000
	fmt.Println(a) //[1 2 3 4 5]
	fmt.Println(c) //[1000 2 3 4 5]
}
Copier après la connexion
Copier après la connexion
🎜 Le code ci-dessus construira une tranche du même type, de la même longueur et des mêmes éléments que la simple expression de tranche a[low: high]. De plus, il définit la capacité de la tranche résultante sur max-low. Seule la première valeur d'index (faible) peut être omise dans une expression de découpage complète ; sa valeur par défaut est 0. 🎜
func main() {
	// 从切片中删除元素
	a := []int{30, 31, 32, 33, 34, 35, 36, 37}
	// 要删除索引为2的元素
	a = append(a[:2], a[3:]...)
	fmt.Println(a) //[30 31 33 34 35 36 37]
}
Copier après la connexion
Copier après la connexion
🎜Les conditions qu'une expression de tranche complète doit satisfaire sont 0 <= low <= high <= max <= cap(a), et les autres conditions sont les mêmes que simples expressions de tranche. 🎜

🎜4. Utilisez la fonction make() pour construire une tranche🎜🎜🎜Nous avons tous créé des tranches basées sur des tableaux. Si nous devons créer une tranche dynamiquement, nous devons le faire. utilisez la fonction intégrée La fonction make() a le format suivant : 🎜rrreee🎜où : 🎜
  • T : le type d'élément de la tranche
  • taille : le nombre d'éléments dans la tranche
  • li>
  • cap : capacité de la tranche
rrreee🎜Dans le code ci-dessus, 10 espaces de stockage internes de a</code > ont été alloués, mais seulement 2 sont réellement utilisés. La capacité n'affecte pas le nombre actuel d'éléments, donc <code>len(a) renvoie 2 et cap(a) renvoie la capacité de la tranche. 🎜

🎜5. Déterminez si la tranche est vide🎜🎜🎜L'essence d'une tranche est d'encapsuler le tableau sous-jacent. Elle contient trois informations : le pointeur du tableau sous-jacent. et la longueur de la tranche (len) et la capacité de la tranche (cap). 🎜🎜Les tranches ne peuvent pas être comparées. Nous ne pouvons pas utiliser l'opérateur == pour déterminer si deux tranches contiennent tous des éléments égaux. La seule opération de comparaison légale pour les tranches est avec nil. Une tranche de valeurs nil n'a pas de tableau sous-jacent, et la longueur et la capacité d'une tranche de valeurs nil sont toutes deux égales à 0. Mais on ne peut pas dire qu'une slice de longueur et de capacité 0 doit être nil, comme dans l'exemple suivant : 🎜rrreee🎜Pour vérifier si une slice est vide, utilisez toujours len(s ) = = 0 au lieu de s == nil. 🎜

🎜6. Copie d'affectation de la tranche 🎜🎜🎜Les deux variables avant et après la copie partagent le tableau sous-jacent. La modification d'une tranche affectera le contenu d'une autre tranche. attention. . 🎜rrreee

🎜7. Traversée de tranches 🎜🎜🎜La méthode de traversée des tranches est la même que celle des tableaux et prend en charge la traversée d'index et la traversée pour plage . 🎜La méthode rrreee

🎜8.append() ajoute des éléments à la tranche🎜🎜🎜La fonction intégrée du langage Go append() peut ajouter dynamiquement des éléments à la tranche. Vous pouvez ajouter un élément à la fois, plusieurs éléments ou des éléments d'une autre tranche (suivi de...). 🎜rrreee🎜Les tranches de valeur nulle déclarées via var peuvent être utilisées directement dans la fonction append() sans initialisation. 🎜
var s []ints = append(s, 1, 2, 3)
Copier après la connexion
Copier après la connexion

每个切片会指向一个底层数组,这个数组的容量够用就添加新增元素。当底层数组不能容纳新增的元素时,切片就会自动按照一定的策略进行“扩容”,此时该切片指向的底层数组就会更换。“扩容”操作往往发生在append()函数调用时,所以我们通常都需要用原变量接收append函数的返回值。

9.使用copy()函数复制切片

由于切片是引用类型,所以a和b其实都指向了同一块内存地址。修改b的同时a的值也会发生变化。

func main() {
	a := []int{1, 2, 3, 4, 5}
	b := a
	fmt.Println(a) //[1 2 3 4 5]
	fmt.Println(b) //[1 2 3 4 5]
	b[0] = 1000
	fmt.Println(a) //[1000 2 3 4 5]
	fmt.Println(b) //[1000 2 3 4 5]
}
Copier après la connexion
Copier après la connexion

Go语言内建的copy()函数可以迅速地将一个切片的数据复制到另外一个切片空间中,copy()函数的使用格式如下:

copy(destSlice, srcSlice []T)
Copier après la connexion
Copier après la connexion

其中:

  • srcSlice: 数据来源切片
  • destSlice: 目标切片
func main() {
	// copy()复制切片
	a := []int{1, 2, 3, 4, 5}
	c := make([]int, 5, 5)
	copy(c, a)     //使用copy()函数将切片a中的元素复制到切片c
	fmt.Println(a) //[1 2 3 4 5]
	fmt.Println(c) //[1 2 3 4 5]
	c[0] = 1000
	fmt.Println(a) //[1 2 3 4 5]
	fmt.Println(c) //[1000 2 3 4 5]
}
Copier après la connexion
Copier après la connexion

10.从切片中删除元素

Go语言中并没有删除切片元素的专用方法,我们可以使用切片本身的特性来删除元素。

func main() {
	// 从切片中删除元素
	a := []int{30, 31, 32, 33, 34, 35, 36, 37}
	// 要删除索引为2的元素
	a = append(a[:2], a[3:]...)
	fmt.Println(a) //[30 31 33 34 35 36 37]
}
Copier après la connexion
Copier après la connexion

要从切片a中删除索引为index的元素,操作方法是a = append(a[:index], a[index+1:]...)

结束:

再次提醒,需要进技术交流群的同学,可以加我微信fangdongdong_25,需要进前端工程师交流群的备注“前端”,需要进go后端交流群的备注“go后端”

【相关推荐:Go视频教程

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!

Étiquettes associées:
source:juejin.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal