Go语言中的数组、切片和映射

以下内容都来源于Go语言101: 数组、切片和映射 -Go语言101

容器类型和容器值概述

每个容器(值)用来表示和存储一个元素(element)序列或集合。一个容器中的所有元素的类型是相同的。

我认为以上说的就是Go语言中的map和Java中的map是一样的,key和value都可以是任意值,比如Java中的对象。

一个数组或者切片的所有元素紧挨着存放在一块连续的内存中。一个数组中的所有元素均存放在此数组值的直接部分,一个切片中的所有元素均存放在此切片值的间接部分。一个映射中的所有元素也均存放在一块连续的内存中,但是映射中的元素并不一定紧挨着存放。

查看容器值的长度和容量

  • 数组的容量和它的长度是相等的,一个非零映射值的容量可以是无限的。
  • 可以调用内置函数len来获取长度,调用cap来获取容量。
  • 数组的长度和容量是不可变的,切片的长度和容量是动态改变的,可以认为是动态数组

读取和修改容器的元素

  package main

import "fmt"

func main() {
	a := [3]int{-1, 0, 1}
	s := []bool{true, false}
	m := map[string]int{"abc": 123, "xyz": 789}
	fmt.Println (a[2], s[1], m["abc"])    // 读取
	a[2], s[1], m["abc"] = 999, true, 567 // 修改
	fmt.Println (a[2], s[1], m["abc"])    // 读取

	n, present := m["hello"]
	fmt.Println(n, present, m["hello"]) // 0 false 0
	n, present = m["abc"]
	fmt.Println(n, present, m["abc"]) // 567 true 567
	m = nil
	fmt.Println(m["abc"]) // 0

	// 下面这两行编译不通过。
	/*
	_ = a[3]  // 下标越界
	_ = s[-1] // 下标越界
	*/

	// 下面这几行每行都会造成一个恐慌。
	_ = a[n]         // panic: 下标越界
	_ = s[n]         // panic: 下标越界
	m["hello"] = 555 // panic: m为一个零值映射
}

容器赋值

当一个映射赋值语句执行完毕之后,目标映射值和源映射值将共享底层的元素。 向其中一个映射中添加(或从中删除)元素将体现在另一个映射中。

和映射一样,当一个切片赋值给另一个切片后,它们将共享底层的元素。它们的长度和容量也相等。 但是和映射不同,如果以后其中一个切片改变了长度或者容量,此变化不会体现到另一个切片中。

当一个数组被赋值给另一个数组,所有的元素都将被从源数组复制到目标数组。赋值完成之后,这两个数组不共享任何元素。

package main

import "fmt"

func main() {
    // 映射
	m0 := map[int]int{0:7, 1:8, 2:9}
	m1 := m0
	m1[0] = 2
	fmt.Println(m0, m1) // map[0:2 1:8 2:9] map[0:2 1:8 2:9]

    // 切片
	s0 := []int{7, 8, 9}
	s1 := s0
	s1[0] = 2
	fmt.Println(s0, s1) // [2 8 9] [2 8 9]

    // 数组
	a0 := [...]int{7, 8, 9}
	a1 := a0
	a1[0] = 2
	fmt.Println(a0, a1) // [7 8 9] [2 8 9]
}

添加修改删除

如果没有就是添加,如果有就是修改

m[k] = e

如果有这个key就是删除,如果没有就是一个空操作,不会有任何影响

delete(m, k)

数组

一个数组中的元素个数总是恒定的,我们无法向其中添加元素,也无法从其中删除元素。但是可寻址的数组值中的元素是可以被修改的。

我们可以通过调用内置append函数,以一个切片为基础,来添加不定数量的元素并返回一个新的切片。 此新的结果切片包含着基础切片中所有的元素和所有被添加的元素。 注意,基础切片并未被此append函数调用所修改。

请注意,当一个append函数调用需要为结果切片开辟内存时,结果切片的容量取决于具体编译器实现。 在这种情况下,对于官方标准编译器,如果基础切片的容量较小,则结果切片的容量至少为基础切片的两倍。 这样做的目的是使结果切片有足够多的冗余元素槽位,以防止此结果切片被用做后续其它append函数调用的基础切片时再次开辟内存。

package main

import "fmt"

func main() {
	var s = append([]string(nil), "array", "slice")
	fmt.Println(s)      // [array slice]
	fmt.Println(cap(s)) // 2
	s = append(s, "map")
	fmt.Println(s)      // [array slice map]
	fmt.Println(cap(s)) // 4
	s = append(s, "channel")
	fmt.Println(s)      // [array slice map channel]
	fmt.Println(cap(s)) // 4
}

使用内置make函数来创建切片和映射

除了使用组合字面量来创建映射和切片,我们还可以使用内置make函数来创建映射和切片。 数组不能使用内置make函数来创建。

package main

import "fmt"

func main() {
	// 创建映射。
	fmt.Println(make(map[string]int)) // map[]
	m := make(map[string]int, 3)
	fmt.Println(m, len(m)) // map[] 0
	m["C"] = 1972
	m["Go"] = 2009
	fmt.Println(m, len(m)) // map[C:1972 Go:2009] 2

	// 创建切片。
	s := make([]int, 3, 5)
	fmt.Println(s, len(s), cap(s)) // [0 0 0] 3 5
	s = make([]int, 2)
	fmt.Println(s, len(s), cap(s)) // [0 0] 2 2
}

插入一条不相关的demo

package main

import "fmt"

func main() {
	ma := map[int][5]int{} // 创建一个key为int value为长度为5的整数数组
	ma[1] = [5]int{1: 789} // key为1,value数组索引1为789,其他索引为默认值
	fmt.Print(ma)
}
// 输出结果为:map[1:[0 789 0 0 0]]

使用内置clear函数来清空映射条目或者重置切片元素

package main

import "fmt"

func main() {
	s := []int{1, 2, 3}
	clear(s)
	fmt.Println(s) // [0 0 0]
	
	a := [4]int{5, 6, 7, 8}
	clear(a[1:3])
	fmt.Println(a) // [5 0 0 8]
	
	m := map[float64]float64{}
	x := 0.0
	m[x] = x
	x /= x // x变成了NaN
	m[x] = x
	fmt.Println(len(m)) // 2
	for k := range m {
		delete(m, k)
	}
	fmt.Println(len(m)) // 1
	clear(m)
	fmt.Println(len(m)) // 0
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ming__GoGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值