Heim > Backend-Entwicklung > Golang > Ein Artikel, der Ihnen hilft, die Grundlagen der Go-Sprache und der Slicing-Ergänzung zu verstehen

Ein Artikel, der Ihnen hilft, die Grundlagen der Go-Sprache und der Slicing-Ergänzung zu verstehen

Freigeben: 2023-07-20 14:55:46
nach vorne
1015 Leute haben es durchsucht
make

Wir wissen, dass Slices mit make erstellt werden können.

var names = make([]string,10,10)
Nach dem Login kopieren

Dieser Satz bedeutet, dass ein Slice dynamisch erstellt wird. Die Anzahl der Elemente im Slice beträgt 10 und die Kapazität des Slice beträgt ebenfalls 10.

Sind Sie verwirrt???

Was ist die Anzahl und Kapazität der Scheiben? ? ?

In welcher Beziehung stehen sie zueinander? ? ?


Die Essenz des Slicings

Tatsächlich ist Slicing eine Sache, die Daten speichert. Derzeit ist bekannt, dass Arrays Dinge speichern können.

其实切片本质,还是数组,只不过是Go帮助我们做了一些封装,可以方便的对切片里面的数据增删改查

例如:

package main

import "fmt"

func main() {
    var names = make([]int, 4, 10)
    //int类型默认值是0
    fmt.Println(names, len(names), cap(names)) //结果:[0 0 0 0] 4 10
}
Nach dem Login kopieren

理解图。

Ein Artikel, der Ihnen hilft, die Grundlagen der Go-Sprache und der Slicing-Ergänzung zu verstehen

没错,本质就是指向了一个长一点的数组。

但是这个数组是会自动扩容的,当容量(cap)append满了之后,会自动扩容。

现在,我们就知道make里面参数的意义了。

注意:在Go中,推荐使用make创建切片,并且在创建时,需要考虑容量,尽可能不触发容量自动扩容机制,提高性能。


为什么切片append之后,前面会有空格

在上一章中,大概有这样一段代码。

package main

import "fmt"

func main() {
    var names = make([]int,5,10)
    names = append(names,11,23,231)
    fmt.Println(names)//[0 0 0 0 0 11 23 231]
}
Nach dem Login kopieren

append之后,前面会有很多0,这是怎么回事。

解释:

在通过make创建切片时,第二个参数切片元素数量

上述代码切片第二个参数是5,表示在创建切片时,前5个就已经有值了,只不过是int默认值0。

所以再append时,是再原有的基础上,添加值的,直到cap满了之后,触发扩容机制。

如图所示。

Ein Artikel, der Ihnen hilft, die Grundlagen der Go-Sprache und der Slicing-Ergänzung zu verstehen

现在,清晰了吧?

那怎么append时,从0开始呢???

这不是很简单,直接让第二个参数为0。

var names = make([]int,0,10)
//结果:[11 23 231]
Nach dem Login kopieren

如图所示。

Ein Artikel, der Ihnen hilft, die Grundlagen der Go-Sprache und der Slicing-Ergänzung zu verstehen

好了,这个,懂了吧,怎么继续哈。


为什么不推荐使用var []类型方式创建切片

我们上述一直在提一个词,自动扩容

我们来看这样一段普通的代码。

package main

import "fmt"

func main() {
    var names []int
    //地址:0x0,长度(len):0,容量(cap):0
    fmt.Printf("地址:%p,长度(len):%d,容量(cap):%d\n", names, len(names), cap(names))
    names = append(names, 1, 2, 3)

    //地址:0xc000010380,长度(len):3,容量(cap):4
    fmt.Printf("地址:%p,长度(len):%d,容量(cap):%d\n", names, len(names), cap(names))
}
Nach dem Login kopieren

虽然按照这种方法,使用append动态添加是没问题的。

在不使用make声明数组时,lencap都是0,并且地址也是一个值。

通过append之后,可以明显看到,地址发生了改变,因为又重新申请了数组,切片重新指向新的数组。

lencap也发生了变化。


copy复制切片

package main

import "fmt"

func main() {
    var names1 = make([]string, 0, 10)
    names1 = append(names1, "张三")
    names1 = append(names1, "李四")
    var names2 = names1         //将names1赋值到names2
    fmt.Println(names1, names2) //[张三 李四] [张三 李四]
    names1[0] = "张三666"//修改names下标为0的值为 张三666
    fmt.Println(names1, names2) //[张三666 李四] [张三666 李四]
    //为什么修改names1的值,会影响names2的值????
}
Nach dem Login kopieren

为什么修改names1的值,会影响names2的值???

Damit kommen wir zurück zum Speicherverteilungsdiagramm, wie im Bild gezeigt.

Ein Artikel, der Ihnen hilft, die Grundlagen der Go-Sprache und der Slicing-Ergänzung zu verstehen

Wir haben oft gesagt, dass unabhängig davon, ob es sich um Druck-, Zuweisungs- oder andere Vorgänge handelt, nur der auf dem Stapel gespeicherte Wert bearbeitet wird. whennames2=names1</ Wenn Code><br/></p>, nur <p cid="n127" mdtype="paragraph" style="line-height: inherit;orphans: 4;margin-top: 0.8em;margin-bottom: 0.8em;white-space: pre-wrap;font-family: "Open Sans", "Clear Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;font-size: 16px;text-align: start;"><span md-inline="plain"><code style="font-family: var(--monospace);vertical-align: initial;border-width: 1px;border-style: solid;border-color: rgb (231 , 234, 237);Hintergrundfarbe: rgb(243, 244, 244);Rahmenradius: 3px;Padding-rechts: 2px;Padding-links: 2px;Schriftgröße: 0,9em;">Namen1< /code ></span><span md-inline="code" spellcheck="false">Die Adresse über dem Stapel, geben Sie <code style="font-family: var(--monospace);vertical-align: initial;border-width: 1px;border-style: solid;border-color: rgb(231, 234, 237);background-color: rgb(243, 244, 244);border-radius: 3px;padding-right: 2px;padding-left: 2px;font-size: 0.9em;">names2=names1时,只会把names1栈上面的地址,给names2

但是存的时堆上面的地址,终究还是指向了同一个堆。

所以修改names1时,names2 Namen2 .

Also ändernnames1Wenn

,

names2 wurde ebenfalls geändert.

🎜🎜🎜🎜🎜🎜Was ist, wenn das oben genannte Problem nicht auftreten soll???🎜🎜🎜🎜🎜🎜Lösung: Kopieren verwenden🎜🎜🎜
package main

import "fmt"

func main() {
    var names1 = make([]string, 0, 10)
    names1 = append(names1, "张三")
    names1 = append(names1, "李四")
    //定义一个names2切片用于接收,第二个参数要留空间,names1里面又几个元素,names2第二个参数也要是几
    var names2 = make([]string, 2, 10)
    copy(names2, names1)//将names1的值,赋值到names2
    fmt.Println(names1, names2) //[张三 李四] [张三 李四]
    names1[0] = "张三666"//修改names下标为0的值为 张三666
    fmt.Println(names1, names2) //[张三666 李四] [张三 李四]
    fmt.Printf("names1地址:%p names2地址:%p\n",names1,names2)
    //names1地址:0xc00009a0a0 names2地址:0xc00009a140
}
Nach dem Login kopieren

内存图

Ein Artikel, der Ihnen hilft, die Grundlagen der Go-Sprache und der Slicing-Ergänzung zu verstehen

自动扩容机制

非常抱歉,我不会。。。


Das obige ist der detaillierte Inhalt vonEin Artikel, der Ihnen hilft, die Grundlagen der Go-Sprache und der Slicing-Ergänzung zu verstehen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:Go语言进阶学习
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage