基础不牢地动山摇之Go基础题

2023-12-09 20:54:50 浏览数 (1)

前言

本文是探讨的是"Go基础题"

平常经常遇到的类型,如有不对, 还望斧正, 感谢! 

经典题一   循环变量引用问题

请你分析下面代码的运行结果

代码语言:go复制
func main() {
     slice := []int{0,1,2,3}

     m := make(map[int]*int)

     for key,val := range slice {

         m[key] = &val

     }

    for k,v := range m {

        fmt.Println(k,"is",*v)

    }

}

答案

代码语言:go复制
    0 is 3

    1 is 3

    2 is 3

    3 is 3

 解析

很有意思的一道题,如果知道的原理的话,就可以不用往下面看了。

重点是在这里,在for循环中,每次向映射里面追加一个,val的地址。 在Go中,val只分配一次地址, 在三次循环中val中存储的值分别为0,1,2,3。但是加到映射m里面的是val的地址,不是val的值,然后最后val存储的值是3

代码语言:go复制
    for k,v := range m {

        fmt.Println(k,"is",*v)

    }

经典题二    defer和panic执行顺序问题

请你分析下面代码的运行结果

代码语言:go复制
package main

 import (

     "fmt"

 )

 func main() {

     defer_call()

 }

func defer_call() {

    defer func() { fmt.Println("一") }()

    defer func() { fmt.Println("二") }()

    defer func() { fmt.Println("三") }()

    panic("触发异常")

}

答案

代码语言:go复制
    三

    二

    一

    panic: 触发异常

解析

同样是很经典的问题

defer 的执行顺序是后进先出,是一个栈的结构,并且defer是会在函数返回之前执行。当出现 panic 语句的时候,会先按照 defer 的后进先出的顺序执行,最后才会执行panic。

经典题三       切片扩容问题

请你分析下面代码的运行结果

代码语言:go复制
func  SliceDemo(s []int){

    s = append(s,0)

    for i := range s {

        s[i]  

    }

}

func main (){

    s1 := []int{1,2}

    s2 :=s1

    s2 = append(s2,3)

    SliceDemo(s1)

    SliceDemo(s2)

    fmt.Println(s1,s2)

}

答案

代码语言:go复制
[1,2][2,3,4]

解析

切片扩容问题,其实主要是append函数的事,考虑两个点,切片的长度和容积,其实可以简单认为 append函数扩容的时候,一旦长度大于容积的时候,就会创建一个原先容积两倍的新的切片,注意是新的切片。

接下来我来具体分析一下

首先在 main 函数中,定义了一个名为 s1 的整数切片,包含元素 1, 2。

将 s1 的值赋给一个新的变量 s2。现在 s1 和 s2 指向同一个底层数组(共享相同的内存地址)。

使用 append 函数将元素 3 添加到 s2 中,此时会创建一个新的底层数组,并将原始数组中的所有元素复制到新数组中,同时添加新的元素 3。所以现在 s1 和 s2 指向不同的底层数组。

调用 SliceDemo 函数并传入参数 s1。

在 SliceDemo 函数中,使用 append 函数将元素 0 添加到 s 切片中。因为传递的是值拷贝而不是指针,所以这里的 s 是 s1 的副本,因此不会影响 s1 的底层数组。

使用 for 循环遍历 s 切片,并将每个元素加 1。同样,由于这是对 s 副本的操作,所以不会影响 s1 的底层数组。

函数调用结束,返回到 main 函数。

再次调用 SliceDemo 函数并传入参数 s2。

同样的过程再次发生:在 SliceDemo 函数中,使用 append 函数将元素 0 添加到 s 切片中。这次操作发生在 s2 的副本上,所以不会影响 s2 的底层数组。

使用 for 循环遍历 s 切片,并将每个元素加 1。这次操作发生在 s2 的副本上,所以不会影响 s2 的底层数组。

函数调用结束,返回到 main 函数。

最后,打印 s1 和 s2 的值。由于之前的函数调用没有改变这两个切片的底层数组,所以输出仍然是 1, 2 和 1, 2, 3。

我正在参与2023腾讯技术创作特训营第四期有奖征文,快来和我瓜分大奖!

0 人点赞