2022/2/2
package main
import (
"fmt"
"math/rand"
"time"
)
func test(arr *[3]int) {
(*arr)[0] = 123
}
func test1(arr [4]int) {
}
//1.数组
//1.1数组是存放多个同一类型数据 数组是go中是值类型,指向一个数据空间
func main() {
//1.1.1定义一个数组
//数组必须规定长度 否则就是切片
// var 数组名 [数组大小]数据类型
var hens [6]float64
fmt.Println("hens=", hens)
fmt.Printf("%pn", &hens)
//数组首元素地址可以通过数组名获取(同C语言)
//给数组每个元素赋值
hens[0] = 3.0
hens[1] = 5.0
hens[2] = 1.0
hens[3] = 3.4
hens[4] = 2.0
hens[5] = 50.0
//1.1.2四种初始化数组的方式
var arr1 [3]int = [3]int{1, 2, 3}
var arr2 = [3]int{4, 5, 6}
var arr3 = [...]int{7, 8, 9, 10}
//指定元素值对应的下标
var arr4 = [3]string{1: "tom", 0: "levi", 2: "joy"}
var arr5 = [3]string{1: "tom~", 0: "levi~", 2: "joy~"}
fmt.Println("arr1=", arr1)
fmt.Println("arr2=", arr2)
fmt.Println("arr3=", arr3)
fmt.Println("arr4=", arr4)
fmt.Println("arr5=", arr5)
//1.1.3遍历数组
var totalWeight float64
//1.1.3.1 常规遍历
for i := 0; i < len(hens); i++ {
totalWeight += hens[i]
}
//1.1.3.2 for-range 遍历
//基本语法
// for index , value := range array{
// }
//说明
//--> 第一个返回值index是数组的下标
//--> 第一个返回值value是在该下表位置的值
//--> 他们都仅在for循环内部可见的局部变量
//--> 遍历数组元素时,如果不想使用下标index,可以使用占位符下划线 _ 标记
//--> index和value是不固定的,但是一般推荐使用
for _, value := range hens {
fmt.Println(value)
}
for index, value := range hens {
fmt.Printf("%d只鸡的体重是%.2fn", index, value)
}
avgWeight := totalWeight / float64(len(hens)) //go内运算需要保持数据类型一致
//如果除数是常数则没问题 如果是变量必须要数据类型一致
fmt.Printf("总体重是: %v, 平均体重是: %.2fn", totalWeight, avgWeight)
//1.2数组是多个相同类型数据的组合,一个数组一旦声明/定义了,长度是固定的,不能动态变化
var arr01 [3]int
arr01[0] = 1
arr01[1] = 2
arr01[2] = 3
//arr01[2] = 1.1 //报错,类型不匹配
//arr01[3] = 3 //长度固定,不能动态变化,否则报越界(数组不能动态增长)
//1.3 数组创建后,如果没有赋值,会有初始值
// 数值(整数系列,浮点数系列) -> 0
// 字符串 -> ""
// bool -> false
//1.4 go的数组属于值类型,在默认情况下是值传递,因此会进行值拷贝,数组间不会相互影响
//1.5 数组引用传递
test(&[3]int{11, 22, 33})
//1.6 在go中长度是数组类型的一部分,在传递函数参数时,需要考虑数组的长度
var arr22 = [...]int{1, 2, 3, 4}
test1(arr22)
var byteArr [26]byte
for i := 0; i < len(byteArr); i++ {
byteArr[i] = 'A' + byte(i)
}
fmt.Println("byteArr = ", byteArr)
for i := 0; i < len(byteArr); i++ {
fmt.Printf("%cn", byteArr[i])
}
//用for-range求和 求平均值
var array [5]int = [...]int{1, -1, 9, 90, 12}
sum := 0
for _, value := range array {
sum += value
}
fmt.Printf("sum = %d, avg = %dn", sum, sum/len(array))
//如何让平均值保留到小数点
fmt.Printf("sum = %d, avg = %fn", sum, float64(sum)/float64(len(array)))
//1.7 随机生成五个数,并将其反转打印
//rand.Intn()生成随机数
//得到随机数,就放到一个int数组
//反转打印, 可以直接倒叙打印, 也可以交换数据元素
var intArr [5]int
rand.Seed(time.Now().UnixNano())
for i := 0; i < len(intArr); i++ {
intArr[i] = rand.Intn(1000)
}
fmt.Println("intArr1 = ", intArr)
temp := 0
for i := 0; i < len(intArr)/2; i++ {
temp = intArr[len(intArr)-1-i]
intArr[len(intArr)-1-i] = intArr[i]
intArr[i] = temp
}
fmt.Println("intArr2 = ", intArr)
}
package main
import "fmt"
//2.切片
/
}
fmt.Println()
//2.5.2 for-range遍历切片
for i, value := range slice4 {
fmt.Printf("slice[%v] = %vn", i, value)
//output:
}
//***2.6 切片可以继续切片
//操作和切数组相同
//***2.7 切片可以使用append函数进行动态增加
var sli1 []int = []int{1, 2, 3}
fmt.Println("sli1 = ", sli1)
//2.7.1 通过append直接给sli1追加具体的元素,但是元素类型要一致
sli2 := append(sli1, 400, 500, 600)
fmt.Println("sli2 = ", sli2)
//2.7.2 追加过后 sli1不会变化,会拷贝到sli2
//如果要变化本身
sli2 = append(sli2, 111, 11, 1222)
fmt.Println("sli2 = ", sli2)
//2.7.3 也可以直接追加切片
sli2 = append(sli2, sli2...) //...是固定的写法
fmt.Println("sli2 = ", sli2)
//***2.8 切片append的底层分析细节
//2.8.1 切片append操作的本质就是对数组扩容
//2.8.2 go底层会创建一个新的数组newArr(安装扩容后大小)
//2.8.3 将slice原来包含的元素拷贝到新的数组newArr
//2.8.4 slice重新引用到newArr
//2.8.5 注意newArr是在底层来维护的,程序员不可见
var t1 [5]int = [5]int{1, 2, 3, 4, 5}
var s1 []int = t1[2:5] //3 4 5
var s2 []int = s1[0:2]
s2[0] = 100
fmt.Println("t1 = ", t1) //output: t1 = [1 2 100 4 5]
fmt.Println("s1 = ", s1) //output: s1 = [100 4 5]
fmt.Println("s2 = ", s2) //output: s2 = [100 4]
//***2.9 切片拷贝
var s3 []int = []int{1, 2, 3, 4, 5}
var s4 = make([]int, 10)
copy(s4, s3)
fmt.Println("s3 = ", s3) //output: s3 = [1 2 3 4 5]
fmt.Println("s4 = ", s4) //output: s4 = [1 2 3 4 5 0 0 0 0 0]
s4[0] = 100
fmt.Println("s3 = ", s3) //output: s3 = [1 2 3 4 5]
fmt.Println("s4 = ", s4) //output: s4 = [100 2 3 4 5 0 0 0 0 0]
//s3 和 s4的数据空间是独立的
var s5 []int = []int{1, 2, 3, 4, 5}
var s6 = make([]int, 3)
copy(s6, s5)
fmt.Println("s6 = ", s6) //output: s6 = [1 2 3]
//如果内存小于被拷贝的切片,那就拷贝满即可
}
package main
import "fmt"
//string 和 slice
func fbn(n int) []uint64 {
//1.声明一个切片,切片大小是n
var fbnSlice []uint64 = make([]uint64, n)
fbnSlice[0] = 1
fbnSlice[1] = 1
for i := 2; i < n; i++ {
fbnSlice[i] = fbnSlice[i-1] + fbnSlice[i-2]
}
return fbnSlice
}
func main() {
//1.string底层是一个byte数组,因此string也可以进行切片处理
var myStr string = "hello world"
//使用切片获取world
slice := myStr[6:]
fmt.Println("slice =", slice)
//2.string是不可变的,也就说不能通过string[0]='z'方式来修改字符串
//myStr[2] = 'q' //error
//3.如果需要修改字符串,可以先将string->[]byte 或者 []rune->修改->重写转成string
//把 h 改为-> z
//1.这个方法可以处理英文和数字,不能处理中文,[]byte是按字节来处理,汉字是三个字节
arr1 := []byte(myStr)
arr1[0] = 'z'
myStr = string(arr1)
fmt.Println("myStr1 =", myStr)
//2.这个方法可以处理中文,因为[]rune是按照字符来处理的
arr2 := []rune(myStr)
arr2[0] = '中'
myStr = string(arr2)
fmt.Println("myStr2 =", myStr)
//编写函数接收一个 n int 能够将斐波那契的数列放到切片中
//思路
//1.声明一个函数 fbn(n int)([]uint64)
//2.编写fbn(n int) 进行for循环来存放斐波那契数列 0-> 1 1-> 1
fbnSliceRet := fbn(10)
fmt.Println("fbnSliceRet =", fbnSliceRet)
}