Go学习(二):切片Slice、指针

【Golang学习之旅】Go 语言数据类型详解(string、slice、map等) ✅ 适合人群:Golang 新手 | 后端开发者 | 面试求职者✅ 文章亮点:超详细解析 + 代码示例 + 实战应用✅ 目标:掌握 Go 语言核心数据类型,助你写出高效、稳定的 Go 代码!📌 本篇文章介绍了 Go 语言的常见数据类型,包括 string、slice、map 等,帮助你掌握 Go 语言基础。📌 进阶学习:Go 并发(Goroutine)、微服务(gRPC)、Web 开发(Gin 框架)Go 官方文档。 阅读详情

目录

 1、切片

1.1 切片初始化

1.2 通过make来创建切片 

1.3 切片的内存布局 

1.4 用append内置函数操作切片(切片追加)

1.5 超出原 slice.cap 限制,就会重新分配底层数组,即便原数组并未填满。 

1.6 slice中cap重新分配规律:1->2->4->8->16->32->64-> 

1.7 copy :函数 copy 在两个 slice 间复制数据,复制长度以 len 小的为准。两个 slice 可指向同一底层数组,允许元素区间重叠。

 1.8 slice遍历:

 2、指针

 2.1 new:少用

2.2 make: 它只用于slice、map以及chan的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。

 1、切片

切片Slice · Go语言中文文档 (topgoer.com)

    1. 切片:切片是数组的一个引用,因此切片是引用类型。但自身是结构体,值拷贝传递。
    2. 切片的长度可以改变,因此,切片是一个可变的数组。
    3. 切片遍历方式和数组一样,可以用len()求长度。表示可用元素数量,读写操作不能超过该限制。 
    4. cap可以求出slice最大扩张容量,不能超出数组限制。0 <= len(slice) <= len(array),其中array是slice引用的数组。
    5. 切片的定义:var 变量名 []类型,比如 var str []string  var arr []int。
    6. 如果 slice == nil,那么 len、cap 结果都等于 0。

1.1 切片初始化

package main

import (
	"fmt"
)

func main() {
	//1.声明切片
	var s1 []int
	if s1 == nil {
		fmt.Println("是空")
	} else {
		fmt.Println("不是空")
	}
	// 2.:=
	s2 := []int{}
	// 3.make()
	var s3 []int = make([]int, 0)
	fmt.Println(s1, s2, s3)
	// 4.初始化赋值
	var s4 []int = make([]int, 0, 0)
	fmt.Println(s4)
	s5 := []int{1, 2, 3}
	fmt.Println(s5)
	// 5.从数组切片
	arr := [5]int{1, 2, 3, 4, 5}
	var s6 []int
	// 前包后不包
	s6 = arr[1:4]
	fmt.Println(s6)

	//切片初始化
	arr2 := [...]int{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
	slice5 := arr2[2:8]
	slice6 := arr2[0:6]         //可以简写为 slice := arr[:end]
	slice7 := arr2[5:10]        //可以简写为 slice := arr[start:]
	slice8 := arr2[0:len(arr)]  //slice := arr[:]
	slice9 := arr2[:len(arr)-1] //去掉切片的最后一个元素
	fmt.Printf("局部变量: arr2 %v\n", arr2)
	fmt.Printf("局部变量: slice5 %v\n", slice5)
	fmt.Printf("局部变量: slice6 %v\n", slice6)
	fmt.Printf("局部变量: slice7 %v\n", slice7)
	fmt.Printf("局部变量: slice8 %v\n", slice8)
	fmt.Printf("局部变量: slice9 %v\n", slice9)

}

1.2 通过make来创建切片 

1.3 切片的内存布局 

package main

import (
	"fmt"
)

func main() {


	//通过make来创建切片,cap是切片的容量,那怎么追加容量?
	var slice10 []int = make([]int, 10)
	//slice10 := make([]int, 10)
	slice11 := make([]int, 10)
	slice12 := make([]int, 2, 5)
	fmt.Printf("make局部slice3 :%v\n", slice10)
	fmt.Printf("make局部slice4 :%v\n", slice11)
	fmt.Printf("make局部slice5 :%v len:%d cap:%d\n", slice12, len(slice12), cap(slice12))

	s10 := []int{0, 1, 2, 3, 8: 100} // 通过初始化表达式构造,可使用索引号。
	fmt.Println(s10, len(s10), cap(s10))

	//切片的内存布局
	data := [...]int{0, 1, 2, 3, 4, 5}
	s := data[1:3]
	fmt.Printf("data :%v len:%d cap:%d\n", data, len(data), cap(data))
	fmt.Printf("data的切片s :%v len:%d cap:%d\n", s, len(s), cap(s))

	//使用 make 动态创建slice,避免了数组必须用常量做长度的麻烦。还可用指针直接访问底层数组,退化成普通数组操作。
	a := []int{0, 1, 2, 3}
	p := &a[2] // *int, 获取底层数组元素指针。
	*p += 100

	fmt.Println(a)

	//多维
	datas := [][]int{
		[]int{1, 2, 3},
		[]int{100, 200},
		[]int{11, 22, 33, 44},
	}
	fmt.Println(datas)

	//可直接修改 struct array/slice 成员。
	d := [5]struct {
		x int
	}{}

	b := d[:]

	d[1].x = 10
	b[2].x = 20

	fmt.Println(d)
	fmt.Printf("%p, %p\n", &d, &d[0])
	fmt.Println(b)
	fmt.Printf("%p, %p\n", &b, &b[0])
	//输出
	// [{0} {10} {20} {0} {0}]
	// 0xc00000e480, 0xc00000e480
	// [{0} {10} {20} {0} {0}]
	// 0xc000008240, 0xc00000e480
	

}

1.4 用append内置函数操作切片(切片追加)

    //append :向 slice 尾部添加数据,返回新的 slice 对象
	var a = []int{1, 2, 3}
	fmt.Printf("slice a : %v\n", a)
	var b = []int{4, 5, 6}
	fmt.Printf("slice b : %v\n", b)
	c := append(a, b...)	 //...
	fmt.Printf("slice c : %v\n", c)
	d := append(c, 7)
	fmt.Printf("slice d : %v\n", d)
	e := append(d, 8, 9, 10)
	fmt.Printf("slice e : %v\n", e)

	s11 := make([]int, 0, 5)
	fmt.Printf("%p\n", &s11)

	s12 := append(s1, 1)
	fmt.Printf("%p\n", &s12)

	fmt.Println(s11, s12)

1.5 超出原 slice.cap 限制,就会重新分配底层数组,即便原数组并未填满。 

package main

import (
	"fmt"
)


func main() {
	
	data := [...]int{0, 1, 2, 3, 4, 10: 0}
	s := data[:2:3] //cap=max-low=3-0=3
	fmt.Println(s, cap(s), &s[0], &data[0])

	s = append(s, 100, 200) // 一次 append 两个值,超出 s.cap 限制。

	fmt.Println(s, data)         // 重新分配底层数组,与原数组无关。
	fmt.Println(&s[0], &data[0]) // 比对底层数组起始指针。
	//输出
	// [0 1] 3 0xc000060060 0xc000060060
	// [0 1 100 200] [0 1 2 3 4 0 0 0 0 0 0]
	// 0xc00000e3f0 0xc000060060

}

1.6 slice中cap重新分配规律:1->2->4->8->16->32->64-> 

package main

import (
    "fmt"
)

func main() {

    s := make([]int, 0, 1)
    c := cap(s)

    for i := 0; i < 50; i++ {
        s = append(s, i)
        if n := cap(s); n > c {
            fmt.Printf("cap: %d -> %d\n", c, n)
            c = n
        }
    }

}

1.7 copy :函数 copy 在两个 slice 间复制数据,复制长度以 len 小的为准。两个 slice 可指向同一底层数组,允许元素区间重叠。

package main

import (
    "fmt"
)

func main() {

    data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    fmt.Println("array data : ", data)
    s1 := data[8:]
    s2 := data[:5]
    fmt.Printf("slice s1 : %v\n", s1)
    fmt.Printf("slice s2 : %v\n", s2)
    copy(s2, s1)
    fmt.Printf("copied slice s1 : %v\n", s1)
    fmt.Printf("copied slice s2 : %v\n", s2)
    fmt.Println("last array data : ", data)

}
    array data :  [0 1 2 3 4 5 6 7 8 9]
    slice s1 : [8 9]
    slice s2 : [0 1 2 3 4]
    copied slice s1 : [8 9]
    copied slice s2 : [8 9 2 3 4]
    last array data :  [8 9 2 3 4 5 6 7 8 9]

 1.8 slice遍历:

package main

import (
    "fmt"
)

func main() {

    data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    slice := data[:]
    for index, value := range slice {
        fmt.Printf("inde : %v , value : %v\n", index, value)
    }

}

 2、指针

    var a *int
    *a = 100
    fmt.Println(*a)

会报错,没有分配内存空间。要分配内存,就引出来今天的new和make。 

 2.1 new:少用

a := new(int)
b := new(bool)

2.2 make: 它只用于slice、map以及chan的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。

使用make进行初始化,然后才可以对它们进行操作。

package main

import "fmt"

func main() {
	var b map[string]int
	b = make(map[string]int, 10)
	b["测试"] = 100
	b["测"] = 20
	fmt.Println(b, len(b))
	var num int = 0
	ptr := &num
	*ptr = 10
	fmt.Println(num)
}

小白学习go之基础篇2 -- Slice切片的原理 文章目录前言一、为什么要有切片?二、切片是怎么实现的呢?1.Go的切片结构体 -- SliceHeader2.初始化切片的两种方式3.切片是在栈上分配内存的还是在堆?3.切片的扩容:三、切片的使用有什么坑需要注意呢?总结 前言 本文主要记录: 1.Slice切片的实现原理。 2.切片的指针是存储在堆中还是栈中的。 3.切片使用中的一些坑。 一、为什么要有切片? 由于go中的数组是值类型的,使用的时候是固定大小的 如arr := [3]int{1,2,3} 之后就无法再改变数组的长度了。 所以gola 阅读详情

相关推荐

Claude Code长期记忆:优雅的上下文管理

ClaudeCode的上下文管理系统采用三层架构设计,通过智能压缩和优化策略在记忆容量与性能间取得平衡。系统包含短期记忆(高速工作区)、中期记忆(智能蒸馏器)和长期记忆(持久化知识库)。当Token使用率达到92%阈值时启动wU2压缩器,采用8段式结构化摘要保留关键信息,并配合智能文件恢复和渐进式预警机制。该系统通过分层处理、优雅降级和透明化交互,为AI应用提供了高效可靠的上下文管理方案,展现了在有限资源下实现智能记忆的艺术。

m0_53117338的博客 3816

【Go自学第五节】Go中函数切片传递与指针传递

Go中函数切片传递与指针传递、函数的参数传递均是值传递、Go之如何在函数内修改指针

Weber's blog 1894

百度智能云ASR实战:5分钟搞定Unity语音转文字(含完整代码)

本文详细介绍了如何在Unity中集成百度智能云ASR服务,实现高效的语音转文字功能。从环境配置、音频处理到服务端通信,提供完整代码示例和实战优化技巧,帮助开发者快速实现语音交互功能,适用于游戏开发、XR应用等场景。

ujm56789012的博客 215

go的数组指针、切片指针与结构体指针

1.数组指针 (1)数组指针与指针数组 这俩概念原本在c语言中就是一个绕口令般的存在,尽管从类型角度来看两者并没什么相似的地方。 但是在go语言中对这两个类型的设定做出了一些不同的规定。首先交代一下基本概念: 数组指针:指的是一个指针,只不过这个指针指向了一个数组 eg: var arr [5]int = [5]int{1,2,3,4,5}; ...

南方有岛 2405

区块链入门:用账本、乐高和三台旧电脑讲懂分布式账本

区块链是一种去中心化的分布式账本技术,其核心原理是通过密码学哈希、共识机制和链式结构实现数据不可篡改与多方共同验证。它不依赖单一中心,而是将交易记录同步复制到多个节点,依靠数学规则而非人工信任达成一致,从而在数字世界构建可验证的信用基础设施。这种‘集体见证’模式显著提升了系统抗单点故障与人为干预的能力,广泛应用于供应链溯源、数字身份、教育管理及公益透明等需强信任保障的场景。本文以账本类比、乐高拆解和Ganache实操为线索,面向零基础读者通俗解析哈希值、挖矿与智能合约等关键概念。

weixin_30517215的博客 274

windows在使用ping 127.0.0.1时出现一般故障的解决方案

本文主要介绍了windows在使用ping 127.0.0.1时出现一般故障的解决方案,希望能对使用windows的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 6万+

Go语言学习笔记:2指针 切片

一指针: 1.每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置 B = 10 A := &B 总结: 取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。 2.指针传值 func mod1(x int) { x = 5 }//未传值 func mod2(y *int) { *y = 10 }//传值 func main() { a := 1 mod1(a) fm...

xiaotian2333333的博客 1036

【ROS2】RViz2加载URDF模型文件

1)运行RViz2rviz22)添加组件:RobotModel3)选择通过文件添加4)选择URDF文件,此时会报错,需要修改Fixed Frame为map即可

郭老二 1450

golang中的slice

golang中的slice表示一个可变长度的数组,声明为 []T ,其中T是类型。 关于数组请参见:golang中的数组 slice跟数组紧密相连,slice有三个属性,分别是:指针、长度(len)和容量(cap),其中指针指向底层数组,所以它天然依赖底层数组。从某种意义上来讲,slice更像一个结构体,这个结构体里面必然包含一个指针。 slice的指针指向底层数组 arr := [...]int{1, 2, 3, 4, 5} slice1 := arr[:3] for i := range slice1

朱登凯的专栏 1722

嵌入式系统开发笔记112:通过有人云测试MQTT

项目中使用到“有人”公司的WH-LTE-7S0模块,本文讲解通过有人云进行MQTT测试的方法。

snmplink的博客 997

YOLO系列算法改进 | 主干改进篇 | 替换LSKNet主干特征提取网络 | 通过动态调整感受野自适应融合长程上下文,显著提升小目标与复杂背景下的检测精度!

YOLO系列算法改进 | 主干改进篇 | 替换LSKNet主干特征提取网络 | 通过动态调整感受野自适应融合长程上下文,显著提升小目标与复杂背景下的检测精度! (以YOLO26最新目标检测模型为基础,利用LSKNet替代Backbone)

2502_91881744的博客 211

Golang如何遍历切片slice

Golang语言切片遍历总结,Golang语言遍历切片只有两种方式通过 for 循环与通过 for range 循环的方式,简单方便。

phplife的技术专栏,专注于php,golang,ai等技术应用 4650

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Golang学习记录10——切片(slice)(注意append)

定义一个切片,然后让切片去引用一个已经创建好的数组。//方式1:通过引用数组定义//引用全部//引用片段[2 3]通过make内置函数来创建切片。make()底层创建一个数组,对外不可见,所以不能直接操作这个数组,需要使用slice去间接访问各元素。make(数据类型, 长度 , [容量])//方式2:通过make内置函数创建-可不指定容量(只会默认长度容量)48[0 0 0 0]定一个切片,直接就指定具体数组,使用原理类似make的方式。

Dearfrienda的博客 2398

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

go 切片slice学习总结

go slice的结构,初始化,容量扩容理解,append,copy,删除操作方法的使用总结

yuxuan89814的专栏 1293

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Golang Slice切片如何扩容

如果切片的容量小于1024个元素,那么扩容的时候slice的cap就乘以2;一旦元素个数超过1024个元素,增长因子就变成1.25,即每次增加原来容量的四分之一。

猫轻王的博客 4975

go slice切片的详细知识(包含底层扩容)

本篇文章是之前我在学习切片时遇到的一些问题,也在网上搜索了许多材料+实践。下面的代码不敢说一定正确,但一定是亲自实践过的。

m0_72874409的博客 2777

golang学习之二:切片slice

、golang切片slice创建、切片与数组的区别、切片截取、切片与底层数组关系、切片内建函数append、copy、切片做函数参数

java_xxxx的博客 1813

【Go学习】slice切片的本质及操作——切片的追加、删除、插入等

【Go学习】slice切片的本质及操作——切片的追加、删除、插入等一、一般操作1,声明变量,go自动初始化为nil,长度:0,地址:0,nilpackage mainimport ( "fmt" )func main(){ var ss []string; fmt.Printf("length:%v \taddr:%p \tisnil:%v",len(ss),ss, ss==

谢健的专栏 5396

Go语言基础:切片slice的声明及使用

go语言基础: 切片的声明和使用

低调,谦虚,自律,反思,成长,保持热爱,奔赴梦想 2097

【Golang】--- Slice

切片作为Go语言的核心数据结构,它的设计兼顾了效率和灵活性。掌握切片的关键在于理解其底层数组+指针+长度+容量的结构,以及引用传递、扩容等特性。最后如果哪些地方的不足,欢迎大家在评论区中指正!

2401_87022967的博客 1371

【GO基础学习】基础语法(2)切片slice

GO基础语法学习:切片slice

高朗的博客 1213

Golang学习——string和slice切片

Golang学习——string和slice切片

weixin_44891093的博客 1992

golang中数组和slice的区别及使用

golang slice 和数组的使用

游走在世界的边缘~ 1098

Go语言学习——slice及其底层逻辑

切片是用来描述底层数组的连续片段的数据结构,定义于runtime包中,本身并不保存数组数据,而只是保存数组连续片段的描述信息。通过结构体里的 array 段指针引用底层数组,长度和容量属性限制底层数组的读写片段。

jiajixi的博客 1082

Go 语言切片(Slice)

Go 语言切片(Slice)是对数组的抽象,是一种灵活的内置类型。切片的长度(len)是当前元素的个数,容量(cap)是底层数组的总大小。切片是引用类型,指向底层数组的某个部分,修改切片可能会影响底层数组。定义:Go 语言中的切片(slice)是一种动态数组,它是对数组的抽象。切片的长度是可变的,可以通过追加元素来增长。特性切片由三个部分组成:指向底层数组的指针、长度(len)和容量(cap)。切片是引用类型,修改切片可能会影响底层的数组。

likuoelie的博客 742
上一篇: Go语言学习(一):变量常量、基本类型、数组
下一篇: Go学习(三):Map、结构体
Lay_XZ
博客等级 码龄5年 29粉丝 14原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值