《Go程序设计语言》4 复合数据类型

数组

数组和所有其它语言一样,定长、元素具有相同数据类型

  • 声明 var a [3]int
    • 数组字面量初始化 var a [3]int = [3]int{1,2,3}
      • 可以不按顺序指定数组的初始化元素,这样未被指定的地方会被自动填0值var sex [...]string{1:"male",2:"femal"}这样sex[0]就是0值
    • 初始化时自动推断数组长度q := [...]int{1,2,3}
    • 数组的长度是常量表达式,必须在编译时就确定
    • 通过len(s)获得数组长度
  • 可以通过下标索引元素a[2]
  • 如果一个数组的元素类型是可比较的,那么数组也是可比较的,即按顺序逐一比较过去

slice

基本上可以视作一个std::vector<T>使用

slice表示一个拥有相同类型元素的可变长度序列,通常类型写作[]T

  • slice用来访问一个数组的全部或部分成员,该数组称为slice的底层数组

  • slice有三个属性

    • 指针:指针指向第一个slice访问的元素
    • 长度:指slice中元素的个数,可以使用len(s)获得
    • 容量:最大的可能长度,即从第一个能访问的1元素到底层数组末尾的长度,可以使用cap(s)获得
  • slice操作符s[i:j]表示引用序列s的左闭右开区间 [ i , j ) [i,j) [i,j)。省略i表示从头开始。省略j表示直到结尾

  • slice可以继续被slice引用,特别的,如果超出了原slice引用的范围,可以自动进行扩容

  • 由于slice是引用类型,当在函数中使用slice作为参数时,可以直接修改传入数组本身的数据

append 函数

将元素追加到slice后面,下面简单看一下实现

func appendInt(x []int, y int) []int {
	var z []int //结果变量
	zlen := len(x)+1 //该新slice应有的长度
	if zlen <= cap(x) { //原slice还能扩容
		z = x[:zlen] //扩容
	}else { //不能继续扩容原slice,分配一个新的底层数组
		zcap := zlen
		if zcap < 2*len(x) {
			zcap = 2*len(x) //增倍扩容
		}
		z = make([]int,zlen,zcap)
		copy(z,x)
	}
	z[len(x)] = y //将添加来的新元素复制
	return z
}

看一下用法

var x []int
x = append(x,1) //追加一个元素
x = append(x,1,2) //追加多个元素
x = append(x,x...) //追加x的所有元素

此时应该注意的是,该slice的底层数组可能处于不断的变化中

map

散列表,键值对,键的值是唯一的。值可以通过对应的值获取、更新、删除

map是散列表的引用,map的类型是map[键类型]值类型 。其中键的类型必须是可以通过==进行比较的类型

  • 初始化:
    • 使用make函数ages := make(map[sting]int)
    • 使用字面量ages := map[string]int("alice":31)
  • 通过下标访问值ages["alice"]
    • 键值不存在也没关系,会自动返回0值。比如ages["Bob"] +=1
    • 其实返回的是两个变量,其中第一个变量是键对应的值,第二个变量是布尔值,用来报告该元素是否存在age,flag = ages["Sb"]
  • 使用delete删除对应键的值delete(ages,"alice")
  • 使用for循环和range配合遍历一个map,注意遍历顺序是随机的,range返回的变量是 键,值 for age,name := range ages

Go语言没有提供集合类型,但是可以通过map实现一个集合,具体来说就是用键来储存集合的内容,map[类型]bool,每次插入时使用,map[元素]=true;检查集合是否有某元素时使用map[元素] == true

结构体

几乎和C完全一致,甚至必须使用type定义新类型也是一样的

type E struct {
	ID int
	name string
}

E e

使用.来获取成员,甚至可以使用.作用于结构体变量的指针来获取成员

注意结构体的成员也有可导出和不可导出的区别,这里的可否导出也是针对的包级别

结构体字面量

  • 或者是类C的,按顺序大括号
type Point struct{X,Y int}
p := Point{1,2}
  • 或者是按照成员名
type Point struct{X,Y int}
p := Point{Y:2,X:1}

结构体比较

如果结构体的所有成员变量可比较,则结构体也可比较,比较结果是逐成员比较的结果

结构体嵌套和匿名成员

给出一个未使用匿名成员的嵌套

type Point struct {
	X,Y int
}
type Circl struct {
	Center Point
	R int
}
type Wheel struct {
	Circle C
	Spokes int
}
var w Wheel

此时访问到X十分困难

w.C.Center.X = 1

通过在结构体声明中,给出一个不带名称的结构体成员,完成匿名成员的声明

type Point struct {
	X,Y int
}
type Circl struct {
	Center 
	R int
}
type Wheel struct {
	Circle 
	Spokes int
}
var w Wheel

此时可以不加指定中间变量的访问到底层

w.X = 1

其效果其实等价于

w.Circl.Point.X = 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值