欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

复合数据类型

程序员文章站 2022-07-16 19:32:29
...

复合数据类型

主要内容

  1. 重点介绍以下四种常用复合数据类型:

    • 数组
    • slice
    • map
    • 结构体

    数组和结构体的长度是固定的;slice和map都是动态数据结构,它们的长度在元素添加到结构体中时可以动态增长

  2. 使用这些数据类型构成的结构化数据编码为json数据,从json数据转换为结构化数据

数组

数组是一个由固定长度且多个相同数据类型元素的序列。因此,无法添加或者删除元素。

声明方式:

// 第一种声明,初始化方式
var q [3]int = [3]int{1, 2, 3}

// 第二种:...表示数组的长度由初始化元素的个数决定
q := [...]int{1, 2, 3}

数组的长度也是数组类型的一部分

// [3]int和[4]int是两种不同的数组类型
q := [3]int{1, 2, 3}
// 编译报错,理由如上
q = [4]int{1, 2, 3, 4} 

数组初始化:

// 初始化索引的顺序是无关紧要的
type Currency int
const (
    USD Currency = iota // 美元
    EUR // 欧元
    GBP // 英镑
    RMB // 人民币
) 
symbol := [...]string{USD: "$", EUR: "€", GBP: "£", RMB: "¥"}
fmt.Println(RMB, symbol[RMB])

// 定义了一个含有100个元素的数组r,最后一个元素被初始化为-1,其它元素都是用0初始化。
r := [...]int{99: -1}

数组间的比较:数组类型和元素类型确定能不能比较;元素相等决定数组相等

a := [2]int{1, 2}
b := [...]int{1, 2}
c := [2]int{1, 3}
// a与b数组类型相同,元素类型相同,可比较
// a与b的各个元素相等,则a与b相等
// a与c,b与c,数组类型相同,元素类型相同,元素不相等
fmt.Println(a == b, a == c, b == c) // "true false false"
d := [3]int{1, 2}
// 编译错误,数组类型不同,不能比较
fmt.Println(a == d) 

函数调用参数传递:Go把数组和其他的类型都看成值传递,而在其他语言中,数组是隐式的使用引用传递

显式地传入一个数组指针,那样的话函数通过指针对数组的任何修改都可以直接反馈到调用者。

func zero(ptr *[32]byte) {
    //  ptr是指针变量,使用range只返回一个索引?
    for i := range ptr {
        // 将ptr数组清零
        ptr[i] = 0
    }
}

// 另一种清零写法
func zero(ptr *[32]byte) {
    // [32]byte{}生成一个有你32字节元素的数组
    // 数组中每个元素的值是字节类型的零值,即0.
    // 
    *ptr = [32]byte{}
}

使用指针:1.高效。 2.允许被调函数修改调用方数组中的元素。

slice

Slice(切片)代表变长的序列,序列中每个元素都有相同的类型。

slice的底层是数组,一个底层数组可以对应多个slice。
months是底层数组,Q2和summer是slice。
复合数据类型

slice 属性:

- 指针:指向第一个slice元素对应的底层数组元素的地址,要注意的是slice的第一个元素并不一定就是数组的第一个元素
- 长度:slice中元素的个数
- 容量:一般是从slice的**开始位置**到**底层数据的结尾位置**

slice操作符:左闭右开

// s即序列或底层数组。引用了s的i到j-1索引位置的元素
// 切片长度为:j-i
s[i:j]
// 引用了s的位置i到最后一个索引的元素
s[i:]
// 引用了s从0到j-1索引的元素。
s[:j]
// 引用整个数组
s[:]

引用异常:panic异常和slice扩容

// 根据上图的显示,months有13个元素。
// 初始化时,使用了 索引号:值的方式初始化。
months := [...]string{1: "January", /* ... */, 12: "December"}
// summer引用了months数组的6-8的元素。
// 其中指针指向6,长度为3,容量为7(指针开始位置为6,底层数组的结束位置为12.)
summer := months[6:9]
// panic 异常,引用超过了被引用对象summer的容量。导致宕机
fmt.Println(summer[:20]) 
// endlessSummer的引用超出了被引用对象summer的长度3。
// 因此endlessSummer**长度**会扩展到5.应用也会变为
// 从6-11
endlessSummer := summer[:5] 

数组与slice初始化一点区别:

// 数组有固定长度
a := [...]int {0,1,2,3,4,5}
// slice无固定长度
s := []int{0,1,2,3,4,5}

slice无法直接使用==做比较:slice的元素是非直接的,它可以包含自身;底层数组元素改变,同一个slice在不同的时间会有不同的元素。

slice允许的比较操作:和nil比较。

检查slice为空:使用len(s) == 0,而非 s==nil

make创建slie:

// 长度和容量相等
make([]T, len)
// 指定长度和容量
make([]T, len, cap)