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]
    
  • 相关阅读:
    苹果一体机发射Wi-Fi
    iphone 屏蔽系统自动更新,消除设置上的小红点
    data parameter is nil 异常处理
    copy与mutableCopy的区别总结
    java axis2 webservice
    mysql 远程 ip访问
    mysql 存储过程小问题
    mysql游标错误
    is not writable or has an invalid setter method错误的解决
    Struts2中关于"There is no Action mapped for namespace / and action name"的总结
  • 原文地址:https://www.cnblogs.com/suolu/p/6714275.html
Copyright © 2011-2022 走看看