go - 复合类型 array, slice, map

chuangrain · · 3135 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Go 语言支持复合类型:
  •   数组:array
  •   切片:slice
  •   指针:pointer
  •   字典:map
  •   通道:chan
  •   结构体:struct
  •   接口:interface

1. array
  同一类型数据的集合
    var arr [n]type    //声明type类型一维数组
    var arr [m][n]type //声明type类型二维数组
    多维数组以此类推
    也可以用 := 声明
    arr := [n]type{元素1[,元素2, ...]} 其中n可以用 "..." 三个点表示,系统会根据元素个数来确定
  下标只能为 int 类型,而 php 还支持 string 类型的下标
  1.1 数组长度 len(arr)
    注:数组长度在定义后就不可变
  1.2 遍历:
    a
. 循环通过过数组下标访问 arr[0] ~ arr[(len(arr))]
    b. range arr, 有两个返回值 第一个为数组下标,第二个为元素的值,与php遍历数组相似
    for k, v := range array {
        fmt.Printf("arr[%d] = %d \t", k, v)
    }
    foreach ($arr as $k => $v) {
        printf("arr[%d] = %d \t", $k, $v);
        //echo '$arr[' . $k . "] = " . $v . "\t";
    }
  1.3 数组在赋值与传递参数时,都会产生一个数组副本,而不是使用它的指针

2. slice
  在定义 array 时,其长度是固定的,并且 array 是一个值类型
  而 slice 是一个可变的数组,但是一个引用类型
  2.1 产生slice的三种方式
    a
. 声明与 array 一样,不过不需要指定长度
    var slice1 []int
    slice2 := []int {元素1[, 元素2, ...]}
    b. 从数组(或者切片或者字符串)中获取 arr[i:j] i=数组的开始位置,j=结束位结果,j-i=切片的长度,i和j都可以省略,省略时 i=0, j=len(arr),i是从0开始,j是从1开始
      a b c d e f
    i 0 1 2 3 4 5
    j 1 2 3 4 5 6
    slice1 := arr[:]    //arr[0:6]/arr[0:]
    slice2 := arr[1:1]  //[]
    slice4 := arr3[1:3] //b c
    slice5 := arr3[:5]  // = arr3[0:5]
    c. make
    slice1 := make([]int, 5, 10)
    len(slice1) = 5, cap(slice1) = 10, 元素的初始值为0
  2.2 相关函数
    len
(slice): 返回 slice 的元素个数(长度)
    cap(slice): 返回 slice 的分配空间大小
    append(slice1, slice2...): 把 slice2 追加到 slice1 产生新的 slice, 若 slice2 是变量时,不能省略...,相当于 append(slice1, a[, b, ...])
    copy(目标slice, 源slice): 以最小的切片元素个数为准,将源 slice 复制到 目标 slice
  2.3 cap - len = 0 时,系统将动态分配新的数组空间,即切片会自动处理存储空间不足的问题
  2.4 遍历与 array 一样
  2.5 在传递参数时,传递的为指针


3. map
  在Java/python等语言中都有提供
  暂时可以理解为:一张无序的表
  其长度也不固定,也是引用类型,在赋值与传参过程中,指向同一地址
  key1 value1
  key2 value2
  ...   ...
  3.1 声明与创建
    var map变量名 map[键type] 值type //键type可以为int或者string,值type,需要make初始化
    map变量名 = make(map[键type] 值type)
    //或者
    map变量名 := make(map[键type] 值type) [{键1:值1}[,{键2:值2},...}] //[]中为可选
  3.2 相关操作
    赋值: map变量名[键] = 值
    读取: map变量名[键]      //如果键不存在,返回nil
    删除键值对: delete(map变量名, 键)  //如果键不存在,无影响
    取map的元素个数: len(map变量名)

    不能用cap函数

note_type_2.go code list

package main

import "fmt"

func main() {
	//先声明后赋值
	var arr [3]int
	//arr = {1, 2, 3} //不能这样赋值给数组
	arr[0] = 1
	arr[1] = 2
	arr[2] = 3
	//arr[3] = 4      //compile error: index out of bounds
	fmt.Println(arr[0], arr[0:2]) //输出 1 [1 2]

	//arr1 := [3]int{4, 5, 6}
	arr1 := [...]int{4, 5, 6} //和上面结果一样
	fmt.Printf("arr[1] = %d \n", arr1[1]) //输出 arr[1] = 5

	//遍历数组
	for i := 0; i < len(arr); i++ {
		fmt.Printf("arr[%d] = %d \t", i, arr[i])
	}
	fmt.Println()
	for k, v := range arr1 {
		fmt.Printf("arr[%d] = %d \t", k, v)
	}
	fmt.Println()
	changeValue(arr1)
	fmt.Println("result: ", arr1) //result: [4 5 6] 值不发生改变

	//二维数组
	arr2 := [2][3]int{{1, 2}, {4, 5, 6}}
	fmt.Println("len(arr2) = ", len(arr2))        //len(arr2) = 2
	fmt.Println("len(arr2[0]) = ", len(arr2[0]))  //len(arr2[0]) = 3
	for i, v := range arr2 {
		fmt.Println(i, v)
	}
	for i1, v1 := range arr2 {
		for i2, v2 := range v1 {
			fmt.Printf("arr2[%d][%d] = %d \t", i1, i2, v2)
		}
		fmt.Println()
	}

	//slice
	slice1 := []byte {'b', 'b'}
	slice1[0] = 'a' //如果只声明了slice,无元素时,直接通过下标赋值会compile error
	fmt.Printf("slice1[0] = %c \n", slice1[0])  //slice1[0] = a
	
	arr3 := [...]byte {'a', 'b', 'c', 'd', 'e', 'f'}
	slice2 := arr3[:]   // = arr3[0:]
	fmt.Println("slice2 = ", slice2)
	slice3 := arr3[1:1] //空
	fmt.Println("slice3 = ", slice3)
	slice4 := arr3[1:3] //b c
	fmt.Println("slice4 = ", slice4)
	slice5 := arr3[:5]  // = arr3[0:5]
	fmt.Println("slice5 = ", slice5)
	slice6 := slice5[1:2] //b
	fmt.Println("slice6 = ", slice6)
	str := "hello"
	slice7 := str[4:5]  //o
	fmt.Printf("slice7[0] = %s \n", slice7) //slice7[0] = o

	fmt.Println("len(slice4) = ", len(slice4)) //len(slice4) = 2
	fmt.Println("cap(slice4) = ", cap(slice4)) //cap(slice4) = 5
	//slice8 := append(slice4, 'a', 'd')       //b c a d
	slice9 := []byte {'a', 'b'}
	slice8 := append(slice4, slice9...)        //b c a d = append(slice4, 'a', 'b')
	fmt.Printf("slice8[2] = %c \n", slice8[2]) //slice8[2] = a
	fmt.Println("len(slice8) = ", len(slice8)) //len(slice8) = 4
	slice10 := []byte {'x', 'y', 'z'}
	copy(slice10, slice9)
	for i, v := range slice10 {
		fmt.Printf("slice10[%d] = %c \t", i, v) //a b z
	}
	fmt.Println()
	/*
	//slice9 = a, b; slice10 = x, y,z 
	copy(slice9, slice10)
	for i, v := range slice9 {
		fmt.Printf("slice9[%d] = %c \t", i, v)  //x y 
	}
	*/

	s1 := make([]int, 5, 10)
	fmt.Println("len, cap = ", len(s1), ", ", cap(s1)) //len, cap = 5, 10

	s2 := []int {1, 2, 3}
	changeValue2(s2)
	fmt.Println("result2: ", s2) //result2: [5 2 3] 结果会发生改变

	//map
	var map1 map[string] string
	//map1["a"] = "123" //如果不初始化,会出现异常 panic: runtime error: assignment to entry in nil map
	map1 = make(map[string] string)
	map1["a"] = "123"
	fmt.Println("map1 = ", map1)  //map1 = map[a:123]
	fmt.Println(map1["b"])        // (nil)
	b, found := map1["b"]         //found 为 bool 值, true = found
	if found {
		fmt.Println("found, and the value = ", b)
	} else {
		fmt.Println("not found")
	}
	map1["b"] = "456"
	fmt.Println("map1 = ", map1)  //map1 = map[a:123 b:456]
	delete(map1, "b")             //删除键为"a"的键值对
	fmt.Println("map1 = ", map1)  //map1 = map[b:456]
	fmt.Println("len(map1) = ", len(map1)) //len(map1) = 1
	//fmt.Println("cap(map1) = ", cap(map1)) // invalid argument map1 (type map[string]string) for cap

	map2 := map1
	map2["a"] = "789"
	fmt.Println("map1 = ", map1) //map1 = map[a:789],其值为发生改变,因为map2和map1是同一地址空间
}


func changeValue(arr [3]int) {
	arr[0] = 100
	fmt.Println("changeValue: ", arr) //changeValue: [100 5 6]
}

func changeValue2(slc []int) {
	slc[0] = 5
	fmt.Println("changeValue2: ", slc) //changeValue2: [5 2 3]
}

运行结果:



有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:chuangrain

查看原文:go - 复合类型 array, slice, map

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

3135 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传