教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 Golang学习笔记一Slice篇

Golang学习笔记一Slice篇

发布时间:2022-01-12   编辑:jiaochengji.com
教程集为您提供Golang学习笔记一Slice篇等资源,欢迎您收藏本站,我们将为您提供最新的Golang学习笔记一Slice篇资源
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"/></svg><h1>1. 从数组说起</h1>

  数组是具有固定长度具有零个或者多个相同数据类型元素的序列。

  由于数组长度固定,在Go里很少直接使用。

<h2>
1.1 定义数组</h2> <pre><code class="lang-go hljs"><span class="token comment">// 3种方式,声明,初始,省略号</span> <span class="token comment">// 变量arr1类型为[5]int</span> <span class="token keyword">var</span> arr1 <span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span><span class="token builtin">int</span> <span class="token comment">// 变量arr2类型为[3]int,同时初始化赋值</span> <span class="token keyword">var</span> arr2 <span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span><span class="token builtin">int</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> <span class="token comment">// 让编译器自己数,结果为[3]int</span> arr3 <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> <span class="token comment">// 错误例子,因为[3]int和[4]int是两种类型</span> arr3 <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">}</span> </code></pre> <ul><li>数组长度是数组类型的一部分,<code>[3]int</code>和<code>[5]int</code>就是两种类型。</li><li>数组长度必须是常量表达式,即这个表达式的值在编译阶段就可以确定。</li></ul><h2>1.2 查看数组基本信息</h2> <ul><li>Go内置函数len,可以返回数组中元素个数。</li></ul><pre><code class="lang-go hljs">arr1 <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> lenth <span class="token operator">:=</span> <span class="token function">len</span><span class="token punctuation">(</span>arr1<span class="token punctuation">)</span> </code></pre> <h2>1.3 数组遍历</h2> <ul><li>数组中的每个元素是通过index来访问的。</li></ul><pre><code class="lang-go hljs">arr1 <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> <span class="token keyword">for</span> i<span class="token punctuation">,</span>val <span class="token operator">:=</span> <span class="token keyword">range</span> arr1 <span class="token punctuation">{</span> <span class="token punctuation">}</span> </code></pre> <h2>1.4 数组作为函数参数</h2> <ul><li>

数组是值类型,值类型意味着拷贝。

</li><li>

注意!!!在其他语言中,数组是隐式的使用引用传递;Golang传参时,传入的参数会创建一个副本,使用这种方式传递大的数组会变的很低效。

</li><li>

可以显式的给函数传递一个数组的指针。

</li></ul><pre><code class="lang-go hljs"><span class="token comment">// 1. 遍历数组,将数组中元素清零</span> fun zero <span class="token punctuation">(</span>ptr <span class="token operator">*</span><span class="token punctuation">[</span><span class="token number">32</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">for</span> i <span class="token operator">:=</span> <span class="token keyword">range</span> ptr <span class="token punctuation">{</span> ptr<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// 2. 利用数组指针,将数组元素清零</span> <span class="token keyword">func</span> zero <span class="token punctuation">(</span>ptr <span class="token operator">*</span><span class="token punctuation">[</span><span class="token number">32</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token operator">*</span>ptr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">32</span><span class="token punctuation">]</span><span class="token builtin">byte</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre> <h2>
1.5 数组比较</h2> <ul><li>如果一个数组中的元素是可比较的,那么数组也是可比较的</li><li>可以直接使用==和!=比较两个数组</li></ul><pre><code class="lang-go hljs">a <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">}</span> <span class="token comment">// [2]int类型</span> b <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">}</span> <span class="token comment">// [2]int类型</span> c <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">}</span> <span class="token comment">// [2]int类型</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a<span class="token operator">==</span>b<span class="token punctuation">,</span>a<span class="token operator">==</span>c<span class="token punctuation">,</span>b<span class="token operator">==</span>c<span class="token punctuation">)</span> <span class="token comment">// true,false,false</span> d <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">}</span> <span class="token comment">// [3]int类型</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span>a <span class="token operator">==</span> d<span class="token punctuation">)</span> <span class="token comment">// 编译错误:不能比较[2]int和[3]int</span> </code></pre> <h1>2. 切片</h1>

  切片用于表示一个拥有相同类型元素可变长的序列,看上去像是没有长度的数组类型。

<h2>
2.1 定义Slice</h2>

  通过数组定义

<pre><code class="lang-go hljs"><span class="token comment">// 定义一个数组</span> arr <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token number">6</span><span class="token punctuation">,</span><span class="token number">7</span><span class="token punctuation">}</span> <span class="token comment">// 根据数组,定义该数组的view,即slice</span> s <span class="token operator">:=</span> arr<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">:</span><span class="token number">6</span><span class="token punctuation">]</span> <span class="token comment">// s={2,3,4,5},左开右闭</span> <span class="token comment">// s就是一个切片,它是数组arr的一个视图</span> <span class="token comment">// 总结来说,一个数组取它的slice,使用slice操作符arr[:]即可,看的是底层数组的全部景象</span> </code></pre>

  直接定义切片

<pre><code class="lang-go hljs"><span class="token keyword">var</span> s1 <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span> s2 <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">}</span> s3 <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">6</span><span class="token punctuation">)</span> <span class="token comment">// 默认len == cap == 6</span> s4 <span class="token operator">:=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">10</span><span class="token punctuation">,</span><span class="token number">32</span><span class="token punctuation">)</span> <span class="token comment">// len == 10 ,cap == 32</span> </code></pre> <h2>
2.2 查看切片基本信息</h2> <ul><li>Go内置函数len和cap,用来返回slice的长度和容量。</li></ul><pre><code class="lang-go hljs"><span class="token comment">// 定义一个数组</span> arr <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token operator">...</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token number">6</span><span class="token punctuation">,</span><span class="token number">7</span><span class="token punctuation">}</span> <span class="token comment">// 根据数组,定义该数组的view,即slice</span> s <span class="token operator">:=</span> arr<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">:</span><span class="token number">6</span><span class="token punctuation">]</span> <span class="token comment">// s={2,3,4,5},左开右闭</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">len</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// len(s) == 4 (2-5)</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token function">cap</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// cap(s) == 6 (2-7)</span> </code></pre> <ul><li>判断slice是否为空。</li></ul><pre><code class="lang-go hljs"><span class="token comment">// slice 不能使用 == 操作符来比较两个切片元素是否相等</span> <span class="token comment">// 唯一允许的比较操作是和nil作比较</span> <span class="token comment">// 但是,slice为nil的情况有很多种</span> <span class="token keyword">var</span> s <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span> <span class="token comment">// len(s) == 0, s == nil</span> s <span class="token operator">=</span> <span class="token boolean">nil</span> <span class="token comment">// len(s) == 0, s == nil</span> s <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token boolean">nil</span><span class="token punctuation">}</span> <span class="token comment">// len(s) == 0, s == nil</span> s <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// len(s) == 0, s!=nil</span> <span class="token comment">// 所以一般情况不用 s == nil来判断slice是否为空,而是使用len(s) == 0来判断</span> </code></pre> <h2>2.3 切片相关操作</h2> <ul><li>切片遍历在语法上和数组是相似的</li></ul><pre><code class="lang-go hljs"><span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span>s <span class="token operator">:=</span> <span class="token keyword">range</span> s1 <span class="token punctuation">{</span> <span class="token punctuation">}</span> </code></pre> <ul><li>append()函数追加元素</li></ul><pre><code class="lang-go hljs"><span class="token comment">// 使用append追加元素可以超过capacity,它会触发slice底层数组的扩容机制</span> <span class="token comment">// 扩容就是重新分配长度更大的底层数组,原来的数组就会进行垃圾回收</span> <span class="token comment">// 由于值传递的关系,必须要使用一个新的slice接收append的返回值</span> <span class="token comment">// append的时候,ptr,len,cap有可能都会发生变化,必须接收新的ptr,len和cap</span> s <span class="token operator">:=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">{</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">}</span> s <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>s<span class="token punctuation">,</span>val<span class="token punctuation">)</span> <span class="token comment">// 下面的一种操作,可以达到删除slice中元素的目的</span> <span class="token comment">// ...表示变长参数列表,追加s[4:]切片后所有元素</span> s <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>s<span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span>s<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token operator">...</span><span class="token punctuation">)</span> <span class="token comment">// append是从切片的len,向后进行扩展的操作</span> <span class="token keyword">var</span> ints <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span> <span class="token operator">=</span> <span class="token function">make</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">int</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">)</span> <span class="token comment">// len=2,cap=5</span> <span class="token comment">// 底层数组:0 0 0 0 0</span> ints <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>ints<span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">// len=3,cap=5 </span> <span class="token comment">// 底层数组:0 0 1 0 0</span> </code></pre> <h2>2.4 切片作为函数参数</h2> <ul><li>所谓切片是引用类型,是指切片作为函数的参数,操作的是同一个底层数组。</li></ul><pre><code class="lang-go hljs"><span class="token keyword">func</span> <span class="token function">nonempty</span><span class="token punctuation">(</span>strings <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token builtin">string</span> <span class="token punctuation">{</span> i <span class="token operator">:=</span> <span class="token number">0</span> <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> s <span class="token operator">:=</span> <span class="token keyword">range</span> strings <span class="token punctuation">{</span> <span class="token keyword">if</span> s <span class="token operator">!=</span> <span class="token string">""</span> <span class="token punctuation">{</span> strings<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> s i<span class="token operator"> </span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> strings<span class="token punctuation">[</span><span class="token punctuation">:</span>i<span class="token punctuation">]</span> <span class="token punctuation">}</span> </code></pre> <h1>3. 面试</h1> <h2>3.1. 数组和切片</h2> <h3>3.1.1. 数组</h3> <ol><li>Go中的数组是值类型,换句话说,如果你将一个数组赋值给另外一个数组,那么,实际上就是将整个数组拷贝一份</li><li>如果Go中的数组作为函数的参数,那么实际传递的参数是一份数组的拷贝,而不是数组的指针。</li></ol><h3>3.1.2. 切片</h3> <ol><li>切片是引用类型,因此在当传递切片时将引用同一指针,修改值将会影响其他的对象。</li><li>切片可能会在堆上分配内存,本身不是动态数组或者数组指针,内部是通过指针引用底层数组,切片本身是一个只读对象,本身没有数据,底层数组才有数据,类似于数组指针的一种封装,是引用类型</li><li>当使用for range 遍历slice的时候,拿到的value其实是切片的值拷贝,每次打印出来的value地址不变</li><li>slice扩容时,当cap小于1024的时候,每次扩容都会变成原来容量的2倍;当大于1024的时候,每次变为之前的1.25倍</li></ol><h3>3.1.3. 切片扩容</h3> <ol><li>预估扩容后的newCap</li></ol><pre><code class="lang-go hljs"><span class="token comment">// 预估规则:</span> <span class="token keyword">if</span> oldCap <span class="token operator">*</span> <span class="token number">2</span> <span class="token operator"><</span> newCap 直接分配内存 <span class="token keyword">else</span> <span class="token keyword">if</span> oldLen <span class="token operator"><</span> <span class="token number">1024</span> newCap <span class="token operator">=</span> oldCap <span class="token operator">*</span> <span class="token number">2</span> <span class="token keyword">if</span> oldLen <span class="token operator">></span> <span class="token number">1024</span> newCap <span class="token operator">=</span> oldCap <span class="token operator">*</span><span class="token number">1.25</span> </code></pre> <ol start="2"><li>newCap个元素需要多大的内存?</li></ol><pre><code class="lang-go hljs"><span class="token comment">// 预估到的newCap只是扩容后元素的个数,具体分配多大的内存呢?</span> <span class="token comment">// newCap * sizeof(T)吗?</span> <span class="token comment">// 事实上,许多编程语言中,申请分配内存,并不是直接和操作系统交涉,而是和语言自身实现的内存管理模块。内存管理模块会提前申请一批常用的内存,管理起来,需要申请 内存时内存管理模块会帮我们匹配到最接近的规格</span> </code></pre> <ol start="3"><li>匹配到合适的内存规格</li></ol><h2>3.2 切片为什么叫切片?与Java中动态数组有区别吗?</h2> <pre><code class="lang-go hljs">TODO<span class="token punctuation">:</span> 以java 中StringBuffer和ArrayList为例作比较 </code></pre> 到此这篇关于“Golang学习笔记一Slice篇”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
想系统学习GO语言(Golang
Go: 学习笔记1 让编程更有乐趣
go语言学习笔记(第3章)—面向对象编程
Golang中对interface{}做type assertion和type switch学习笔记
Go语言内存分配机制
Golang笔记:语法,并发思想,web开发,Go微服务相关
Go 语言数据类型:byte、rune与字符串
Go 学习笔记 07 | 指针详解
学习golang开始前的准备工作
Golang学习笔记(五):Go语言与C语言的区别

[关闭]
~ ~