1)数组定义:存放多个同一类型的数据,go语言中,数组是值类型 var 数组名[数组大小]数据类型
var a [5]int var b [3]int = [3]int{1,2,3} var c = [3]int{1,2,3} var d = […]int {1,2,3} //…代表让系统去判断数据大小 2)数组的遍历
方式一:常规遍历for 方式二:for-range结构遍历 for index,value := range array01{ … }
index是数组的下标、value是下标对应的值,这两个变量都是仅在for循环内的局部变量,不需要下标时,可以用_替换index,index和value名称是可以自定义的 3)注意事项和细节
package main
import "fmt"
func test01(arr [3]int) { //[3]int [4]int 在这里不是一种数据类型,因为长度不一样
arr[0] = 88
fmt.Println("in func test01", &arr[0], arr)
}
func test02(arr *[3]int) {
(*arr)[0] = 99 //指向数组的指针的使用
fmt.Printf("arr指针的地址 %p\n", &arr)
fmt.Println("in func test02", &arr[0], *arr)
}
func main() {
// var score [6]float64
// fmt.Printf("数组的地址%p\n", &score)
// fmt.Printf("数组首个元素的地址%p\n", &score[0])
// for i := 0; i < len(score); i++ {
// fmt.Printf("请输入第%d个元素", i+1)
// fmt.Scanln(&score[i])
// }
// for i := 0; i < len(score); i++ {
// fmt.Printf("score[%d]=%v\n", i, score[i])
// }
// var b [3]int = [3]int{1, 2, 3}
// var c = [3]int{1, 2, 3}
// var d = [...]int{1, 2, 3} //...代表让系统去判断数据大小,固定写法
// e := [...]int{1: 123, 2: 111, 0: 333} //指定下标赋值,类型推导
// fmt.Println("b", b)
// fmt.Println("c", c)
// fmt.Println("d", d)
// fmt.Println("e", e)
// for i, v := range e {
// fmt.Println(i, v)
// }
arr := [3]int{11, 22, 33} //如果这里定义[4]int,参数传入会报错
test01(arr)
fmt.Println("in func main", &arr[0], arr) //因为是值类型,因此arr[0] = 11,而不是88,可以看到2个arr[0]地址也不一样,函数test和main都单独对arr数组生成了独立的内存空间
test02(&arr)
fmt.Println("in func main", &arr[0], arr) //可以看到,指针引用后,函数test和main里的arr数组值和内存地址是一样的
}
package main
import (
"fmt"
"math/rand"
"time"
)
func exe01() {
//创建一个byte类型的数组,放置A-Z,使用for访问所有元素及打印
var myChars [26]byte
for i := 0; i < 26; i++ {
myChars[i] = 'A' + byte(i)
}
for i := 0; i < 26; i++ {
fmt.Printf("%c ", myChars[i])
}
}
func exe02() {
//请求出一个数组的最大值,并得到对应的下标
//思路
//1、声明一个数组,填入内容
//2、假定第一个元素就是最大值,下标是0
//3、用假定的第一个元素和后面每个元素循环比较,有更大的数则交换
intArr := [...]int{1, -1, 33, 5, 15, 111}
maxVal := intArr[0]
maxValIndex := 0
for i := 1; i < len(intArr); i++ {
if maxVal < intArr[i] {
maxVal = intArr[i]
maxValIndex = i
}
}
fmt.Printf("maxVal=%v maxValIndex=%v \n", maxVal, maxValIndex)
}
func exe03() {
//请求出一个数组的和与平均值,使用for-range
intArr2 := [...]int{1, -1, 33, 5, 15}
sum := 0
for _, val := range intArr2 {
sum += val
}
fmt.Printf("数组的和=%v,平均值=%v \n", sum, float32(sum)/float32(len(intArr2))) //go运算,int除法结果是整数,需要转换浮点类型
}
func exe04() {
//随机生成5个数,并将其反转打印
//思路
//1、使用rand.Intn()函数生成随机数,放入数组
//2、反转打印:交换次数=数组大小/2,第一个和最后一个交换,第二个和倒数第二个交换,依次类推
var intArr3 [33]int
arrlen := len(intArr3)
rand.Seed(time.Now().UnixNano()) //用纳秒时间戳生成随机种子
for i := 0; i < arrlen; i++ {
intArr3[i] = rand.Intn(100)
}
fmt.Printf("交换前数组 %v\n", intArr3)
for i := 0; i < arrlen/2; i++ {
tmp := intArr3[i] //第i个放临时变量
intArr3[i] = intArr3[arrlen-i-1] //倒数i个赋值给第i个,数组下标从0开始,因此要-1,5个元素的数组,最后一个下标是4
intArr3[arrlen-i-1] = tmp //临时变量(第i个)赋值给倒数i个
}
fmt.Printf("交换后数组 %v\n", intArr3)
}
func main() {
// exe01()
// exe02()
// exe03()
exe04()
}
1)切片是数组的一个引用,因此切片是引用类型;切片的长度是可以变化的;切片的使用和数组类似 2)切片定义的基本语法: var 切片名 []类型: var a []int 3)切片的使用: 方式一、定义一个切片,引用一个已经创建好的数组;
方式二、通过make创建切片:var slice []int = make([]type,len,[cap]) //cap可选 方式三、定义一个切片,直接指定具体数组,原理和make类似 4)切片遍历的方法和数组相同:
常规for、for-range 5)引用数组的简写法:x到结束 arr[x:end]、开始到x arr[start:x]、全部 arr[:]
6)切片可以继续切片 7)append内置函数,可以对切片进行动态追加,容量不够时会动态扩容及生成一个新的底层数组 8)切片可以追加切片,固定写法 slice = append(slice,slice…),不能追加数组 9)
切片的拷贝操作,使用copy内置函数操作,拷贝后仍然是切片类型 copy(b,a)
a,b都是切片类型,复制a每个元素到b对应的位置,b其他的空间不变,改变的是b切片;只是复制值,相对的空间还是独立的;a长度大于b时,从前往后复制能容纳的元素 10)string和slice
string底层是一个byte数组,因此可以进行切片 string是不可变的,不能通过str[0]='a’来修改;可以通过将string -> []byte或[]rune后再修改转换后的切片
package main
import (
"fmt"
)
func demo1() {
var intArr [5]int = [...]int{1, 2, 3, 4, 5}
slice := intArr[1:3]
fmt.Println("切片的值,长度,容量是:\n", slice, len(slice), cap(slice))
fmt.Printf("%p %p \n", &intArr[1], &slice[0]) //数组和切片的地址是相同的
//切片本质是一个struct: 内存地址 len cap
slice[0] = 22 //修改切片,实际是修改了引用的数组
fmt.Println(intArr, slice)
slice = append(slice, 11)
fmt.Println("切片的值,长度,容量是:\n", slice, len(slice), cap(slice))
slice = append(slice, 22)
fmt.Printf("%p %p \n", &intArr[1], &slice[0])
fmt.Println("切片的值,长度,容量是:\n", slice, len(slice), cap(slice))
slice = append(slice, 33)
fmt.Println("切片的值,长度,容量是:\n", slice, len(slice), cap(slice))
//容量是动态调整的
fmt.Printf("%p %p \n", &intArr[1], &slice[0])
//动态扩容后,生成了一个新的底层数组,内存地址就不一样了
slice[0] = 222 //这时候再修改,原来的数组不会变了
fmt.Println(intArr, slice)
}
func demo2() {
//切片的另外2种创建方式,底层数组不可见,通过slice操作
var slice1 []int = []int{1, 2, 3}
var slice2 []int = make([]int, 2, 6)
fmt.Println(slice1, slice2)
//遍历方法和数组一样
for i := 0; i < len(slice1); i++ {
fmt.Println(slice1[i])
}
for i, v := range slice1 {
fmt.Println(i, v)
}
}
func demo3() {
var a []int = []int{1, 2, 3, 4, 5}
var b = make([]int, 10)
copy(b, a)
fmt.Println(a, b)
}
func demo4() {
str := "you are so beatuful"
slice := str[4:7]
fmt.Println(slice)
// str[1] = '1' //编译报错
slice2 := []byte(str)
slice2[0] = 'x' //这样修改不报错
str = string(slice2)
fmt.Println(str) //byte类型不能处理中文,因为一个中文3个字节,rune按字符处理,兼容汉字
}
func main() {
demo4()
}
package main
import "fmt"
//编写一个函数,将斐波那契数列放入切片
func finb(n int) []uint64 {
//思路
//斐波那契数列:1,2,3,5,8
//定义一个函数,返回切片
slice := make([]uint64, n)
slice[0] = 1
slice[1] = 1
for i := 2; i < n; i++ {
slice[i] = slice[i-1] + slice[i-2]
}
return slice
}
func main() {
fnb := finb(10)
fmt.Println(fnb)
}