go 数组(array)和切片(slice)

数组Array

和以往的数组有很大的不同

  • 数组时值类型,复制和传参会复制整个数组,而不是指针
  • 数组长度必须是常量,且是类型的组成部分。[2]int[3]int是不同的数据类型
  • 支持 == 和 != 操作符
  • 指针数组[n]*T 数组指针 *[n]T
  • 可用符合语句初始化。
package main  
  
import "fmt"  
  
func main() {  
   a := [3]int{1, 2}           // 未初始化元素值为 0。  
   b := [...]int{1, 2, 3, 4}   // 通过初始化值确定数组长度。  
   c := [5]int{2: 100, 4: 200} // 使用索引号初始化元素。  
   //复合语句初始化  
   d := [...]struct {  
      name string  
      age  uint8  
   }{  
      {"user1", 10}, // 可省略元素类型。  
      {"user2", 20}, // 别忘了最后一行的逗号。  
   }  
   fmt.Println(a)  
   fmt.Println(b)  
   fmt.Println(c)  
   fmt.Println(d)  
   }

输出:

[1 2 0]
[1 2 3 4]              
[0 0 100 0 200]        
[{user1 10} {user2 20}]

多维数组:

package main  
  
import "fmt"  
  
func main() {  
   a := [2][3]int{{1, 2, 3}, {4, 5, 6}}  
   b := [...][2]int{{1, 1}, {2, 2}, {3, 3}}  
   fmt.Println(a)  
   fmt.Println(b)  
}

输出:

[[1 2 3] [4 5 6]]
[[1 1] [2 2] [3 3]]

Slice 切片

slice不是数组或者数组指针,他是通过内部指针和相关属性引用数组片段,以实现变长方案的
(理解成一个变长数组)

他是一个引用类型

package main  
  
import "fmt"  
  
func main() {  
   data := []int{1, 2, 3, 4, 5, 6, 7, 8}  
   slice := data[1:4:8]  // [low : high : max]
   fmt.Println(slice)  
   fmt.Println(len(slice))  
   fmt.Println(cap(slice))  
}

输出:

[2 3 4]
3
7

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xOMTFk2z-1673265973748)(../images/Pasted%20image%2020230109162238.png)]

len计算的是可用元素的数量,cap是计算最大的容量

三个值的灵活应用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z1b1SElD-1673265973749)(../images/Pasted%20image%2020230109162458.png)]

读写操作:

package main  
  
import "fmt"  
  
func main() {  
   data := [...]int{1, 2, 3, 4, 5, 6, 7, 8}  
  
   s := data[2:4] //【3,4】  
   s[0] += 100  
   s[1] += 200  
   fmt.Println(s)  
   fmt.Println(data)  
}

可以知道读写操作实际是底层的数组。

package main  
  
import "fmt"  
  
func main() {  
   s1 := []int{0, 1, 2, 3, 8: 100} // 通过初始化表达式构造,可使用索引号。  
   fmt.Println(s1, len(s1), cap(s1))  
   s2 := make([]int, 6, 8) // 使用 make 创建,指定 len 和 cap 值。  
   fmt.Println(s2, len(s2), cap(s2))  
   s3 := make([]int, 6) // 省略 cap,相当于 cap = len。  
   fmt.Println(s3, len(s3), cap(s3))  
  
}

输出:

[0 1 2 3 0 0 0 0 100] 9 9
[0 0 0 0 0 0] 6 8
[0 0 0 0 0 0] 6 6

切片个各种创建方式

切片与指针:

s := []int{0, 1, 2, 3}

p := &s[2]                        // *int, 获取底层数组元素指针。
*p += 100

fmt.Println(s)

输出:

[0 1 102 3]

``[][]T,是指元素类型为 []T

data := [][]int{
    []int{1, 2, 3},
    []int{100, 200},
    []int{11, 22, 33, 44},
}

可直接修改 struct array/slice 成员。

d := [5]struct {
    x int
}{}

s := d[:]

d[1].x = 10
s[2].x = 20

fmt.Println(d)
fmt.Printf("%p, %p\n", &d, &d[0])

输出:

[{0} {10} {20} {0} {0}]
0x20819c180, 0x20819c180

append

在slice的尾部添加数据,返回新的slice对象

package main  
  
import "fmt"  
  
func main() {  
   s := make([]int, 0, 5)  
   fmt.Printf("%p\n", &s)  
  
   s2 := append(s, 1)  
   fmt.Printf("%p\n", &s2)  
  
   fmt.Println(s, s2)  
  
   s3 := append(s2, 2, 3)//可以添加多个值  
   fmt.Println(s3)  
}

输出:

0xc000008078
0xc000008090
[] [1]    

可以看到两次的内存地址不一样了
可以一次添加多个值

一旦append的数据超过了切片的cap值,也就是最大容量,底层就会重新分配一个数组,就和原来的数组无关了
例如:

package main  
  
import "fmt"  
  
func main() {  
   data := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 10: 9}  
   s := data[:2:3]  
   s = append(s, 23, 34)  
  
   fmt.Println(s, data)  
   fmt.Println(&s[0], &data[0])  
}

输出:

[1 2 23 34] [1 2 3 4 5 6 7 8 0 0 9]
0xc00000e4b0 0xc000016420

可以看出底层数组被重新分配了,没有用同一个数组。

copy(切片复制)

函数 copy 在两个 slice 间复制数据,复制长度以 len 小的为准。两个 slice 可指向同一底层数组,允许元素区间重叠。

package main  
  
import "fmt"  
  
func main() {  
   data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}  
  
   s := data[8:]  
   s2 := data[:5]  
   fmt.Println(s)  
   fmt.Println(s2)  
  
   copy(s2, s) // dst:s2, src:s  
  
   fmt.Println(s2)  
   fmt.Println(data)  
}

输出:

[8 9]
[0 1 2 3 4]          
[8 9 2 3 4]          
[8 9 2 3 4 5 6 7 8 9]

大的slice复制给小的slice,上面两个slice中0和1都有元素,小的slice覆盖了打的slice。

goto

使用goto前,需先定义标签。标签区分大小写,且未使用的标签会引发编译器的错误。

package main  
  
import "fmt"  
  
func main() {  
  
   for i := 0; i < 3; i++ {  
      fmt.Println(i)  
      if i > 1 {  
         goto exit  
      }  
   }  
exit:  
   fmt.Println("exec.")  
  
}  
  
func test() {  
  
}

输出:
0
1
2
exec.

不能跳到其他函数或者内层代码上:

package main  
  
func test() {  
test:  
   println("test")  
   println("test exit.")  
}  
func main() {  
   for i := 0; i < 3; i++ {  
   loop:  
      println(i)  
   }  
   goto test  
   goto loop  
  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值