Fork me on GitHub

Golang之旅31-array&slice

数组和切片

数组array

  • 可以存放多个同一类型数据
  • 数组是种数据类型,数组是值类型
  • 数组的地址和数组中第一个元素的地址相同
  • 第二个元素的地址 = 第一个元素的地址 + 这个数组类型占用的字节数(int:8,int32:4)
  • 数组中的地址是连续的,通过数组名来进行获取&intArr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main
import "fmt"

func main(){
var hens [4]float64
// 赋值过程
hens[0] = 1.0
hens[1] = 2.0
hens[2] = 4.0
hens[3] = 3.0

// 遍历数组求体重
totalweight := 0.0
for i := 0;i < len(hens);i++{
totalweight += hens[i]
}

// 求出平均体重
avgweight := fmt.Sprintf(".2f", totalweight / float64(len(hens))
fmt.Printf(totalweight, avgweight)
}

数组使用

下标从0开始,3种初始化方式

1
2
3
4
var numArray [3]int{1,3,4}
var numArray [...]int{9,3,2}
var numArray [...]int{1: 900, 2: 800, 0:100}
nameArray := [...]int{1: "jack", 2: "tom", 0:"jim"}

for- range遍历方式

1
2
3
4
5
6
7
8
9
10
11
12
13
package main
import "fmt"

func main(){
heros := [...]string{"张三", "李四", "王五"}
for index, value := range heros{
fmt.Printf("i=%v value=%v", index, value)
}

for _, value := range heros{
fmt.Printf("元组的值=%v\n", value)
}
}

数组注意事项

  1. 数组是多个相同类型的组合,长度是固定的,不能动态变化
  2. 数组中的元素可以是任何数据类型,但是不能混用
  3. 数组定义之后没有赋值,则默认是零值
    1. 数值类型:0
    2. 字符串:""
    3. bool数组:false
  4. 数组是值类型,默认是值传递,因此会进行值拷贝。数组间不会相互影响
  5. 长度是数组的一部分,在传递参数的时候需要考虑数组的长度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main
import "fmt"

func test1(arr [3]int){
arr[0] = 88
}

// 数组类型的指针
func test2(arr *[3]int){
(*arr)[0] = 99
}


func main(){
// 值传递
arr := [3]int{1,2,3}
test1(arr) // [88,2,3]
fmt.Println(arr) // [1,2,3]

// 引用传递
arr := [3]int{1,2,3}
test2(&arr) // [99,2,3]
fmt.Println(arr) // [1,2,3]
}

MC7Zmd.png

MC7CY6.png

数组案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main
import "fmt"
func main(){
// 创建一个byte类型的数组,放置26个元素的数组,A-Z;并用for循环遍历
var myChars [26]byte
for i:=0 ; i < 26; i++{
myChars[i] = 'A' + byte(i) // 需要强制转换,将i转成byte类型
}
for i:0; i < 26;i++{
fmt.Printf("%c", myChars[i])
}

// 访问数组中的最大元素
var numArray = [...]int{1,4,2,6,3,8,9,5}
// 假定第一个是最大元素
maxVal := numArray[0]
maxIndex := 0

// 通过for循环遍历比较;如果maxVal不是最大的,则进行元素和索引的交换
for i:=1; i< len(numArray);i++{
// 循环走完,找到了最大元素及其索引
if maxVal < numArray[i]{
maxVal = numArray[i]
maxIndex = i
}
}
fmt.Printf("maxVal=%v maxIndex", mavVal, maxIndex)

// 求出数组的和以及平均值
var intArray = [...]int{1,4,2,6,3,8,9,5}
sum := 0
for _, value := range intArray{
sum += value
}
fmt.Printf("sum=%v 平均值=%v",sum, float(sum) / float(len(intArray))). // 如何让平均值保留小数位
}

数组反转

随机生成5个数,进行反转输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main
import (
"fmt"
"math/rand"
"time"
)

func main(){
// 1. 随机生成5个数:rand.Intn()函数
// 2. 将随机数放入数组中
// 3. 反转打印:倒数第一个和整数第一个交换,倒数第二个和整数第二个交换;索引相加刚好是:lenght - 1;比如:0 + (lenght-1)
var intArr [5]int
lenght := len(intArr)
//为了使每次生成的随机数不同,需要设置一个随机数种子seed
rand.Seed(time.Now().UnixNano())
for i:=0;i<lenght;i++{
intArr[i] = rand.Intn(100) // 随机生成[0,100)之间的整数
}
fmt.Println("交换前=", intArr)

tmp := 0
for i := 0;i<len/2;i++{
tmp = intArr[length - 1- i]
intArr[length - 1- i] = intArr[i]
intArr[i] = tmp
}
fmt.Println("交换后=", intArr)
}

slice基础

  • 切片包含长度和容量
  • 切片是数组的引用,是引用传递
  • 切片的长度是变化的,切片是动态的数组
  • 切片从底层来说,就是一个数据结构struct
1
2
3
4
5
6
7
8
9
var 变量名 []类型
var a []int

// 底层的结构体
type slice struct{
ptr *[2]int
len int
cap int
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import "fmt"

func main(){
var intArr = [...]int{0,1,2,3,4,5,6,7,8}
slice := intArr[1:6] // 1,2
fmt.Println("intArr=", intArr)
fmt.Println(slice)
fmt.Println(&intArr[1])
fmt.Println(&slice[0]) // 上下两个地址相等
slice[3] = 100 // 改变切片中的元素
// 切片和原来的数组中的元素也会改变
fmt.Println(intArr)
fmt.Println(slice)
}

MiGRrn.png

Mit35V.png

切片初始化

  1. 通过创建好的数组来定义切片,这个数组是事先存在的,程序是可见的。
  2. 通过make来初始化切片var sliceName []type=make([], len,[cap])make会创建一个切片,也会创建一个数组,这个数组在底层是由切片进行维护的。程序员不可见。
    1. 长度必须指定
    2. 容量是可选的,如果不指定默认是长度值
    3. 如果不给切片的各个元素赋值,就会使用默认值
1
2
3
4
5
6
7
8
9
func main(){
var slice = make([]float64, 5, 10) // 切片必须make初始化之后才能使用
slice[1] = 10 // 再进行赋值
slice[3] = 30

fmt.Println(slice)
fmt.Println(len(slice)) // 长度
fmt.Println(cap(slice)) // 容量
}
  1. 创建切片的时候直接指定
1
2
3
func main(){
var slice []int = []int{1,3,4,5}
}

切片遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main
import "fmt"

func main(){
var arr = [...]{10,1,2,3,4,5,6,7}
// 将数组全部取出来
// arr[:]
// arr[0:len(arr)]
slice = arr[1:5] //1,2,3,4

// for遍历
for i := 0;i < len(slice); i++{
fmt.Println(i, slice[i])
}

// for-range遍历
for i, v := range slice { // 如果只想取其中一个,另一个用下划线_代替
fmt.Printf("i=%v v=%v", i, v)
}
}

append

  • 对切片进行动态追加到末尾,自动扩容
  • 切片中追加切片必须带上
1
2
3
4
// 追加元素到切片中
slice3 = append(slice3,400,500,600) // 对slice进行扩容操作
// 追加切片到切片中,后面的点必须带上
slice3 = append(slice3, slice1...) // 将slice1追加到slice中

MihG01.png

copy

1
2
3
4
5
6
7
8
9
10
11
package main
import "fmt"

func main(){
// slice1和slice2是相互独立的
var slice1 = []int{1,2,3,4}
var slice2 := make([]int, 10) // 长度和容量都是10
copy(slice1, slice2) // 将slice1拷贝给slice2;即使slice2的长度不够,也不会报错,只会拷贝部分元素
fmt.Println(slice1) // [1,2,3,4]
fmt.Println(slice2) // [1,2,3,4,0,0,0,0,0,0]
}

本文标题:Golang之旅31-array&slice

发布时间:2019年11月06日 - 23:11

原始链接:http://www.renpeter.cn/2019/11/06/Golang%E4%B9%8B%E6%97%8531-array%E5%92%8Cslice.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Coffee or Tea