一、数组
数组的基础使用如下(tips:fmt的print输出可直接输出数组,不需要遍历),er:
func main() {
//普通的定义数组的格式如下
var arr1 [5]int
//也可以采用和命名变量一样的形式,使用冒号,或是直接设置初始值
arr2 := [3]int{1,3,5}
//当然,也可以不需要直接定义好数组大小,交由解释器自己去数,由...代替
arr3 := [...]int{2,4,6,8,10}
//定义好一个二维数组的方式如下
var grid [4][5]int
fmt.Println(arr1,arr2,arr3,grid)
}
如果想要遍历数组,首先想到的就是for循环,eg:
func main() {
arr3 := [...]int{2,4,6,8,10}
for i:=0;i
但是go语言有更加方便的写法,使用range关键字,eg:
for i:= range arr3{
fmt.Println(arr3[i])
}
有时候我们不止想要索引,还想要直接获取值,那么可以这样写,eg:
for i,v:= range arr3{
fmt.Println(i,v)
}
那么我们不想要索引,只想要值,怎么办,像下面这样写?
//可以试试这样写,但是编译不会通过
for i,v:= range arr3{
fmt.Println(v)
}
这样是不会通过编译的,因为go语言默认,只要是被命名的变量,那么就一定要用到,否则就编译不通过,解决办法就是使用"_"来进行省略变量。
for _,v:= range arr3{
fmt.Println(v)
}
需要注意的是,方法中数组的参数是可以定义好大小的。比如[3]int 和[4]int是不同的参数,调用错误是会报错的
func change(a [3]int) {
a[0]=100
}
另外在函数调用的时候,都是是值传递(这和大多数语言都不一致),也就是参数拷贝数组,函数内不会影响函数外。如下代码运行可以看到a[0]的值没有被改变,eg:
func change(a [5]int) {
a[0]=100
}
func main() {
arr3 := [...]int{2,4,6,8,10}
change(arr3)
for _,v:= range arr3{
fmt.Println(v)
}
}
当然如果想要引用传递,那么可以使用指针,eg:
func change(a *[5]int) {
a[0]=100
}
func main() {
arr3 := [...]int{2,4,6,8,10}
change(&arr3)
for _,v:= range arr3{
fmt.Println(v)
}
}
但是这样也很麻烦,go语言一般是不使用数组的,go语言推荐使用切片
二、切片
切片可以理解是将数组进行切分。
func main() {
//此为数组
arr :=[...]int{0,1,2,3,4,5,6}
fmt.Println("arr[2:6]=",arr[2:6])
fmt.Println("arr[:6]=",arr[:6])
fmt.Println("arr[2:]=",arr[2:])
fmt.Println("arr[:]=",arr[:])
}
上述输出结果如下,可以看到不同的切片方式对应不同的结果
那么继续试验,通过一个方法看看切片是否是引用传递,运行如下代码
func updateSlice(s []int) {
s[0]=100
}
func main() {
arr :=[...]int{0,1,2,3,4,5,6}
s1 := arr[2:]
fmt.Println("arr[2:]=",s1)
fmt.Println("afterslice")
updateSlice(s1)
fmt.Println(s1)
fmt.Println(arr)
}
结果如下,可以看到切片后的值是引用传递,切片本身没有数据,是对原数组的一个view,会改变原有数组的值,所以方法中参数为数组,那么使用的时候也是要用切片的,比如updateSlice(arr[:])
三、切片的操作
如果在切片中插入的元素超过原有元素了怎么办,比如如下代码
func main() {
arr :=[...]int{0,1,2,3,4,5,6,7}
s2 := arr[3:5]
s3 := append(s2,10)
s4 := append(s3, 11)
s5 := append(s4, 12)
fmt.Println("s3,s4,s5=",s3,s4,s5)
fmt.Println(arr)
}
结果如下,可以看到未超过原有长度的会改变数组元素,超过的则没有改元素了,这是因为切片遇到新增元素超过原有元素的情况,则会放入一个临时的数组内,过一段时间会有垃圾回收机制将临时数组回收
所以类似var s []int这样的写法,实际上也是一种切片,只不过go语言默认 Zero value for slice is nil,实际上没有定义初始值的切片,这个时候s==nil
同时切片还支持其他的一些操作
func main() {
s1 :=[]int{2,4,6,8}
//创建一个长度为16的数组
s2 := make([]int,16)
fmt.Println("s2=",s2)
//创建一个长度为10但是capacity为32的数组
s3 := make([]int,10,32)
fmt.Println("s3=",s3)
//拷贝slice
copy(s2,s1)
fmt.Println("after copying s2=",s2)
//删除某个元素,以删除第三个元素为例
s2 = append(s2[:3],s2[4:]...)
fmt.Println("after deleting s2=",s2)
//弹出头元素
front :=s2[0]
s2 = s2[1:]
fmt.Println("after popping front=",front)
fmt.Println("after popping s2=",s2)
//弹出尾元素
tail :=s2[len(s2)-1]
s2 = s2[:len(s2)-1]
fmt.Println("after popping tail=",tail)
fmt.Println("after popping s2=",s2)
}
运行结果如下
四、map
map的结构如下,map[key]value,eg:
m := map[string]string{//m == empty map
"name": "ccmouse",
"course": "golang",
"site": "imooc",
"quality": "notbad",
}
//或者
m2 := make(map[string]int)//m2 == nil
如果想要取map中的值,可以通过v:=m["course"],需要注意的是如果key没有,则返回的是一个空值,如果想要获知是否存在相应key值,eg:
if v, ok:=m["cause"];ok{
//dosomething...
}