本文是对极客时间-go语言的学习记录和自己的一些理解,如有侵权请联系删除。

1. 数组和切片

GO语言的array和slice属于集合类型,都是某一类数据的集合,不同的是数组的长度是固定的,而切片是可以改变长度的

定义

image.png

数组的长度在定义是必须显示的指定,并且定义之后不在改变。而切片指指定了数据的类型,没有长度,切片的长度可以自动的随着其元素的数量增长而增长,但不会随这元素的数量减少而减小。

数组的定义

  1. func main() {
  2. var arr[3] int
  3. arr1 := [4] int {1,2,3,4}
  4. arr2 := [...]int{1,2,3,4,5} //...自动计算数组的长度
  5. }

切片的定义:

  1. var s0 []int
  2. s1 := []int{1,2,3,4,5}

长度和容量

  1. 我们可以通过内联函数len得到数组和切片的长度, 通过cap他们的容量. 长度是数组/切片实际存储元素的个数,容量代表这他们可以存储元素的大小。<br />切片可以看做事对数组某段数据的引用,切片的底层数据结构还是数组。举个列子:
  1. s3 := []int{1, 2, 3, 4, 5, 6, 7, 8}
  2. s4 := s3[3:6]
  3. fmt.Printf("The length of s4: %d\n", len(s4))
  4. fmt.Printf("The capacity of s4: %d\n", cap(s4))
  5. fmt.Printf("The value of s4: %d\n", s4)

image.png

通过一个列子来看slice长度增加的规律

  1. func TestSliceGrowing(t *testing.T) {
  2. s := []int{}
  3. for i := 0; i < 10; i++ {
  4. s = append(s, i)
  5. t.Log(len(s), cap(s))
  6. }
  7. }

输出如下:

  1. === RUN TestSliceGrowing
  2. sliec_test.go:11: 1 1
  3. sliec_test.go:11: 2 2
  4. sliec_test.go:11: 3 4
  5. sliec_test.go:11: 4 4
  6. sliec_test.go:11: 5 8
  7. sliec_test.go:11: 6 8
  8. sliec_test.go:11: 7 8
  9. sliec_test.go:11: 8 8
  10. sliec_test.go:11: 9 16
  11. sliec_test.go:11: 10 16

一个切片如果无法容纳更多的元素,GO语言就会想办法扩容,他不会改变原先的切片,而是会自动生成一个容量更大的切片, 然后将原有的元素和新元素一并copy到新的切片中。在一般情况下,简单的认为新切片的容量将会是原切片的容量的2倍.
但是,当原切片的长度(以下简称原长度)大于或等于1024时,Go 语言将会以原容量的1.25倍作为新容量的基准(以下新容量基准)。新容量基准会被调整(不断地与1.25相乘),直到结果不小于原长度与要追加的元素数量之和(以下简称新长度).

2. Map

映射是方便而强大的内联数据结构, 它可以关联不同的类型的值。其建可以是任何支持比较的的类型,如整数,浮点型,字符串,指针,接口(需要其动态类型支持相等性判断),结构和数组。目前切片还不支持作为映射键值。与切片相同,映射也是引用类型.(变量指向同一块内存,其中一个引用改变其类型,对其他的引用也可见)

  • 定义
    1. var timeZone = map[string]int{
    2. "UTC": 0*60*60,
    3. "EST": -5*60*60,
    4. "CST": -6*60*60,
    5. "MST": -7*60*60,
    6. "PST": -8*60*60,
    7. }
    获取定义的值
    1. offset := timeZone["EST"]
    若试图通过不存在的建来取值,就会返回与该映射中项类型对应的的零值,如果某个映射包含的整数,则获取不存在的键值返回的结果就是0; 如果是bool类型,返回的就是false ```go attended := map[string]bool{ “Ann”: true, “Joe”: true, … }

if attended[person] { // will be false if person is not in the map fmt.Println(person, “was at the meeting”) }

  1. 如果要区分某个键值的对应的值,是不存在还是定义的就是零值,Go语言通过一个bool值来区分
  2. ```go
  3. func offset(tz string) int {
  4. if seconds, ok := timeZone[tz]; ok { //通过返回ok,来判断是否存在
  5. return seconds
  6. }
  7. log.Println("unknown time zone:", tz)
  8. return 0
  9. }

通过for range结构来遍历整个map

  1. func TestTravelMap(t *testing.T) {
  2. m1 := map[int]int{1: 1, 2: 4, 3: 9}
  3. for key, v := range m1 {
  4. t.Log(key, v)
  5. }
  6. }

输出

  1. map_test.go:31: 1 1
  2. map_test.go:31: 2 4
  3. map_test.go:31: 3 9

引用文档

极客时间—GO语言核心36讲
Effective Go