数组
数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成。因为数组的长度是固定的,因此在Go语言中很少直接使用数组。
数组声明方式:
#第一种 var balance [2] int balance =[2]int {1,2} #第二种 var ba = [3] int {1,2,3} #第三种 ba := [...] int {1,2,3} #数组可用索引访问,但是索引不支持负数
#第四种
r := [...]int{99: -1}#定义了一个含有100个元素的数组r,最后一个元素被初始化为-1,其它元素都是用0初始化
数组遍历:
#方法1 var ba = [...] int {1,2,3} for i:=0;i<len(ba);i++ { print(ba[i]) } #方法二 for key,value := range ba{ print(key) print(value) }
Slice
Slice(切片)代表变长的序列,序列中每个元素都有相同的类型。一个slice类型一般写作[]T,其中T代表slice中元素的类型;slice的语法和数组很像,只是没有固定长度而已。数组和slice之间有着紧密的联系。一个slice是一个轻量级的数据结构,提供了访问数组子序列(或者全部)元素的功能,而且slice的底层确实引用一个数组对象。一个slice由三个部分构成:指针、长度和容量。指针指向第一个slice元素对应的底层数组元素的地址,要注意的是slice的第一个元素并不一定就是数组的第一个元素。长度对应slice中元素的数目;长度不能超过容量,容量一般是从slice的开始位置到底层数据的结尾位置。内置的len和cap函数分别返回slice的长度和容量。多个slice之间可以共享底层的数据,并且引用的数组部分区间可能重叠。
slice 声明
切片不需要说明长度: var identifier []type make 可以用来声明切片 var slice1 []type = make([]type, len) 简写也可以简写为slice1 := make([]type, len) 也可以指定容量,其中capacity为可选参数。 make([]T, length, capacity) s :=[] int {1,2,3 } 直接初始化切片,[]表示是切片类型,{1,2,3}初始化值依次是1,2,3.其cap=len=3 s := arr[:] 初始化切片s,是数组arr的引用 s := arr[startIndex:endIndex] 将arr中从下标startIndex到endIndex-1 下的元素创建为一个新的切片 s := arr[startIndex:] 默认 endIndex 时将表示一直到arr的最后一个元素 s := arr[:endIndex] 默认 startIndex 时将表示从arr的第一个元素开始 s1 := s[startIndex:endIndex] 通过切片s初始化切片s1 s :=make([]int,len,cap) 通过内置函数make()初始化切片s,[]int 标识为其元素类型为int的切片 注意:如果切片操作超出cap(s)的上限将导致一个panic异常,但是超出len(s)则是意味着扩展了slice,因为新slice的长度会变大,
因为slice值包含指向第一个slice元素的指针,因此向函数传递slice将允许在函数内部修改底层数组的
元素。换句话说,复制一个slice只是对底层的数组创建了一个新的slice
为何slice不直接支持比较运算符呢?这方面有两个原因。第一个原因,一个slice的元素是间接引用的,一个slice甚至可以包含自身。虽然有很多办法处理这种情形,但是没有一个是简单有效的。第二个原因,因为slice的元素是间接引用的,一个固定值的slice在不同的时间可能包含不同的元素,因为底层数组的元素可能会被修改。并且Go语言中map等哈希表之类的数据结构的key只做简单的浅拷贝,它要求在整个声明周期中相等的key必须对相同的元素。对于像指针或chan之类的引用类型,==相等测试可以判断两个是否是引用相同的对象。一个针对slice的浅相等测试的==操作符可能是有一定用处的,也能临时解决map类型的key问题,但是slice和数组不同的相等测试行为会让人困惑。因此,安全的做饭是直接禁止slice之间的比较操作。slice唯一合法的比较操作是和nil比较,一个零值的slice等于nil。一个nil值的slice并没有底层数组。一个nil值的slice的长度和容量都是0,但是也有非nil值的slice的长度和容量也是0的,例如[]int{}或make([]int,3)[3:]。与任意类型的nil值一样,我们可以用[]int(nil)类型转换表达式来生成一个对应类型slice的nil值。如果你需要测试一个slice是否是空的,使用len(s) == 0来判断,而不应该用s ==nil来判断。除了和nil相等比较外,一个nil值的slice的行为和其它任意0产长度的slice一样;例如reverse(nil)也是安全的。除了文档已经明确说明的地方,所有的Go语言函数应该以相同的方式对待nil值的slice和0长度的slice。内置的make函数创建一个指定元素类型、长度和容量的slice。
slice append操作:
func main() { var x, y []int for i := 0; i < 10; i++ { y = append(x, i) fmt.Printf("%d cap=%d %v ", i, cap(y), y) x = y } } 0 cap=1 [0] 1 cap=2 [0 1] 2 cap=4 [0 1 2] 3 cap=4 [0 1 2 3] 4 cap=8 [0 1 2 3 4] 5 cap=8 [0 1 2 3 4 5] 6 cap=8 [0 1 2 3 4 5 6] 7 cap=8 [0 1 2 3 4 5 6 7] 8 cap=16 [0 1 2 3 4 5 6 7 8] 9 cap=16 [0 1 2 3 4 5 6 7 8 9]
通常我们并不知道append调用是否导致了内存的重新分配,因此我们也不能确认新的slice和原始的slice是否引用的是相同的底层数组空间。同样,我们不能确认在原先的slice上的操作是否会影响到新的slice。因此,通常是将append返回的结果直接赋值给输入的slice变量:runes = append(runes, r)
map
哈希表是一种巧妙并且实用的数据结构。它是一个无序的key/value对的集合,其中所有的key都是不同的,然后通过给定的key可以在常数时间复杂度内检索、更新或删除对应的value。一个map就是一个哈希表的引用,map类型可以写为map[K]V,其中K和V分别对应key和value。map中所有的key都有相同的类型,所以的value也有着相同的类型,但是key和value之间可以是不同的数据类型。其中K对应的key必须是支持==比较运算符的数据类型,所以map可以通过测试key是否相等来判断是否已经存在。虽然浮点数类型也是支持相等运算符比较的,但是将浮点数用做key类型则是一个坏的想法,最坏的情况是可能出现的NaN和任何浮点数都不相等。对于V对应的value数据类型则没有任何的限制。
内置的make函数可以创建一个map: ages := make(map[string]int) 我们也可以用map字面值的语法创建map,同时还可以指定一些最初的key/value: ages := map[string]int{ "alice": 31, "charlie": 34, } 这相当于 ages := make(map[string]int) ages["alice"] = 31 ages["charlie"] = 34 创建空的map的表达式是map[string]int{}
结构体
结构体是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体。每个值称为结构体的成员。
type Employee struct { ID int Name string Address string DoB time.Time Position string Salary int ManagerID int } 1, var dilbert Employee
2, a := Employee{"ID":1}
如果要在函数内部修改结构体成员的话,用指针传入是必须的;因为在Go语言中,所有的函数参数都是
值拷贝传入的,函数参数将不再是函数调用时的原始变量。
如果结构体的全部成员都是可以比较的,那么结构体也是可以比较的,那样的话两个结构体将可以使用==或!=运算符进行比较。相等比较运算符==将比较两个结构体的每个成员