高级数据类型:

  高级数据类型有数组、切片、map、指针、结构体、函数、接口、通道等,本文只介绍Arrary、Slice、map、ptr。

数组:

(1)概念:

  数组是同一种数据类型的集合。数组从声明时大小就已经确定,使用过程中可以修改值,但是数组的大小不可改变。

(2)初始化

  方法一:使用初始化列表来设置数组元素的值

  var testArray[3]int

  var numArray=[3]int{4,5}

  方法二:自行推断数组的长度的方式

  var numArray=[...]int{4,5}

  方法三:使用指定索引值的方式来初始化数组

  var numArray=[...]int{1:4,3:5}

(3)数组的遍历

func main() {
var a = [...]string{"南山", "罗湖", "保安"}
// 方法1:for循环遍历
for i := ; i < len(a); i++ {
fmt.Println(a[i])
} // 方法2:for range遍历
for index, value := range a {
fmt.Println(index, value)
}
}

(4)多维数组

func main() {
a := [][]string{
{"南山", "罗湖"},
{"保安", "光明"},
{"龙华", "龙岗"},
}
fmt.Println(a)
fmt.Println(a[][]) //支持索引取值:龙岗
}

注意:多维数组只有第一层可以使用...来让编译器推导数组长度。

切片:

  切片是一个拥有相同类型元素的可变长度的序列,它非常灵活,支持自动扩容。切片是一个引用类型,它的内部结构包含:地址、长度、容量。

(1)为什么用切片:

  a.数组的内a容固定,不能自动扩展;

  b.值传递,b数组作为函数参数时,将整个数组拷贝一份给形参;

  go语言中,我们几乎可以在所有的场景中,用切片来替代数组。切片拥有自己的长度和容量,可以通过使用len()、cap()函数分别求切片的长度和容量。

(2)基于数组定义切片:

func main() {
// 基于数组定义切片
a := []int{, , , , }
b := a[:] //基于数组a创建切片,包括元素a[1],a[2],a[3]
fmt.Println(b) //[26 37 48]
fmt.Printf("type of b:%T\n", b) //type of b:[]int
c := a[:] //[26 37 48 59]
d := a[:] //[15 26 37 48]
e := a[:] //[15 26 37 48 59]
}

(3)切片再切片:

func main() {
//切片再切片
a := [...]string{ "南山区", "罗湖区", "光明区", "宝安区", "龙岗区", "龙华区"}
fmt.Printf("a:%v type:%T len:%d cap:%d\n", a, a, len(a), cap(a))
b := a[:]
fmt.Printf("b:%v type:%T len:%d cap:%d\n", b, b, len(b), cap(b))
c := b[:]
fmt.Printf("c:%v type:%T len:%d cap:%d\n", c, c, len(c), cap(c))
}

(4)使用make()函数构造切片:

  上面都是基于数组或切片来创建切片的,如果是动态创建一个切片,则用make([]T, size, cap)函数

(5)切片的本质:

  切片的本质就是对底层数组的封装,一个slice是一个轻量级的数据结构,提供访问数组子序列(或者全部)元素的功能。一个slice由三部分组成:指针、长度(len)、容量(cap),指针指向slice的第一个元素对应的底层数组元素的地址(并不一定是底层数组的首地址)

(6)切片的赋值拷贝

func main() {
s1 := make([]int, ) //[0 0 0]
s2 := s1 //将s1直接赋值给s2,s1和s2共用一个底层数组
s2[] =
fmt.Println(s1) //[200 0 0]
fmt.Println(s2) //[200 0 0]
}

(7)切片的遍历

  切片支持索引遍历和for range遍历

func main() {
s := []int{, , } for i := ; i < len(s); i++ {
fmt.Println(i, s[i])
} for index, value := range s {
fmt.Println(index, value)
}
}

(8)添加元素

func main() {
//append()添加元素和切片扩容
var numSlice []int
for i := ; i < ; i++ {
numSlice = append(numSlice, i)
fmt.Printf("%v len:%d cap:%d ptr:%p\n", numSlice, len(numSlice), cap(numSlice), numSlice)
}
}
    扩容策略
    a.如果cap(申请容量)大于2倍old.cap(旧容量),则newcap=cap;
    b.否则,如果old.cap<1024,则newcap=2*old.cap;
    c.否则,如果old.cap>=1024,则最终容量(newcap)从旧容量(old.cap)开始循环增加原来的1/4,即(newcap=old.cap,for {newcap += newcap/4})直到最终容量(newcap)大于等于新申请的容量(cap);
    d.如果最终容量(cap)计算值溢出,则最终容量(cap)就是新申请容量(cap);
(9)使用copy()函数复制切片
  copy(destSlice,srcSlice[]T)函数可以迅速将一个切片的数组复制到另一个切片空间中
func main() {
// copy()复制切片
a := []int{, , , , }
c := make([]int, , )
copy(c, a) //使用copy()函数将切片a中的元素复制到切片c
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(c) //[1 2 3 4 5]
c[] =
fmt.Println(a) //[1 2 3 4 5]
fmt.Println(c) //[20 2 3 4 5]
//说明copy后a和c的底层数组不是同一个数组
}

(10)从切片中删除元素

  go语言中没有删除元素的方法,可以使用切片本身的特殊性来删除元素。

func main() {
// 从切片中删除元素
a := []int{, , , , , , , }
// 要删除索引为2的元素
a = append(a[:], a[:]...)
fmt.Println(a) //[30 31 33 34 35 36 37]
}

要从切片a中删除索引为index的元素,方法是:a=append(a[:index],a[index+1:]...)

map:

(1)概念

  map是一种映射关系容器,是一种无序的基于key-value的数据结构,必须初始化后才可以使用,默认初始值为nil,需要make函数来分配内存。

  在map里所有的键都是唯一的,而且必须是支持==和!=操作符的类型,对于切片、函数以及包含切片的结构体等类型,由于具有引用语义,不能作为映射的键,键为这些类型编译会报错;map值可以是任意类型,所有键的类型必须相同,值也是如此。

注意:map是无序的,每次打印的顺序都可能不同。

(2)map的基本使用:

func main() {
scoreMap := make(map[string]int, )
scoreMap["张三"] =
scoreMap["李四"] =
fmt.Println(scoreMap)
fmt.Println(scoreMap["李四"])
fmt.Printf("type of a:%T\n", scoreMap)
} 输出:
map[小明: 李四:] type of a:map[string]int

判断某个键是否存在:value,ok:=map[key]

func main() {
scoreMap := make(map[string]int)
scoreMap["张三"] =
scoreMap["李四"] =
// 如果key存在ok为true,v为对应的值;不存在ok为false,v为值类型的零值
v, ok := scoreMap["张三"]
if ok {
fmt.Println(v)
} else {
fmt.Println("没有此人")
}
}

map的遍历使用 for range

func main() {
scoreMap := make(map[string]int)
scoreMap["张三"] =
scoreMap["李四"] =
scoreMap["王五"] =
for k, v := range scoreMap {
fmt.Println(k, v)
}
}

注意:遍历map时的元素顺序与添加键值对的顺序无关。

使用delete()函数删除键值对:delete(map,key)

func main(){
scoreMap := make(map[string]int)
scoreMap["张三"] =
scoreMap["小明"] =
scoreMap["李四"] =
delete(scoreMap, "小明")//将小明:150从map中删除
for k,v := range scoreMap{
fmt.Println(k, v)
}
}

求map的键值对的容量,不能用cap()函数,而是用len(),map与slice一样可以自动扩容。

func main() {
rand.Seed(time.Now().UnixNano()) //初始化随机数种子 var scoreMap = make(map[string]int, ) for i := ; i < ; i++ {
key := fmt.Sprintf("stu%02d", i) //生成stu开头的字符串
value := rand.Intn() //生成0~10的随机整数
scoreMap[key] = value
}
for k,v:=range scoreMap{
fmt.Println(k, v)
}
}

指针:

  指针是一个代表某个内存地址值,这个内存地址往往是在内存中存储另一个变量的起始位置。go语言的指针保留的应用不到C/C++ 的1/3,不过还是保留了对基本的内存操作。学习go语言指针只需记住两个符号:&(取地址)、*(根据地址取值/解引用)。

(1)栈帧(stack)

   a.用来给函数运行提供的内存空间

   b.当函数调用时,产生栈帧,函数调用结束,释放栈帧

   c.栈帧存储:局部变量、形参、内存字段描述

   d.栈帧的空间使用完后,会自己释放

(2)空指针和野指针

  空指针:未被初始化的指针

  野指针:被一片无效地址空间初始化

func main() {
var a *int//空指针
fmt.Println(*a)
var p *int =0xc04204c080//野指针
fmt.Println(*p)
}

(3)堆(heap)

  make、new的变量存在堆中,堆上申请的空间在c/c++上必须释放的,而go有垃圾回收(gc),但并不是就可以无限申请内存,因为堆的大小是有限的,所以为了能够循环地申请内存空间,在使用完后,或者不使用后,提示gc进行垃圾回收,可以通过赋nil值来提醒gc进行回收。

  func new(Type) *Type,使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值。

func main() {
a := new(int)
b := new(bool)
fmt.Printf("%T\n", a) // *int
fmt.Printf("%T\n", b) // *bool
fmt.Println(*a) //
fmt.Println(*b) // false
}

  指针作为引用类型需要初始化后才会拥有内存空间,才可以给它赋值。应使用内置的new函数对指针进行初始化之后就可以正常对其赋值了。

func main() {
var a *int
a = new(int)
*a =
fmt.Println(*a)
}

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

make与new的差异

  a.二者都是用来分配内存

  b.make只用于slice、map、channel的初始化,返回的是这三个引用类型本身

  c.而new用于内存分配,初始值为类型的零值,返回的是指针

(4)变量存储

  等号左边的变量,代表变量所指向的内存空间;(写)

  等号右边变量,代表变量内存空间存储的数据值;(读)

func main() {
var p *int
p=new(int)
*p=
fmt.Printf("%d\n",*p)
fmt.Printf("%v\n",*p)
}

(5)指针的函数参数

  传地址(引用):将形参的地址值作为函数参数

  传值(数据):将形参的值拷贝一份给实参

func main() {
d :=
modifty1(d)
fmt.Println(d)
modifty2(&d)
fmt.Println(d)
} func modifty1(x int) {
x =
} func modifty2(x *int) {
*x =
}

高级数据类型(arrary、slice、map、ptr)的更多相关文章

  1. GO语言系列(四)- 内置函数、闭包与高级数据类型

    一.内置函数.递归函数.闭包 内置函数 1. close:主要用来关闭channel 2. len:用来求长度,比如string.array.slice.map.channel 3. new:用来分配 ...

  2. Scala进阶之路-高级数据类型之集合的使用

    Scala进阶之路-高级数据类型之集合的使用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Scala 的集合有三大类:序列 Seq.集 Set.映射 Map,所有的集合都扩展自 ...

  3. hive高级数据类型

    hive的高级数据类型主要包括:数组类型.map类型.结构体类型.集合类型,以下将分别详细介绍. 1)数组类型 array_type:array<data_type> -- 建表语句 cr ...

  4. GoLang基础数据类型--->字典(map)详解

    GoLang基础数据类型--->字典(map)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   可能大家刚刚接触Golang的小伙伴都会跟我一样,这个map是干嘛的,是 ...

  5. Scala进阶之路-高级数据类型之数组的使用

    Scala进阶之路-高级数据类型之数组的使用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数组的初始化方式 1>.长度不可变数组Array 注意:顾名思义,长度不可变数 ...

  6. Oracle11g R2学习系列 之八高级数据类型

    所谓的高级数据类型,就是大数据类型,即BCNB(助记词:BC牛逼)+XML数据类型. B:blob,用来存储可变长度的二进制数据. C:clob,主要用来存储可变长度的字符型数据,也就是其他数据库中提 ...

  7. Delphi 基本数据类型列表 高级数据类型列表 字符类型查询列表清单

    原文:Delphi 基本数据类型列表 高级数据类型列表 字符类型查询列表清单 长长的列表文字类型文件 分类 范围 字节 备注 简单类型 序数 整数 Integer -2147483648 .. 214 ...

  8. C++复习6.C/C++高级数据类型

    C/C++高级数据类型 1.C语言支持把基本数据类型组合起来形成更加强大的构造数据类型,就是C语言的struct(UDT, User Defined Type). Struct 和class : 在C ...

  9. Python入门篇-封装与解构和高级数据类型集合(set)和字典(dict)

    Python入门篇-封装与解构和高级数据类型集合(set)和字典(dict) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.封装和结构 #!/usr/bin/env pytho ...

随机推荐

  1. Deep Image Retrieval: Learning global representations for image search In ECCV, 2016学习笔记

    - 论文地址:https://arxiv.org/abs/1604.01325 contribution is twofold: (i) we leverage a ranking framework ...

  2. metasploit练习

    复现ms08_067_netapi 使用模块 msf5 > use exploit/windows/smb/ms08_067_netapi 查看配置 msf5 exploit(windows/s ...

  3. Mac 终端启动AVD模拟器

    cd ~/Library/Android/sdk/tools ./emulator -list-avds // 列出av列表 Nexus_5X_API_26 ./emulator @Nexus_5X_ ...

  4. JuJu团队11月26号工作汇报

    JuJu团队11月26号工作汇报 JuJu   Scrum 团队成员 今日工作 剩余任务 困难 于达 对原始文本进行预处理, 并转换成可被julia读入的格式 完成预处理并用julia读入. 读入后按 ...

  5. 实训30 延时中断组织块0B20仿真

    实训30 延时中断组织块的仿真试验   问题1 系统功能块SFC中提供了一些查询中断状态字的指令,举例说明 例如 SF34 "QRY_DINT" 用来查询 "延时中断&q ...

  6. 【转载】Asp .Net Web Api路由路径问题

    原文章地址:https://www.cnblogs.com/devtester/p/8897302.html MVC也好,WebAPI也好,据我所知,有部分人是因为复杂的路由,而不想去学的.曾经见过一 ...

  7. JavaWeb高级编程(下篇)

    Java标准标签库 JSP标签语法中包含一些简写可以帮助轻松编写JSP.这些简写中第一个就是taglib指令. <%@ taglib prefix="c" uri=" ...

  8. 剑指offer - 栈的压入弹出序列 - JavaScript

    题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列 1,2,3,4,5 是某栈的压入顺序,序列 4,5,3,2,1 ...

  9. Python 中 unittest 框架加载测试用例的常用方法

    unittest 当中为我们提供了许多加载用例的方法,这里说下常用的两种方法...推荐使用第二种 第一种加载测试用例的方法:使用加载器加载两个模块 需要把所有的模块加载到套件中 那么就可以自动的运行所 ...

  10. Git提交出现error: src refspec master does not match any的问题

    在本地与远程分别新建了一个仓库并且关联后,想要把本地的文件提交到github上面, 输入下方命令后没有成功,而是出现了报错:error: src refspec master does not mat ...