zoukankan      html  css  js  c++  java
  • GO入门——4. 数组、切片与map

    1. 数组

    • 定义数组的格式:var [n],n>=0
    • 数组长度也是类型的一部分,因此具有不同长度的数组为不同类型
    • 注意区分指向数组的指针和指针数组
        //数组的指针
        a := [2]int{1, 2}
    	p := &a
    	fmt.Println(p)  //&[1 2]
    	
    	//指针数组
    	x, y := 1, 2
    	b := [2]*int{&x, &y}    //[0xc042034208 0xc042034220]
    	fmt.Println(b)
    
    • 数组在Go中为值类型
    • 数组之间可以使用==或!=进行比较,但不可以使用<或>
    • 可以使用new来创建数组,此方法返回一个指向数组的指针
    • Go支持多维数组
    	a := [2][3]int{
    		{1, 2, 3},
    		{4, 5, 6}}  //最后的}必须在这一行
    	fmt.Println(a)  //[[1 2 3] [4 5 6]]
    
    	//长度不同的数组类型不同
    	var a [2]int
    	var b [1]int
    	// a = b	编译错误:cannot use b (type [1]int) as type [2]int in assignment
    
    	//直接赋值
    	c := [2]int{1}             //第一个为1,第二个默认为0
    	d := [20]int{10: 1, 19: 2} //指定固定位置的值
    
    	//系统推断类型(长度)
    	e := [...]int{1, 2, 3}
    	f := [...]int{1, 2, 3, 19: -1}
    
    	//通过new创建指向数组的指针,都可以通过[]来获取和设置数组元素
    	p1 := new([2]int)
    	p1[1] = 1
    	fmt.Println(p1)	//&[0 1]
    	p2 := [2]int{}
    	p2[1] = 1	//[0 1]
    	fmt.Println(p2)
    

    2. 切片

    • 其本身并不是数组,它指向底层的数组

    • 作为变长数组的替代方案,可以关联底层数组的局部或全部
      为引用类型

    • 可以直接创建或从底层数组获取生成

    • 使用len()获取元素个数,cap()获取容量

    • 一般使用make()创建

    • 如果多个slice指向相同底层数组,其中一个的值改变会影响全部

    • make([]T, len, cap)

    • 其中cap可以省略,则和len的值相同

    • len表示存数的元素个数,cap表示容量

    2.1 reslice

    • Reslice时索引以被slice的切片为准
    • 索引不可以超过被slice的切片的容量cap()值
    • 索引越界不会导致底层数组的重新分配而是引发错误

    2.2 append

    • 可以在slice尾部追加元素
    • 可以将一个slice追加在另一个slice尾部
    • 如果最终长度未超过追加到slice的容量则返回原始slice
    • 如果超过追加到的slice的容量则将重新分配数组并拷贝原始数据
    //数组
    	a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
    	//slice
    	var s []int
    	//取从[5,len(a))的值放入slice
    	s = a[5:]
    	fmt.Println(s) //[6 7 8 9 0]
    	s[1] = 10      //slice是共享数组的,因此修改slice数组也会修改
    	fmt.Println(s) //[6 10 8 9 0]
    	fmt.Println(a) //[1 2 3 4 5 6 10 8 9 0]
    	//make的三个参数表示类型、len和cap
    	//当长度超过cap时,该slice的cap将乘以2将内存换一个位置,并将原始数据复制过去
    	ss := make([]int, 2, 3)
    	for i := 0; i < 10; i++ {
    		s1 := append(ss, i) //append的返回值需要注意,当赋值给新的slice时,ss将永远不会改变
    		fmt.Println(len(ss), cap(ss), ss)
    		fmt.Println(len(s1), cap(s1), s1)
    	}
    
    	//当slice重新分配内存后,对其值的修改不会影响到之前共享的数组
    	s2 := a[:2]
    	fmt.Println(s2)
    	s2 = append(s2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3)
    	s2[0] = 100
    	fmt.Println(a) //[1 2 3 4 5 6 10 8 9 0]
    
    	//copy,当长的复制到短的时只复制短的个数,当短的复制到长的时将短的完全复制到长的中
    	s3 := []int{1, 2, 3, 4, 5, 6}
    	s4 := []int{7, 8, 9}
    	copy(s3, s4)	//将s4复制到s3
    	fmt.Println(s3) //[7 8 9 4 5 6]
    	s3 = []int{1, 2, 3, 4, 5, 6}
    	copy(s4, s3)
    	fmt.Println(s4)	//[1 2 3]
    

    3 map

    • 类似其它语言中的哈希表或者字典,以key-value形式存储数据

    • Key必须是支持==或!=比较运算的类型,不可以是函数、map或slice

    • Map查找比线性搜索快很多,但比使用索引访问数据的类型慢100倍

    • Map使用make()创建,支持 := 这种简写方式

    • make([keyType]valueType, cap),cap表示容量,可省略

    • 超出容量时会自动扩容,但尽量提供一个合理的初始值

    • 使用len()获取元素个数

    • 键值对不存在时自动添加,使用delete()删除某键值对

    • 使用 for range 对map和slice进行迭代操作

    //声明与赋值,[]中为key类型,其后为value
    	var m map[string]int
    	m = map[string]int{}
    
    	//通过make创建与声明
    	var m1 = make(map[int]string)
    	m2 := make(map[int]string)
    	//对k-v取值与设值
    	m1[1] = "ok"
    	fmt.Println(m1[1]) //ok
    	delete(m1, 1)      //删除key
    	fmt.Println(m1[1]) //空
    	//多返回
    	a, ok := m1[2]
    	if !ok {
    		fmt.Println("没有key=2的value") //输出
    	}
    	fmt.Println(a, ok) //当不存在key时会返回空,ok=false
    	//复杂map
    	var mf map[int]map[string]int
    	mf = make(map[int]map[string]int) //初始化最外层map
    	mf[1] = make(map[string]int)      //初始化map[1]中的map,仅仅初始化key=1的map
    	mf[1]["ok"] = 3
    	fmt.Println(mf[1]["ok"])
    

    4 range

    //对于slice,i,v分别为index和slice下标对应的值,可以采用_将值忽略
    	s := []int{1, 2, 3}
    	for i, v := range s {
    		fmt.Println(i, v)
    		v = 10   //i,v为值的拷贝,修改不影响slice
    		s[i] = 0 //直接修改了slice
    	}
    	fmt.Println(s) //输出[0 0 0]
    
    	//对于map,k,v即为map中的key,value
    	//每次range的顺序可能不一样
    	m := map[int]string{
    		1: "ok"}
    	for k, v := range m {
    		fmt.Println(v)
    		m[k] = "okok"	//修改map中值也只能通过对m进行直接操作
    	}
    	fmt.Println(m)	//map[1:okok]
    
  • 相关阅读:
    POJ 1142 Smith Numbers
    POJ 1171 Letter Game 解题思路
    人人德克萨斯牌出手规则整理
    OpenMP相关知识索引
    如何进行有效的沟通
    台哥算法练习:一个for循环打印九九乘法表
    啊哈,381654729!
    发牌的小窍门
    判断数abcdef能否被k整除(k属于[2,9])
    如何在数轴上找到一个数的倒数
  • 原文地址:https://www.cnblogs.com/suolu/p/6714275.html
Copyright © 2011-2022 走看看