快上网建站品牌

13518219792
  • 首页
  • 关于我们
    • 如何选择
    • 选择理由
  • 案例作品
    • 网站建设
    • 优化推广
    • 微信开发
    • 电商托管
  • 服务项目
    • 网站建设
    • 移动端/APP
    • 微信/小程序
    • 技术支持
    • 其它服务
  • 建站知识
    • 成都网站建设
    • 成都做网站
    • 成都网站设计
  • 网站售后
    • 成都网站运营
    • 成都网站维护
    • 成都网站推广
  • 客服中心
  • 全国分站

你真的理解 Golang 切片吗?全切片表达式及切片使用技巧

简介

Golang 中通常的 slice 语法是 a[low:high],您可能很熟悉。还有另一种切片语法,形式为 a[low:high:max],它采用三个索引而不是两个索引。第三索引 max 是做什么的?

创新互联建站主要为客户提供服务项目涵盖了网页视觉设计、VI标志设计、成都全网营销推广、网站程序开发、HTML5响应式成都网站建设、手机网站开发、微商城、网站托管及网站维护公司、WEB系统开发、域名注册、国内外服务器租用、视频、平面设计、SEO优化排名。设计、前端、后端三个建站步骤的完善服务体系。一人跟踪测试的建站服务标准。已经为成都会所设计行业客户提供了网站制作服务。

提示: 不是 Python 切片语法 a[low:high:step] 中的 step 步长索引。

答: 第三个索引用于设置切片的容量!在 Golang 规范中称为 “全切片表达式”。

了解 Golang 切片

为了理解为什么要在 Golang 中加入这个功能,以及它的作用,让我们从数组和指针开始。

越界错误在 C 语言程序中很常见,Golang 通过内置的运行时边界检查器来缓解这个问题。数组的边界检查很简单,因为 Golang 的数组是固定长度的,然而,指针的边界检查就不那么简单了,因为指针的边界没有明确定义。Golang 中的切片只是解决指针的边界检查的一种方法。

Golang 不使用普通的指针来访问数组元素,而是用一个长度字段来扩充指针;结果(带长度的指针)被称为 "切片",或在其他地方称为 "胖指针"。有了长度字段,运行时的边界检查就很容易了。

Golang 的切片不仅仅是带长度的指针,它们还有一个 "容量 "字段,因为增加动态分配的数组是一个很常见的任务。分片的容量也作为分片表达式 a[low:high] 的边界检查器——切片的末端不能超过其容量。

理解 a[low:high:max]

切片索引表达式由长度字段进行边界检查,长度字段可以通过分片来减少,以提供所需的边界检查。

同样地,人们可能会想,是否有可能减少片断的容量,以加强对切片表达式 a[low:high] 的边界检查。例如,下面的表达式将一个切片的容量减少到它的长度:

a = a[0:len(a):len(a)]

在这之后,切片 a 被限制在它自己的范围内,切片结束后的元素不能被访问或修改,即使你不小心重新分片或追加到它上面。

这个技巧对于从不可改变的数组中返回一个切片很有用;如果你不小心追加到所谓的不可改变的切片中,就会强制复制,并且没有数据被覆盖,因为已经没有容量了。

这种形式的分片表达式在 Golang 规范中被称为 "完整分片表达式"(full slice expression)。

切片的使用技巧

定义切片:

type SeriesInt64 struct {
   values   []int64
}

自从引入内置的 append 以来,Go 1 中删除的 container/vector 包的大部分功能都可以使用 append 和 copy 来复制。

自从引入泛型以来,golang.org/x/exp/slices 包中提供了其中几个函数的泛型实现。

以下是矢量方法及其切片操作:

AppendVector

a = append(a, b...)

Copy

b := make([]T, len(a))
copy(b, a)

// These two are often a little slower than the above one,
// but they would be more efficient if there are more
// elements to be appended to b after copying.
b = append([]T(nil), a...)
b = append(a[:0:0], a...)

// This one-line implementation is equivalent to the above
// two-line make+copy implementation logically. But it is
// actually a bit slower (as of Go toolchain v1.16).
b = append(make([]T, 0, len(a)), a...)

封装成函数,可以这样写:

func (s *SeriesInt64) copy() *SeriesInt64 {
    if len(s.values) == 0 {
        return &SeriesInt64{
            values:[]int64{},
        }
    }
    // Copy slice
    x := s.values[0 : len(s.values)]
    newSlice := append(x[:0:0], x...)
    return &SeriesInt64{
        values: newSlice,
    }
}

Cut

a = append(a[:i], a[j:]...)

Delete

a = append(a[:i], a[i+1:]...)
// or
a = a[:i+copy(a[i:], a[i+1:])]

封装后:

func (s *SeriesInt64) remove(row int) {
    s.values = append(s.values[:row], s.values[row+1:]...)
}

Delete without preserving order

a[i] = a[len(a)-1] 
a = a[:len(a)-1]

NOTE 如果元素的类型是指针或带指针字段的结构体,需要进行垃圾回收,上述 Cut 和 Delete 的实现存在潜在的内存泄漏问题:一些有值的元素仍然被切片 a 引用,从而无法收集。下面的代码可以解决这个问题:

Cut

copy(a[i:], a[j:])
for k, n := len(a)-j+i, len(a); k < n; k++ {
 a[k] = nil // or the zero value of T
}
a = a[:len(a)-j+i]

Delete

copy(a[i:], a[i+1:])
a[len(a)-1] = nil // or the zero value of T
a = a[:len(a)-1]

Delete without preserving order

a[i] = a[len(a)-1]
a[len(a)-1] = nil
a = a[:len(a)-1]

Expand

Insert n elements at position i:

a = append(a[:i], append(make([]T, n), a[i:]...)...)

Extend

Append n elements:

a = append(a, make([]T, n)...)

Extend Capacity

Make sure there is space to append n elements without re-allocating:

if cap(a)-len(a) < n {
 a = append(make([]T, 0, len(a)+n), a...)
}

Filter (in place)

n := 0
for _, x := range a {
 if keep(x) {
  a[n] = x
  n++
 }
}
a = a[:n]

Insert

a = append(a[:i], append([]T{x}, a[i:]...)...)

注意:第二个追加创建一个新的切片,它有自己的底层存储,并将 a[i:] 中的元素复制到该切片,然后这些元素被复制回切片 a(由第一个追加)。使用替代方法可以避免创建新切片(以及内存垃圾)和第二个副本:

Insert

s = append(s, 0 /* use the zero value of the element type */)
copy(s[i+1:], s[i:])
s[i] = x

封装后:

func (s *SeriesInt64) insert(row int, val int64) {
    s.values = append(s.values, 0)
    copy(s.values[row+1:], s.values[row:])
    s.values[row] = val
}

InsertVector

a = append(a[:i], append(b, a[i:]...)...)

// The above one-line way copies a[i:] twice and
// allocates at least once.
// The following verbose way only copies elements
// in a[i:] once and allocates at most once.
// But, as of Go toolchain 1.16, due to lacking of
// optimizations to avoid elements clearing in the
// "make" call, the verbose way is not always faster.
//
// Future compiler optimizations might implement
// both in the most efficient ways.
//
// Assume element type is int.
func Insert(s []int, k int, vs ...int) []int {
 if n := len(s) + len(vs); n <= cap(s) {
  s2 := s[:n]
  copy(s2[k+len(vs):], s[k:])
  copy(s2[k:], vs)
  return s2
 }
 s2 := make([]int, len(s) + len(vs))
 copy(s2, s[:k])
 copy(s2[k:], vs)
 copy(s2[k+len(vs):], s[k:])
 return s2
}

a = Insert(a, i, b...)

Push

a = append(a, x)

Pop

x, a = a[len(a)-1], a[:len(a)-1]

Push Front/Unshift

a = append([]T{x}, a...)

Pop Front/Shift

x, a = a[0], a[1:]

Prepending

func (s *SeriesInt64) prepend(val int64) {
    if cap(s.values) > len(s.values) {
        s.values = s.values[:len(s.values)+1]
        copy(s.values[1:], s.values)
        s.values[0] = val
        return
    }
    // No extra capacity so a new slice needs to be allocated:
    s.insert(0, val)
}

图片来源:

  • Go Slice Tricks Cheat Sheet

当前标题:你真的理解 Golang 切片吗?全切片表达式及切片使用技巧
文章转载:http://www.gydahua.com/article/cocijdi.html
扫二维码与项目经理沟通

我们在微信上24小时期待你的声音

解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流

其他资讯

  • 如何鉴别ps图片的真假
  • 微信公众平台认证需要多久?(微信公众平台认证需要多久时间)
  • Oracle 11g数据库默认审计选项说明详解
  • 虚拟主机租用情况
  • 光纤双路由什么意思(光纤双纤)

行业动态

企业网站建设的重要性!

现在虽然是移动互联网时代,但企业网站依然重要,包含PC站点,移动站。可以说企业网站关系企业的未来发展和前途,尤其对中小企业更是如此,一些中小企业老板,对自己的名片很在乎,因为这是个门面。...

服务项目

  • 网站建设

    查看详情
  • 移动端/APP

    查看详情
  • 微信/小程序

    查看详情
  • 技术支持

    查看详情
  • 其它服务

    查看详情
  • 更多服务项目

    用我们的专业和诚信赢得您的信赖,从PC到移动互联网均有您想要的服务!

    获取更多

联系吧 在百度地图上找到我们

电话:13518219792

如遇占线或暂未接听请拨:136xxx98888

业务咨询 技术咨询 售后服务
网站设计
成都网站设计
外贸网站设计方案
高端网站设计
成都企业网站设计
网站制作
成都网站制作
网站制作公司
成都网站制作
企业网站制作
联系我们
电话:13518219792
邮箱:631063699@qq.com
地址:成都青羊区锦天国际1002号
网址:www.gydahua.com
网站建设
南充网站建设
成都企业网站建设
成都集团网站建设
成都定制网站建设

微信二维码

  • 友情链接
  • 成都网站建设
  • 域名注册
  • 成都品牌全案策划
  • 成都响应式网站建设公司
  • 四川搅拌罐车
  • 云服务器
  • 广汉锦华
  • 成都纯化水设备
  • 成都门头发光字设计
  • 四川沃尔沃发电机

Copyright © 2002-2023 www.gydahua.com 快上网建站品牌 QQ:244261566 版权所有 备案号:蜀ICP备19037934号

  • 在线咨询
  • 13518219792
  • 微信二维码

  • 移动版官网