前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基础不牢地动山摇之Go基础题

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

原创
作者头像
言志志
修改2023-12-09 20:54:50
3283
修改2023-12-09 20:54:50
举报
文章被收录于专栏:Go语言学习笔记Go语言学习笔记

前言

本文是探讨的是"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腾讯技术创作特训营第四期有奖征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 经典题一   循环变量引用问题
    • 答案
      •  解析
      • 经典题二    defer和panic执行顺序问题
        • 答案
          • 解析
          • 经典题三       切片扩容问题
            • 答案
              • 解析
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档