返回顶部
首页 > 资讯 > 后端开发 > GO >深入理解go slice结构
  • 693
分享到

深入理解go slice结构

2024-04-02 19:04:59 693人浏览 泡泡鱼
摘要

文章 slice介绍 append的机制 slice tricks Go data slice array的语法: [4]int{1,2,3,4}, [...]int{1,2,

文章

slice介绍

append的机制

slice tricks

Go data

slice

array的语法: [4]int{1,2,3,4}, [...]int{1,2,3}。在go中array是值类型,这就意味着一个类型为array的变量名并不是一个指针,当传递值是,array总是被复制。

slice的语法: []int{1,2,3,4}, make([]int), make([]int,10)

当make只有两个参数时,cap和len相同。

slice本质上是array的一个片段的描述,它包含3部分:
[ptr, len, cap]

通过make([]int, 5)创建的slice,其内存布局如下:

在这里插入图片描述

对这个slice进行截断之后,形成新的slice:

在这里插入图片描述

使用cap可以对slice进行扩增: s[:cap(s)].

copy(dst, src []T) int的用法: copy会复制dst和src中长度最小的元素所对应的数量(所以如果dst==nil, 则copy返回0)。并且,copy还能处理dst和src存在重叠的情况。
用法:


t := make([]byte, len(s), (cap(s)+1)*2)
copy(t, s)
s = t

append(dst []T, element...T) []T的实现,与下面的AppendByte类似:
首先检查容量,容量不足则使用make构造一个新的slice并将原来的元素移动。


func AppendByte(slice []byte, data ...byte) []byte {
    m := len(slice)
    n := m + len(data)
    if n > cap(slice) { // if necessary, reallocate
        // allocate double what's needed, for future growth.
        newSlice := make([]byte, (n+1)*2)
        copy(newSlice, slice)
        slice = newSlice
    }
    slice = slice[0:n]
    copy(slice[m:n], data)
    return slice
}

slice对GC的影响(gotcha)

如果对一个很大的数组,取其中很小的一段切片,都会造成这个数组不会被gc回收。
gc使用mark-and-sweep(标记清除)。gc维护一个已分配的堆对象表,在标记阶段,它将寄存器,堆栈上的指针作为root进行遍历标记。

为什么部分slice会导致整体的array不会回收呢?设想下面的slice:


a := [4]int{0,1,2,3}
s := a[1:2] // {1}
return s

a会不会被回收呢?答案是不会,因为gc遍历s时,通过data指针找到对应的array切片,它发现这个地址在之前分配的一个array对象的范围内,从而标记这个array为可到达对象,避免其被整个清除。(这里所要理解的就是array是按范围标记的,并不是按指针头标记的,因为一个内存块对象是有范围的,如果被部分引用,说明整个对象仍然是可达的。)

如何解决?如果是这种情况,一个较大array返回较小切片,可以使用复制:

before:


var digitRegexp = regexp.MustCompile("[0-9]+")

func FindDigits(filename string) []byte {
    b, _ := ioutil.ReadFile(filename)
    return digitRegexp.Find(b)
}

after:


func CopyDigits(filename string) []byte {
    b, _ := ioutil.ReadFile(filename)
    b = digitRegexp.Find(b)
    c := make([]byte, len(b))
    copy(c, b)
    return c
}

reflect.SliceHeader


package reflect

// SliceHeader和StringHeader具有相同的Data和Len,这导致[]byte可以直接转换成string,而不需要任何复制
type SliceHeader struct {
	Data uintptr
	Len  int
	Cap  int
}
type StringHeader struct {
	Data uintptr
	Len  int
}

转换代码:


func SliceByteAsString(b []byte) string {
    return *(*string)(unsafe.Pointer(&b))
}
func StringAsSliceByte(s string) []byte {
    p := unsafe.Pointer(&d)
    var b []byte
    hdr :=  (*reflect.SliceHeader)(unsafe.Pointer(&b))
    hdr.Data = uintptr(p)
    hdr.Cap = len(s)
    hdr.Len = len(s)
    return b
}

func Int64AsByteSlice(d int64) []byte {
    p := unsafe.Pointer(&d)
    var b []byte
    hdr :=  (*reflect.SliceHeader)(unsafe.Pointer(&b))
    hdr.Data = uintptr(p)
    hdr.Cap = 8
    hdr.Len = 8
    return b
}

到此这篇关于go slice结构的文章就介绍到这了,更多相关go slice结构内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: 深入理解go slice结构

本文链接: https://lsjlt.com/news/135686.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 深入理解go slice结构
    文章 slice介绍 append的机制 slice tricks go data slice array的语法: [4]int{1,2,3,4}, [...]int{1,2,...
    99+
    2024-04-02
  • 深入了解Go语言结构体
    Go语言作为一种快速、简洁、并发的编程语言,结构体(struct)是其重要的数据结构之一。结构体允许我们将不同类型的数据组合在一起,形成一个更为复杂的自定义数据类型。本文将深入探讨Go...
    99+
    2024-03-10
    go语言 结构体 深入
  • 深入解析Go语言的语法结构
    Go语言作为一种开源的静态类型编程语言,在近年来受到越来越多开发者的青睐。其简洁的语法结构和高效的编译速度,使得它在云计算、大数据、网络编程等领域有着广泛的应用。本文将深入解析Go语言...
    99+
    2024-04-02
  • Java Swing的层次结构深入理解
    目录Java Swing的层次结构什么是Java SwingSwing组件的层次结构关于三层组件Java Swing基础(层次结构,组件,布局管理)Swing基础层次结构Swing ...
    99+
    2024-04-02
  • 深入理解Golang Channel 的底层结构
    目录make chan发送和接收Goroutine Pause/Resumewait empty channelGolang 使用 Groutine 和 channels 实现了 C...
    99+
    2024-04-02
  • 深入理解Java虚拟机 JVM 内存结构
    目录前言JVM是什么JVM内存结构概览运行时数据区程序计数器Java虚拟机栈本地方法栈方法区运行时常量池Java堆直接内存前言 JVM是Java中比较难理解和掌握的一部分,也是面试中...
    99+
    2024-04-02
  • 深入理解JavaScript中的语法和代码结构
    目录概述功能性和可读性空白括弧分号缩进身份标识区分大小写保留关键字概述 所有编程语言都必须遵守特定的规则才能运行。 确定编程语言的正确结构的这组规则称为语法。 许多编程语言主要由具有...
    99+
    2024-04-02
  • 深入浅出理解C语言初识结构体
    目录1.定义和使用结构体变量结构体的基础知识自己建立结构体类型struct 结构体名类型名 成员名:声明结构体的形式结构体的初始化  2. 结构体成员的访问3.结构体传参1...
    99+
    2024-04-02
  • Java 数据结构深入理解ArrayList与顺序表
    目录一、ArrayList简介二、ArrayList的使用1、ArrayList的构造2、ArrayList的遍历3、ArrayList的常见操作(方法)4、ArrayList的扩容...
    99+
    2024-04-02
  • 深入学习Go语言数据结构的奥秘
    深入学习Go语言数据结构的奥秘,需要具体代码示例 Go语言作为一门简洁、高效的编程语言,在处理数据结构方面也展现出了其独特的魅力。数据结构是计算机科学中的基础概念,它旨在组织和管理数据...
    99+
    2024-04-02
  • 如何深入了解JVM内存结构
    如何深入了解JVM内存结构,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。你对JVM内存结构是否熟悉,这里向大家描述一下,主要包括类装载子系统,方法区,PC寄存器...
    99+
    2023-06-17
  • 深入解析MySQL索引数据结构
    目录概述索引数据结构 二叉树 红黑树 B-Tree B+Tree Hash 索引 InnoDB 索引实现(聚集) 索引文件和数据文件是分离的(非聚集) 聚集索引和非聚集索引 联合/复...
    99+
    2024-04-02
  • 深入了解Rust 结构体的使用
    目录楔子定义并实例化结构体简化版的实例化方式基于已有结构体实例创建元组结构体没有字段的空结构体结构体数据的所有权使用结构体的示例程序楔子 结构体是一种自定义的数据类型,它允许我们将多...
    99+
    2022-11-13
    Rust 结构体使用 Rust 结构体
  • HTML 框架标签:深入理解其结构和用法
    框架集元素(<frameset>) <frameset>元素定义了框架集的整体结构,并确定了各个框架的位置和大小。它具有以下主要属性: rows: 指定框架集的垂直布局,使用逗号分隔的行高百分比或像素值。 col...
    99+
    2024-03-13
    框架标签
  • 深入理解Go语言中的函数重构技巧
    在Go语言程序开发中,函数重构技巧是十分重要的一环。通过优化和重构函数,不仅可以提高代码质量和可维护性,还可以提升程序的性能和可读性。本文将深入探讨Go语言中的函数重构技巧,结合具体的...
    99+
    2024-04-02
  • 【深入】体系结构-003-SCN
    1、介绍 2、分类 3、SCN与数据库启动 4、SCN与数据库关闭 ...
    99+
    2024-04-02
  • 深入Linux PAM体系结构
    一、什么是Linux-PAM 为安全起见,计算机系统只有经过授权的合法用户才能访问,在这里如何正确鉴别用户的真实身份是一个关键的问题。所谓用户鉴别,就是用户向系统以一种安全的方式提交自己的身份证明,然后由系统确认用户的身份是否属实...
    99+
    2023-06-06
  • 深入了解Golang中的Slice底层实现
    目录1 Go数组2 切片的数据结构3 创建切片3.1 方法一:make3.2 方法二:字面量4 nil和空切片5 切片扩容5.1 扩容策略5.2 底层数组是不是新地址range遍历数...
    99+
    2023-02-26
    Golang Slice实现 Golang Slice Go Slice
  • 深入了解Golang中Slice切片的使用
    目录写在前面上代码分析原因总结写在前面 周日下午在家学习,看到一个关于切片的问题,在网上找了一些资料,做个总结。 上代码 func main() { sl := make([]in...
    99+
    2023-02-27
    Golang Slice切片使用 Golang Slice切片 Golang Slice
  • 深入探究Go语言结构体方法的定义
    深入理解Go语言结构体定义的方法,需要具体代码示例 引言 Go语言是一门简洁高效的编程语言,在其核心特性中,结构体是一个非常重要的概念。与其他编程语言不同,Go语言的结构体不仅可以包含属性字段,还可以定义与结...
    99+
    2024-02-02
    方法 go语言 结构体定义
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作