Go语言数组和切片的坑点记录

       虽说golang的数组和切片使用简单,但是当你编码到一定量的时候,你就会发现原来简单的数组和切片也有很多坑点啊,下面就记录了我实际工作中的采坑点,话不都说直接上代码,各种注意点都在代码注释里了。

package main

import "fmt"

func main() {
	test01()
	//test02()
	test03()
	test04()
	test05()
	//test06()
	test07()
}

/*
  下标索引操作的一些误区 s[i:l:c] i 是起始偏移的起始位置,l 是起始偏移的长度结束位置, l-i 就是新 slice 的长度,
  c 是起始偏移的容量结束位置,c-i 就是新 slice 的容量。其中 i 、l 、c 并不是当前 slice 的索引,而是引用底层数组
  相对当前 slice 起始位置的偏移量,所以是可超出当前 slice 的长度的, 但不能超出当前 slice 的容量,具体请看test01, test02
*/
func test01() {
	mySlice := []string{"21"}
	//mySlice := [1]string{"21"} // 数组也和切片一样
	//fmt.Println("Result1:", mySlice[1]) // 数组越界, panic
	// 下面这行代码是正确的,不会发生数组越界问题
	fmt.Println("Result2:", mySlice[1:])
}

func test02() {
	s := make([]string, 100)
	s[20] = "100"
	s1 := s[10:10]
	s2 := s1[10:20]
	s3 := s[100:100]
	s4 := s[100:102] // 数组越界, panic
	fmt.Println(s1)
	fmt.Println(s2)
	fmt.Println(s3)
	fmt.Println(s4)
}

func test03() {
	//mySlice := make([]string, 2, 3) // 这条语句是创建一个长度为2且容量为3的, 并且含有两个空字符串的切片, 当append一个元素时不会重新分配内存
	mySlice := make([]string, 2) // 这条语句创建了一个长度和容量都为2的, 并且含有两个空字符串的切片
	fmt.Println(len(mySlice), cap(mySlice))
	mySlice = append(mySlice, "21") // 当新添加一个元素的时候,原来2的容量已经不够,所以需要重新分配一个长度是原来2倍的空间
	fmt.Printf("Content:%s, Len:%d, Cap:%d\n", mySlice, len(mySlice), cap(mySlice))
}

/*
  切片的append操作有一个特殊的地方, 当是字节切片时, 可以append一个字符或字符串, 具体如下:
*/
func test04() {
	hisSlice := make([]byte, 10, 20)
	hisSlice = append(hisSlice, 'd')
	//hisSlice = append(hisSlice, 'd'...) // 不合法
	hisSlice = append(hisSlice, []byte{'d'}...)
	hisSlice = append(hisSlice, 'd', 'e')
	hisSlice = append([]byte("Tokyo"), "London"...)
	hisSlice = append(hisSlice, "Tokyo"...)
	//hisSlice=append(hisSlice,"Singapore","NewYork"...) // 不合法
	fmt.Println("hisSlice:", string(hisSlice))
}

func test05() {
	slice := []string{"1", "2", "3", "4", "5", "6"}
	fmt.Println("Slice:", slice)

	sli := slice[:] // 引用一个切片
	fmt.Println("sli:", sli)

	slice = slice[:0] // 清空一个切片
	fmt.Println("Slice:", slice)
}

/*
  从数组或切片中截取切片:
  1.若没有指定max, max的值为截取对象(数组/切片)的容量
  2.若指定max, max值不能超过原对象(数组/切片)的容量
  3.利用数组创建切片, 切片操作的是同一个底层数组
  具体例子如下:
*/
func test06() {
	mySlice := []string{"1", "2", "3", "4", "5", "6"}
	mySlice = append(mySlice, []string{"1", "2", "3"}...) // 附加切片

	hisSlice := mySlice[1:6:13] // 13超过了原切片的容量, 所以会panic
	//hisSlice := mySlice[1:5:5]
	//hisSlice := mySlice[1:5]  // 未指定max, 则max为原切片最大容量

	fmt.Println("MySliceCap:", cap(mySlice))
	fmt.Println("HistSliceCap:", cap(hisSlice))
}

func test07() {
	arr := [3]string{"1", "2", "3"}
	//arr = append(arr, "3") // 数组不可以使用append方法
	//fmt.Println(len(arr), cap(arr)) // 数组可以使用len,cap方法

	//var arr1 []string // 使用copy的切片必须是有长度的, 这种nil的切片会拷贝为空
	//arr1 := make([]string, 0, 10) // 使用copy的切片必须是有长度的, 这种零长度的切片会拷贝为空
	arr1 := make([]string, 1)
	//arr1 := make([]string, 6)
	n := copy(arr1, arr[:]) // n: 返回的是实际被拷贝的元素数量
	fmt.Println("arr1:", arr1, "len:", n)

	// 特殊的地方是可以把字符串或字符拷贝到字节切片中, 
    // 并且拷贝的顺序是从前到后,例子如下:
	arr2 := make([]byte, 2, 4)
	copy(arr2, "Tokyo")
	copy(arr2, []byte{'A'})
	fmt.Println("arr2:", string(arr2))
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值