你自学半年也搞不懂的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的较量一直都是人们津津乐道的话题.两个平台各有各的优势所在,同时也都力图能在各个方面赶超对手.对于用户来说,青菜萝卜 ...
随机推荐
- 洛谷P1003 铺地毯 模拟
这一题就是一个很普通的模拟,每次输入的时候存储四个角的值 把四个角的横纵坐标存储在一排.然后在倒序遍历一遍,查找的时候就看所要查找的坐标在不在这个范围内,如果找到了就标记一下再输出,如果没有找到就输出 ...
- 证明与计算(7): 有限状态机(Finite State Machine)
什么是有限状态机(Finite State Machine)? 什么是确定性有限状态机(deterministic finite automaton, DFA )? 什么是非确定性有限状态机(nond ...
- YII2自动初始化脚本
#!/usr/bin/expect spawn ./init expect "Which environment do you want the application to be init ...
- [codevs2370]小机房的树<LCA>
题目链接:http://codevs.cn/problem/2370/ 这题我还是做了比较久了,因为有人告诉我这是用tarjan离线做 好吧算我是蒟蒻,真心不懂tarjan怎么做,最后还是用倍增做的 ...
- [POI2014][树形DP]FarmCraft
题目 In a village called Byteville, there are houses connected with N-1 roads. For each pair of houses ...
- ADB 调试
1.adb简介 adb的全称为Android Debug Bridge,就是起到调试桥的作用.通过adb我们可以在Eclipse中方面通过DDMS来调试Android程序,说白了就是debug工具.a ...
- 如何编写优雅的异步代码 — CompletableFuture
前言 在我们的意识里,同步执行的程序都比较符合人们的思维方式,而异步的东西通常都不好处理.在异步计算的情况下,以回调表示的动作往往会分散在代码中,也可能相互嵌套在内部,如果需要处理其中一个步骤中可能发 ...
- idea打包或编译错误,错误为c盘idea路径某些文件被占用(非idea文件,项目生成的文件)
方法列表(2的效果可能更好) 1.将被占用的文件删除之后,重新打包或编译. 2.多编译几次项目. 3.发现真正可能的原因.(貌似被南航企业版360拦截了,导致targe或maven等文件被占用问题) ...
- Java并发基础06. 线程范围内共享数据
假设现在有个公共的变量 data,有不同的线程都可以去操作它,如果在不同的线程对 data 操作完成后再去取这个 data,那么肯定会出现线程间的数据混乱问题,因为 A 线程在取 data 数据前可能 ...
- Pointer Lock API(2/3):属性、方法、事件
Pointer Lock API 提供了三个属性.两个方法.两个事件 Tabel Of Content 属性 Document.pointerLockElement Document.onpointe ...