你自学半年也搞不懂的go底层,看这篇。这篇讲 go的数组、切片、Maps
数组
1、定义数组
package main
import "fmt"
func main() {
//定义了一个大小为3的int类型数组
//数组在定义阶段,大小和类型就固定了
var a [3]int //只定义,没有初始化
fmt.Println(a)
}
//[0 0 0]
2、使用数组
package main
import "fmt"
func main() {
var a [3]int
a[2]=100 //修改赋值
fmt.Println(a)
fmt.Println(a[0]) //取0的位置
}
//[0 0 100]
//0
3、定义并赋值
package main
import "fmt"
func main() {
//方式一
var a [3]int=[3]int{1,2,3} //[1 2 3]
//方式二
var a =[3]int{1,2,3} //[1 2 3]
//方式三
a := [3]int{1, 2, 3} //[1 2 3]
//只给第2个位置设为99
a := [3]int{2:99} //[0 0 99]
//指定位置设置
a := [3]int{2:99,1:88} //[0 88 99]
fmt.Println(a)
}
4、数组的大小是类型的一部分
package main
import "fmt"
func main() {
//这两个不是一个类型
var a [2]int
var b [3]int
a=b
fmt.Println(a>b)
}
5、数组是值类型(当参数传递到函数中,修改不会改变原来的值)
// go语言中,都是copy传递
/*
python中都是引用传递,一切皆对象,就是地址,当做参数传递是把地址传过去了
python中比较特殊:可变类型和不可变类型
*/
package main
import "fmt"
func main() {
var a [3]int=[3]int{5,6,7}
fmt.Println(a) //[5 6 7]
test1(a)
fmt.Println(a) //[5 6 7]
}
func test1(a [3]int) {
a[0]=999
fmt.Println(a) //[999 6 7]
}
6、数组长度
package main
import "fmt"
func main() {
var a [3]int=[3]int{5,6,7}
fmt.Println(len(a)) //3
}
7、循环数组
package main
import "fmt"
func main() {
//方式一
var a [3]int=[3]int{5,6,7}
for i:=0;i<len(a);i++{
fmt.Println(a[i])
}
//方式二
//range:是一个关键字
var a [3]int=[3]int{5,6,7}
for i,v:=range a{
fmt.Println(i) //索引
fmt.Println(v) //数组的值
}
//方式三
//函数如果返回两个值,必须用两个值来接收
//range可以用一个值来接收,如果用一个值来接收,就是索引
var a [3]int=[3]int{5,6,7}
for i:=range a{
fmt.Println(i) //索引
}
//方式四
//只取值,不取索引
var a [3]int=[3]int{5,6,7}
for _,v:=range a{
fmt.Println(v) //值
}
}
8、多维数组
package main
import "fmt"
func main() {
//定义一个二维数组
var a [3][2]int // [[0 0] [0 0] [0 0]]
//定义并初始化
var a [3][2]int=[3][2]int{{1,2},{4,5},{9,70}}
a[1][0]=999 //修改值
fmt.Println(a) // [[1 2] [999 5] [9 70]]
}
切片
//切片是由数组建立的一种方便、灵活且功能强大的包装(Wrapper)。切片本身不拥有任何数据。它们只是对现有数组的引用。
//切片底层依附于数组
1、创建切片
package main
import "fmt"
func main() {
//创建切片(基于一个数组创建)
var a [9]int=[9]int{1,2,3,4,5,6,7,8,9}
//基于数组,切出一部分成为切片
// []int 中括号中没有东西,就是切片
var b []int
// 没有-1 没有步长
b=a[0:3] //前闭后开 //[1 2 3]
b=a[3:6] //前闭后开 //[4 5 6]
b=a[:] //前闭后开 //[1 2 3 4 5 6 7 8 9]
b=a[3:] //前闭后开 //[4 5 6 7 8 9]
fmt.Println(b)
}
2、使用切片
package main
import "fmt"
func main() {
var a [9]int=[9]int{1,2,3,4,5,6,7,8,9}
var b []int
b=a[3:] //前闭后开 //[4 5 6 7 8 9]
fmt.Println(b[0]) // 4
}
3、切片的修改会影响底层数组,数组的修个也会影响切片。相互影响
package main
import "fmt"
func main() {
var a [9]int=[9]int{1,2,3,4,5,6,7,8,9}
var b []int=a[0:3] //前闭后开
fmt.Println(a) //[1 2 3 4 5 6 7 8 9]
fmt.Println(b) //[1 2 3]
a[0]=999
b[2]=888
fmt.Println(a) //[999 2 888 4 5 6 7 8 9]
fmt.Println(b) //[999 2 888]
}
4、切片的长度和容量
package main
import "fmt"
func main() {
var a [9]int=[9]int{1,2,3,4,5,6,7,8,9}
var b []int=a[2:3] //前闭后开 //[3]
fmt.Println(len(b)) //1
//切片容量是7,意思是,可以往里追加值
fmt.Println(cap(b)) //7 还可以往后追加7个
//容量就是原数组的长度呗?对不对?不太对。。
b[0]=9999
fmt.Println(a) //[1 2 9999 4 5 6 7 8 9]
fmt.Println(b) //[9999]
}
5、追加值
//总结1:当切片追加值,超过了切片容量,切片容量会翻倍,在原来容量基础上乘以2
//总结2:一旦超过了原数组, 就会重新申请数组,把数据copy到新数组,切片和原数组就没有关系了
//总结3:追加值打破了原数据的容量,就不会再影响原数据
package main
import "fmt"
func main() {
var a [9]int=[9]int{1,2,3,4,5,6,7,8,9}
var b []int=a[2:3] //前闭后开 //[3]
b=append(b,1) //追加1
b=append(b,11,22,33,44,55) //继续追加
fmt.Println(len(b)) //7
fmt.Println(cap(b)) //7
fmt.Println(b) // [3 1 11 22 33 44 55]
fmt.Println(a) // [1 2 3 1 11 22 33 44 55]
//到了数组的尾部,继续追加值
b=append(b,999)
fmt.Println(len(b)) // 8
fmt.Println(cap(b)) //容量是14
//总结1:当切片追加值,超过了切片容量,切片容量会翻倍,在原来容量基础上乘以2
b=append(b,222,333,444,555,666,7,8)
fmt.Println(len(b)) //15
fmt.Println(cap(b)) //容量是14*2=28
//总结2:一旦超过了原数组, 就会重新申请数组,把数据copy到新数组,切片和原数组就没有关系了
fmt.Println(a)
fmt.Println(b)
a[8]=7777
fmt.Println(a)
fmt.Println(b)
}
6、通过make创建切片(底层也依附于数组)
package main
import "fmt"
func main() {
//var a []int
//切片零值是什么? nil类型:是所有引用类型的空值
//fmt.Println(a)
//if a==nil{
// fmt.Println("我是空的")
//}
//3是长度,4是容量
//var a []int=make([]int,3,4) //[0 0 0]
//3是长度,3是容量
var a []int=make([]int,3) //[0 0 0]
fmt.Println(a)
fmt.Println(len(a)) //3
fmt.Println(cap(a)) //3
a=append(a,55) // [0 0 0 55]
fmt.Println(a)
fmt.Println(len(a)) //4
fmt.Println(cap(a)) //6
}
7、切片定义并赋初值
package main
import "fmt"
func main() {
var a []int=[]int{1,2,3}
fmt.Println(a) //[1 2 3]
fmt.Println(len(a)) //3
fmt.Println(cap(a)) //3
}
8、切片是引用类型,当参数传递,会修改掉原来的值
package main
import "fmt"
func main() {
var a []int=[]int{1,2,3}
fmt.Println(a) // [1 2 3]
test3(a)
fmt.Println(a) // [999 2 3]
}
func test3(a []int) {
a[0]=999
fmt.Println(a) // [999 2 3]
}
9、多维切片
package main
import "fmt"
func main() {
var a [][]int=make([][]int,2,3)
fmt.Println(a) //[[] []]
fmt.Println(a[0]==nil) //true
//会报错
//a[0][0]=999
// 如何做?(for循环完成初始化)
a[0]=make([]int,2,3)
a[0][1]=999
fmt.Println(a) //[[0 999] []]
a[1][0]=99999
//
////定义并赋初值用的多
//var a [][]int=[][]int{{1,2,3},{4,5,6,7,7,8}}
//////跟上面不一样
//var a [][3]int=[][3]int{{1,2,3},{4,5,6}}
//fmt.Println(a)
}
10、切片的copy
package main
import "fmt"
func main() {
var a []int=make([]int,3,4)
var b []int=make([]int,2,6)
fmt.Println(a) //[0 0 0]
fmt.Println(b) //[0 0]
a[0]=11
a[1]=22
a[2]=33
b[0]=999
fmt.Println(a) // [11 22 33]
fmt.Println(b) // [999 0]
copy(b,a) //拷贝,把a拷给b,多余的截断
fmt.Println(b) // [11 22]
}
11、切片越界
package main
import "fmt"
func main() {
var a []int=make([]int,3,4)
fmt.Println(a) //[0 0 0]
a[0]=11
a[1]=22
a[2]=33
fmt.Println(a) //[11 22 33]
a=append(a,999) //追加
fmt.Println(a) //[11 22 33 999]
//中括号取值,只能取到长度值,不能取到容联大小
fmt.Println(a[3]) //999
fmt.Println(a[4]) //越界报错
}
Maps
//maps:hash,字典, key:value存储
1、map的定义和使用
package main
import "fmt"
func main() {
//map[key类型]value类型:key的类型必须可hash,key值:数字,字符串
//map的零值:nil 它是一个引用类型
var a map[int]string
fmt.Println(a) //map[]
if a==nil{
fmt.Println("我是空的") // 我是空的
}
}
2、定义了,没有初始化,使用
package main
import "fmt"
func main() {
//var a map[int]string
//初始化用make
var a map[int]string=make(map[int]string)
//如果有,会修改,如果没有,会放入
a[1]="lqz" // 设值
a[1]="jeff" //覆盖
a[2]="18"
//a["xx"] key值不能乱写
fmt.Println(a) //map[1:jeff 2:18]
}
3、获取元素
package main
import "fmt"
func main() {
var a map[int]string=make(map[int]string)
//var a map[int]int=make(map[int]int)
fmt.Println(a[0]) //取出value值的空值 ""
fmt.Println(a) // map[]
}
4、判断value值是否存在
package main
import "fmt"
func main() {
//统一的方案来判断value值是否存在
//a[0] 可以返回两个值,一个是value值(可能为空),另一个是true或false
var a map[int]int=make(map[int]int)
a[0]=0
v,ok:=a[0]
fmt.Println(v) //0
fmt.Println(ok) //true
}
5、map删除元素
package main
import "fmt"
func main() {
var a map[int]int=make(map[int]int)
a[1]=11
a[2]=22
fmt.Println(a) //map[1:11 2:22]
//根据key删(内置函数)
delete(a,1)
fmt.Println(a) //map[2:22]
}
6、map长度
package main
import "fmt"
func main() {
var a map[int]int=make(map[int]int)
fmt.Println(len(a)) //0
a[1]=11
a[2]=22
fmt.Println(len(a)) //2
}
7、map 是引用类型
package main
import "fmt"
func main() {
var a map[int]int=make(map[int]int)
a[1]=11
fmt.Println(a) // map[1:11]
test(a)
//证明是引用类型,相互改变
fmt.Println(a) // map[1:999]
}
func test(a map[int]int) {
a[1]=999
fmt.Println(a) //map[1:999]
}
8、map的相等性
//和python的字典差不多,只能按key取值后比较
package main
import "fmt"
func main() {
var a map[string]string=make(map[string]string)
a["name"]="lqz"
var b map[string]string=make(map[string]string)
b["name"]="lqz"
fmt.Println(a)
fmt.Println(b)
//不能这样判断,map只能跟nil比较
if a["name"]==b["name"] {
fmt.Println("相等")
}
}
9、循环map
//range循环
package main
import "fmt"
func main() {
var a map[string]string=map[string]string{"name":"lqz","age":"19","sex":"男"}
for k,v:=range a{
fmt.Println(k) //key
fmt.Println(v) //value
}
}
//map是无序的(python中字典从3.6以后有序了,3.6之前无序,底层如何实现的)
你自学半年也搞不懂的go底层,看这篇。这篇讲 go的数组、切片、Maps的更多相关文章
- 现在连Linux都搞不懂,当初我要是这么学习操作系统就好了!
原创声明 本文首发于微信公众号[程序员黄小斜] 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图 简介 学习编程,操作系统是你必须要掌握的基础知识,那么操作系统到底是什么呢? 这还 ...
- 为什么你精通CRUD,却搞不懂数据库的基本原理?
原创声明 本文作者:黄小斜 转载请务必在文章开头注明出处和作者. 本文思维导图
- 那些年搞不懂的"协变"和"逆变"
博主之前也不是很清楚协变与逆变,今天在书上看到了有关于协变还是逆变的介绍感觉还是不太懂,后来看了一篇园子里面一位朋友的文章,顿时茅塞顿开.本文里面会有自己的一些见解也会引用博友的一些正文,希望通过本篇 ...
- 搞不懂的算法-排序篇<1>
最近在学习算法,跟着<Algorithms>这本书,可能是自己水平不够吧,看完排序算法后各种,希尔,归并,快排,堆的实现在脑子里乱成一锅粥,所以就打算大概总结一下,不求精确,全面,只想用平 ...
- 听说同学你搞不懂Java的LinkedHashMap,可笑
先看再点赞,给自己一点思考的时间,微信搜索[沉默王二]关注这个有颜值却假装靠才华苟且的程序员.本文 GitHub github.com/itwanger 已收录,里面还有我精心为你准备的一线大厂面试题 ...
- 什么鬼?你还搞不懂json和字典的区别??
现在自动化培训烂大街,是个人都能说的上几个框架,面试如果问框架相关问题,求职者只需一瓶 82 年的雪碧,会吹的让你怀疑人生!所以面试官为了更清楚的知道你是停留在表面上的花拳绣腿还是有扎实的基础,就不会 ...
- python3编码问题终结者--还搞不懂你来找我
python unicode bytes str 编码 首先需要说明一下,该篇文章是以python3为基础的,python2是否适合没有验证过.由于python编码问题确实比较多,文章篇幅可能较长,请 ...
- 搞不懂SSH与JAVA+Servlet+javabean有什么关系
在SSH中:struts 是控制层,同时与Jsp结合代表表现层,同时负责客户端请求的处理,Spring主要处理逻辑事物处理,Hibernate主要对数据库的持久化操作. Jsp+Servlet+Jav ...
- 搞不懂为什么开发人员爱iOS恨Android?
导读:很多网站发表文章大同小异.唯有这个不同点,给大家分享. Android和iOS的较量一直都是人们津津乐道的话题.两个平台各有各的优势所在,同时也都力图能在各个方面赶超对手.对于用户来说,青菜萝卜 ...
随机推荐
- Android LinearLayout线性布局详解
为了更好地管理Android应用的用户界面里的各组件,Android提供了布局管理器.通过使用布局管理器,Android应用图形用户界面具有良好的平台无关性.推荐使用布局管理器来管理组件的分布.大小, ...
- spring-cloud-gateway静态路由
为什么引入 API 网关 使用 API 网关后的优点如下: 易于监控.可以在网关收集监控数据并将其推送到外部系统进行分析. 易于认证.可以在网关上进行认证,然后再将请求转发到后端的微服务,而无须在每个 ...
- 深入理解NIO(二)—— Tomcat中对NIO的应用
深入理解NIO(二)—— Tomcat中对NIO的应用 老哥行行好,转载和我说一声好吗,我不介意转载的,但是请把原文链接贴大点好吗 Tomcat大致架构 先贴两张图大致看一眼Tomcat的架构 Tom ...
- mybatis采坑之Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column '?°?é?“é?“' in 'field list'
最后找到问题: 符号问题 修改之后正常
- Sql练习201908131742
orderdt_jimmy表结构: sql查询: then amount end) t1, then amount end) t2, then amount end) t3 from orderdt_ ...
- 使用错误代码对象进行C++错误处理
原文发表于codeproject,由本人翻译整理分享于此. 前言 我已经使用了本文描述的代码和机制近20年了,到目前为止,我还没有找到更好的方法来处理大型C++项目中的错误.最初的想法是从一篇文章(D ...
- Three.js中的动画实现02-[Three.js]-[Object3D属性.onAfterRender/.onBeforeRender]
Table Of Content Object3D简介以及两个属性的介绍 一个示例 Object3D简介以及两个属性的介绍 这是Three.js中大部分对象的基类,提供了一系列的属性和方法来对三维空间 ...
- Vue引用阿里图标库
首先进入官网http://www.iconfont.cn/ 转载:https://blog.csdn.net/qq_34802010/article/details/81451278 选择图标库 在里 ...
- JVM类加载过程详细分析
双亲委派加载模型 为什么需要双亲委派加载模型 主要是为了安全,避免用户恶意加载破坏JVM正常运行的字节码文件,比如说加载一个自己写的java.util.HashMap.class.这样就有可能造成包冲 ...
- Maven多模块项目+MVC框架+AJAX技术+layui分页对数据库增删改查实例
昨天刚入门Maven多模块项目,所以简单写了一个小测试,就是对数据库单表的增删改查,例子比较综合,写得哪里不妥还望大神赐教,感谢! 首先看一下项目结构: 可以看到,一个项目MavenEmployee里 ...