Heim  >  Artikel  >  Backend-Entwicklung  >  Ein Artikel, der Slices in Golang kurz analysiert

Ein Artikel, der Slices in Golang kurz analysiert

青灯夜游
青灯夜游nach vorne
2022-12-05 19:12:495973Durchsuche

In diesem Artikel lernen Sie Golang kennen und sprechen über Slice in den Grundlagen der Go-Sprache. Ich hoffe, dass er Ihnen hilfreich sein wird.

Ein Artikel, der Slices in Golang kurz analysiert

1. Definition von Slice

Aus dem vorherigen Abschnitt wissen wir, dass es in Array a bereits drei Elemente gibt, da die Länge des Arrays fest ist und die Array-Länge Teil des Typs ist Kann nicht fortfahren Ein neues Element wird zu Array a hinzugefügt. In js ist es normal, dass wir Elemente zu Arrays und anderen Operationen hinzufügen. Was sollen wir also mit go tun? Damit stellen wir unseren heutigen Schwerpunkt vor – das Schneiden. [Empfehlung für ein Programmier-Tutorial: Programmierlehre]

Slice ist eine Sequenz variabler Länge mit Elementen desselben Typs. Es handelt sich um eine Kapselungsschicht, die auf dem Array-Typ basiert. Es ist sehr flexibel und unterstützt die automatische Erweiterung. Ein Slice ist ein Referenztyp und seine interne Struktur enthält Adresse, Länge und Kapazität. Slices werden im Allgemeinen verwendet, um eine Datensammlung schnell zu bearbeiten. 地址长度容量。切片一般用于快速地操作一块数据集合。

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

var name []T

其中,

  • 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比较
}

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)]

3.完整切片表达式

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

a[low : high : max]

上面的代码会构造与简单切片表达式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

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

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

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

make([]T, size, cap)

其中:

  • 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
}

上面代码中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

要检查切片是否为空,请始终使用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]
}

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)
	}
}

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]
}

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

Die grundlegende Syntax zum Deklarieren eines Slice-Typs lautet wie folgt: 🎜
var s []ints = append(s, 1, 2, 3)
🎜Daunter 🎜
  • name: repräsentiert den Variablennamen
  • T: repräsentiert den Elementtyp im Slice
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]
}

🎜2. Einfacher Slice-Ausdruck🎜🎜🎜Die unterste Ebene des Slice ist ein Array, sodass wir den Slice durch den Slice-Ausdruck erhalten können auf dem Array. low und high im Slicing-Ausdruck stellen einen Indexbereich dar (links schließt ein, rechts schließt nicht ein), das heißt, der folgende Code wählt 1&lt aus Array a aus; =Die Elemente mit dem Indexwert <4 bilden Slices, das erhaltene Slice length=high-low und die Kapazität ist gleich der Kapazität des zugrunde liegenden Arrays des erhaltenen Slice. 🎜
copy(destSlice, srcSlice []T)

🎜3. Vollständiger Slice-Ausdruck🎜🎜🎜Für Arrays, Zeiger auf Arrays oder Slice a (🎜beachten Sie, dass es sich nicht um eine Zeichenfolge handeln kann🎜) werden vollständige Slice-Ausdrücke unterstützt🎜
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]
}
🎜 Der obige Code erstellt ein Slice desselben Typs, derselben Länge und derselben Elemente wie der einfache Slice-Ausdruck a[low: high]. Darüber hinaus wird die Kapazität des resultierenden Slice auf max-low gesetzt. In einem vollständigen Slicing-Ausdruck kann nur der erste Indexwert (niedrig) weggelassen werden; der Standardwert ist 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]
}
🎜Die Bedingungen, die ein vollständiger Slice-Ausdruck erfüllen muss, sind 0 <= niedrig <= hoch <= max <= cap(a), und andere Bedingungen sind die gleichen wie bei einfachen Slice-Ausdrücke. 🎜

🎜4. Verwenden Sie die Funktion make(), um ein Slice zu erstellen. 🎜🎜🎜Wir haben alle Slices basierend auf Arrays erstellt. Wenn wir ein Slice dynamisch erstellen müssen, müssen wir es verwenden Die integrierte Funktion make() hat das folgende Format: 🎜rrreee🎜wobei: 🎜
  • T: der Elementtyp des Slice
  • Größe: die Anzahl der Elemente im Slice
  • li>
  • cap: Kapazität des Slice
rrreee🎜Im obigen Code 10 interne Speicherplätze von a wurden zugewiesen, aber nur 2 werden tatsächlich verwendet. Die Kapazität hat keinen Einfluss auf die aktuelle Anzahl der Elemente, daher gibt len(a) 2 zurück und cap(a) gibt die Kapazität des Slice zurück. 🎜

🎜5. Bestimmen Sie, ob das Slice leer ist. Die Essenz eines Slice besteht darin, das zugrunde liegende Array zu kapseln. Es enthält drei Informationen: den Zeiger des zugrunde liegenden Arrays und die Länge des Slice (len) und die Kapazität des Slice (cap). 🎜🎜Slices können nicht mit dem Operator == verglichen werden, um festzustellen, ob zwei Slices alle gleiche Elemente enthalten. Die einzige zulässige Vergleichsoperation für Slices ist mit nil. Ein Slice mit nil-Werten hat kein zugrunde liegendes Array und die Länge und Kapazität eines Slice mit nil-Werten sind beide 0. Aber wir können nicht sagen, dass ein Slice mit einer Länge und Kapazität von 0 nil sein muss, wie im folgenden Beispiel: 🎜rrreee🎜Um zu überprüfen, ob ein Slice leer ist, verwenden Sie immer len(s ) = = 0 statt s == nil. 🎜

🎜6. Zuweisungskopie des Slice 🎜🎜🎜Die Änderung eines Slice wirkt sich auf den Inhalt des anderen Slice aus besondere Aufmerksamkeit. 🎜rrreee

🎜7. Slice-Traversal 🎜🎜🎜Die Traversal-Methode von Slices ist die gleiche wie die von Arrays und unterstützt Index-Traversal und for range-Traversal . 🎜rrreee

🎜8.append()-Methode fügt Elemente zum Slice hinzu. 🎜🎜🎜Die integrierte Funktion append() der Go-Sprache kann Elemente dynamisch hinzufügen die Scheibe. Sie können jeweils ein Element, mehrere Elemente oder Elemente aus einem anderen Slice (gefolgt von ...) hinzufügen. 🎜rrreee🎜Durch var deklarierte nullwertige Slices können ohne Initialisierung direkt in der Funktion append() verwendet werden. 🎜
var s []ints = append(s, 1, 2, 3)

每个切片会指向一个底层数组,这个数组的容量够用就添加新增元素。当底层数组不能容纳新增的元素时,切片就会自动按照一定的策略进行“扩容”,此时该切片指向的底层数组就会更换。“扩容”操作往往发生在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]
}

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

copy(destSlice, srcSlice []T)

其中:

  • 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]
}

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]
}

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

结束:

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

【相关推荐:Go视频教程

Das obige ist der detaillierte Inhalt vonEin Artikel, der Slices in Golang kurz analysiert. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen