Go言語の基礎とスライスの補足を理解するための記事
make を渡すことができることはわかっています。 スライスを作成します。
var names = make([]string,10,10)
この文は、スライスが動的に作成されることを意味し、スライスの要素数は 10 で、スライスの容量も 10 です。
混乱していませんか???
スライスの数と容量は何ですか? ? ?
彼らの関係は何ですか? ? ?
スライスの本質
実際、スライスとは、データを保存する方法がすべてです。 1 つ目は、配列が物を保存できることを現在知っていることです。
其实切片的本质,还是数组,只不过是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 }
理解图。
没错,本质就是指向了一个长一点的数组。
但是这个数组是会自动扩容的,当容量(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] }
append之后,前面会有很多0,这是怎么回事。
解释:
在通过make创建切片时,第二个参数是切片元素的数量。
上述代码切片第二个参数是5,表示在创建切片时,前5个就已经有值了,只不过是int默认值0。
所以再append时,是再原有的基础上,添加值的,直到cap满了之后,触发扩容机制。
如图所示。
现在,清晰了吧?
那怎么append时,从0开始呢???
这不是很简单,直接让第二个参数为0。
var names = make([]int,0,10) //结果:[11 23 231]
如图所示。
好了,这个,懂了吧,怎么继续哈。
为什么不推荐使用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)) }
虽然按照这种方法,使用append动态添加是没问题的。
在不使用make声明数组时,len和cap都是0,并且地址也是一个值。
通过append之后,可以明显看到,地址发生了改变,因为又重新申请了数组,切片重新指向新的数组。
len和cap也发生了变化。
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的值???? }
为什么修改names1的值,会影响names2的值???
これで、図に示すメモリ分布図に戻ります。
印刷であれ、割り当てであれ、操作するのは スタック# だけであると何度も述べてきました。 ## 上に保存されている 値。
#names2=names1 の場合、 #names1# のみ##スタック上のアドレスは
names2 に与えられます。
しかし、保存するとき、ヒープ上のアドレスは依然として同じヒープを指します。
#したがって、
names1、names2# を変更する場合# も変更されました。
解決策: コピーを使用します
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 }
内存图
自动扩容机制
非常抱歉,我不会。。。
以上がGo言語の基礎とスライスの補足を理解するための記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Go Crawler Collyのキュースレッドの問題は、Go言語でColly Crawler Libraryを使用する問題を調査します。 �...

大企業または有名なオープンソースプロジェクトによって開発されたGOのどのライブラリが開発されていますか? GOでプログラミングするとき、開発者はしばしばいくつかの一般的なニーズに遭遇します...

GO言語で構造を定義する2つの方法:VARとタイプのキーワードの違い。構造を定義するとき、GO言語はしばしば2つの異なる執筆方法を見ます:最初...

Go言語での文字列印刷の違い:printlnとstring()関数を使用する効果の違いはGOにあります...

redisstreamを使用してGo言語でメッセージキューを実装する問題は、GO言語とRedisを使用することです...

Golandのカスタム構造ラベルが表示されない場合はどうすればよいですか?ゴーランドを使用するためにGolandを使用する場合、多くの開発者はカスタム構造タグに遭遇します...

ポインター構文とviperライブラリの使用における問題への取り組みGO言語でプログラミングするとき、特にポインターの構文と使用を理解することが重要です...
