当前位置: 首页 > news >正文

网站建设中最重要的是什么玄圭互联网站建设推广

网站建设中最重要的是什么,玄圭互联网站建设推广,沈阳网站备案查询,保定市制作网站公司Slice slice 翻译成中文就是切片#xff0c;它和数组#xff08;array#xff09;很类似#xff0c;可以用下标的方式进行访问#xff0c;如果越界#xff0c;就会产生 panic。但是它比数组更灵活#xff0c;可以自动地进行扩容。 了解 slice 的本质, 最简单的方法就是…Slice slice 翻译成中文就是切片它和数组array很类似可以用下标的方式进行访问如果越界就会产生 panic。但是它比数组更灵活可以自动地进行扩容。 了解 slice 的本质, 最简单的方法就是看它的源码: // runtime/slice.go type slice struct {array unsafe.Pointer // 元素指针len int // 长度 cap int // 容量 } slice 共有三个属性: 指针 指向底层数组长度 表示切片可用元素的个数也就是说使用下标对 slice 的元素进行访问时下标不能超过 slice 的长度容量 底层数组的元素个数容量 长度。在底层数组不进行扩容的情况下容量也是 slice 可以扩张的最大限度。 注意: 底层数组是可以被多个 slice 同时指向的因此对一个 slice 的元素进行操作是有可能影响到其他 slice 的。 slice 创建 方式代码示例直接声明var slice []intnewslice : *new([]int)字面量slice : []int{1,2,3,4}makeslice : make(int[], 5, 10)从切片或者数组截取slice : array[1:5] 或 slice : sourceSlice[1:5] 直接声明 第一种创建出来的 slice 其实是一个 nil slice。它的长度和容量都为0。和nil比较的结果为true。 这里比较混淆的是empty slice它的长度和容量也都为0但是所有的空切片的数据指针都指向同一个地址 0xc42003bda0。空切片和 nil 比较的结果为false。 创建方式nil切片空切片方式一var s1 []intvar s2 []int{}方式二var s4 *new([]int)var s3 make([]int, 0)len00cap00和 nil 比较truefalse nil 切片和空切片很相似长度和容量都是0官方建议尽量使用 nil 切片。 关于nil slice和empty slice的探索可以参考 - 深度解析 Go 语言中「切片」的三种特殊状态 字面量 比较简单直接用初始化表达式创建。 package mainimport fmtfunc main() {s1 : []int{0, 1, 2, 3, 8: 100}fmt.Println(s1, len(s1), cap(s1)) }运行结果 [0 1 2 3 0 0 0 0 100] 9 9 唯一值得注意的是上面的代码例子中使用了索引号直接赋值这样其他未注明的元素则默认 0 值 make make 函数需要传入三个参数切片类型长度容量。当然容量可以不传默认和长度相等。 使用 make 关键字创建 slice: packge main import fmtfunc main(){// 长度为 5, 容量为 10slice : make(int[], 5, 10)// 索引为 2 的元素赋值为 2slice[2] 2 fmt.Println(slice) } 截取 截取也是比较常见的一种创建 slice 的方法可以从数组或者 slice 直接截取当然需要指定起止索引位置。 基于已有 slice 创建新 slice 对象被称为 reslice。新 slice 和老 slice 共用底层数组新老 slice 对底层数组的更改都会影响到彼此。 基于数组创建的新 slice 对象也是同样的效果对数组或 slice 元素作的更改都会影响到彼此。 值得注意的是新老 slice 或者新 slice 老数组互相影响的前提是两者共用底层数组如果因为执行 append 操作使得新 slice 底层数组扩容移动到了新的位置两者就不会相互影响了。所以问题的关键在于两者是否会共用底层数组。 截取操作采用如下方式 data : [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} // data[low, high, max] slice : data[2:4:6] 其他易错点 slice 和数组的区别在哪 slice 的底层数据是数组slice 是对数组的封装它描述一个数组的片段。两者都可以通过下标来访问单个元素。 数组是定长的长度定义好之后不能再更改。在 Go 中数组是不常见的因为其长度是类型的一部分限制了它的表达能力比如 [3]int 和 [4]int 就是不同的类型。 而切片则非常灵活它可以动态地扩容。切片的类型和长度无关。 append 到底做了什么 先来看看 append 函数的原型 func append(slice []Type, elems ...Type) []Type append 函数的参数长度可变因此可以追加多个值到 slice 中还可以用 … 传入 slice直接追加一个切片。 slice append(slice, elem1, elem2) slice append(slice, anotherSlice...)注: append函数返回值是一个新的sliceGo编译器不允许调用了 append 函数后不使用返回值。 slice 扩容 在分配内存空间之前需要先确定新的切片容量运行时根据切片的当前容量选择不同的策略进行扩容 大多数的文章都是这样描述的: 当原 slice 容量小于 1024 的时候新 slice 容量变成原来的 2 倍原 slice 容量超过 1024新 slice 容量变成原来的1.25倍。 其实结论不太准确的 为了说明上面的规律是错误的如下代码 package mainimport fmtfunc main() {s : make([]int, 0)oldCap : cap(s)for i : 0; i 2048; i {s append(s, i)newCap : cap(s)if newCap ! oldCap {fmt.Printf([%d - %4d] cap %-4d | after append %-4d cap %-4d\n, 0, i-1, oldCap, i, newCap)oldCap newCap}} }运行结果 [0 - -1] cap 0 | after append 0 cap 1 [0 - 0] cap 1 | after append 1 cap 2 [0 - 1] cap 2 | after append 2 cap 4 [0 - 3] cap 4 | after append 4 cap 8 [0 - 7] cap 8 | after append 8 cap 16 [0 - 15] cap 16 | after append 16 cap 32 [0 - 31] cap 32 | after append 32 cap 64 [0 - 63] cap 64 | after append 64 cap 128 [0 - 127] cap 128 | after append 128 cap 256 [0 - 255] cap 256 | after append 256 cap 512 [0 - 511] cap 512 | after append 512 cap 1024 [0 - 1023] cap 1024 | after append 1024 cap 1280 [0 - 1279] cap 1280 | after append 1280 cap 1696 [0 - 1695] cap 1696 | after append 1696 cap 2304在老 slice 容量小于1024的时候新 slice 的容量的确是老 slice 的2倍。目前还算正确。 但是当老 slice 容量大于等于 1024 的时候情况就有变化了。当向 slice 中添加元素 1280 的时候老 slice 的容量为 1280之后变成了 1696两者并不是 1.25 倍的关系1696/12801.325。添加完 1696 后新的容量 2304 当然也不是 1696 的 1.25 倍。 可见现在网上各种文章中的扩容策略并不正确。我们直接搬出源码源码面前了无秘密。 从前面汇编代码我们也看到了向 slice 追加元素的时候若容量不够会调用 growslice 函数所以我们直接看它的代码。 // go 1.9.5 src/runtime/slice.go:82 func growslice(et *_type, old slice, cap int) slice {// ……newcap : old.capdoublecap : newcap newcapif cap doublecap {newcap cap} else {if old.len 1024 {newcap doublecap} else {for newcap cap {newcap newcap / 4}}}// ……capmem roundupsize(uintptr(newcap) * ptrSize)newcap int(capmem / ptrSize) }看到了吗如果只看前半部分现在网上各种文章里说的 newcap 的规律是对的。现实是后半部分还对 newcap 作了一个内存对齐这个和内存分配策略相关。进行内存对齐之后新 slice 的容量是要 大于等于 老 slice 容量的 2倍或者1.25倍。 之后向 Go 内存管理器申请内存将老 slice 中的数据复制过去并且将 append 的元素添加到新的底层数组中。 为什么 nil slice 可以直接 append 其实 nil slice 或者 empty slice 都是可以通过调用 append 函数来获得底层数组的扩容。最终都是调用 mallocgc 来向 Go 的内存管理器申请到一块内存然后再赋给原来的nil slice 或 empty slice然后摇身一变成为“真正”的 slice 了。 总结 切片是对底层数组的一个抽象描述了它的一个片段。切片实际上是一个结构体它有三个字段长度容量底层数据的地址。多个切片可能共享同一个底层数组这种情况下对其中一个切片或者底层数组的更改会影响到其他切片。append 函数会在切片容量不够的情况下调用 growslice 函数获取所需要的内存这称为扩容扩容会改变元素原来的位置。扩容策略并不是简单的扩为原切片容量的 2 倍或 1.25 倍还有内存对齐的操作。扩容后的容量 原容量的 2 倍或 1.25 倍。当直接用切片作为函数参数时可以改变切片的元素不能改变切片本身想要改变切片本身可以将改变后的切片返回函数调用者接收改变后的切片或者将切片指针作为函数参数。 参考 深度解密Go语言之Slice
http://www.hkea.cn/news/14393890/

相关文章:

  • 宁夏建设投资集团公司网站147seo工具
  • 网站建立多少钱企业宣传片制作哪家好
  • 外网网站有什么好的推荐网站标题怎么做链接
  • 宁波网站建设信任蓉胜网络好华天动力oa系统
  • 网站图片特效源码纷享销客crm官网
  • 织梦网站被植入广告wordpress怎么开发
  • 电子商务网站建设项目的阶段下列( )是计算机网页制作工具
  • 湖南地税局官网站水利建设基金管理咨询公司取名
  • 高特效网站广州个人网站备案要多久
  • 网站建设教学改进c 企业网站开发
  • wordpress页面路径网站seo的主要优化内容
  • 互联网信息服务 网站备案卢沟桥做网站的公司
  • 网站建设流图visio北京网站建设找德冿朴
  • 网站建设价目表WordPress禁ua
  • 外贸网站建设的重要性武钢建设公司网站
  • 深圳高端网站电子商务网站建设与管理读后感
  • 网站开发时图片加载慢怎么解决广州网站推广平台
  • 内蒙古高等级公路建设开发有限责任公司网站杭州网站建设外包公司
  • 大型的营销型网站现在互联网创业可以做哪些项目
  • 做3d模型网站赚钱么注册代理公司
  • 黑龙江建设厅网站 孙宇传媒公司产品宣传片
  • 阿里云网站域名申请wordpress 4.8
  • 网站开发发展方向做app和做网站那个难
  • 一级a做爰小说免费网站襄城县城乡建设管理局网站
  • 网站开发的大致流程wordpress后台系统
  • 雄安建设集团有限公司网站asp网站背景
  • 代运网站网站制作费用是多少
  • 商城网站开发模板建设淘宝网站需要多少钱
  • 微网站教程网站建设与管理实训报告总结
  • 建设咖啡厅网站的意义网络平台建设怎么做