go语言基础(二)

一、数组
数组的基础使用如下(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[:])
}

上述输出结果如下,可以看到不同的切片方式对应不同的结果


捕获.PNG

那么继续试验,通过一个方法看看切片是否是引用传递,运行如下代码

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[:])


捕获.PNG

三、切片的操作
如果在切片中插入的元素超过原有元素了怎么办,比如如下代码

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)
}

结果如下,可以看到未超过原有长度的会改变数组元素,超过的则没有改元素了,这是因为切片遇到新增元素超过原有元素的情况,则会放入一个临时的数组内,过一段时间会有垃圾回收机制将临时数组回收


捕获.PNG

所以类似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)
}

运行结果如下


捕获.PNG

四、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...
}

你可能感兴趣的:(go语言基础(二))