Go常见语法题目解析

1、写出下面代码输出内容。

package mainimport ("fmt"
)func main() {defer_call()
}func defer_call() {defer func() { fmt.Println("打印前") }()defer func() { fmt.Println("打印中") }()defer func() { fmt.Println("打印后") }()panic("触发异常")
}

解析:

defer 关键字的实现跟go关键字很类似,不同的是它调用的是runtime.deferproc而不是runtime.newproc

defer出现的地方,插入了指令call runtime.deferproc,然后在函数返回之前的地方,插入指令call runtime.deferreturn

goroutine的控制结构中,有一张表记录defer,调用runtime.deferproc时会将需要defer的表达式记录在表中,而在调用runtime.deferreturn的时候,则会依次从defer表中出栈并执行。

因此,题目最后输出顺序应该是defer 定义顺序的倒序。panic 错误并不能终止 defer 的执行。

2、 以下代码有什么问题,说明原因

type student struct {Name stringAge  int
}func pase_student() {m := make(map[string]*student)stus := []student{{Name: "zhou", Age: 24},{Name: "li", Age: 23},{Name: "wang", Age: 22},}for _, stu := range stus {m[stu.Name] = &stu}
}

解析:

golang 的 for ... range 语法中,stu 变量会被复用,每次循环会将集合中的值复制给这个变量,因此,会导致最后m中的map中储存的都是stus最后一个student的值。

3、下面的代码会输出什么,并说明原因

func main() {runtime.GOMAXPROCS(1)wg := sync.WaitGroup{}wg.Add(20)for i := 0; i < 10; i++ {go func() {fmt.Println("i: ", i)wg.Done()}()}for i := 0; i < 10; i++ {go func(i int) {fmt.Println("i: ", i)wg.Done()}(i)}wg.Wait()
}

解析:

这个输出结果决定来自于调度器优先调度哪个G。从runtime的源码可以看到,当创建一个G时,会优先放入到下一个调度的runnext字段上作为下一次优先调度的G。因此,最先输出的是最后创建的G,也就是9.

func newproc(siz int32, fn *funcval) {argp := add(unsafe.Pointer(&fn), sys.PtrSize)gp := getg()pc := getcallerpc()systemstack(func() {newg := newproc1(fn, argp, siz, gp, pc)_p_ := getg().m.p.ptr()//新创建的G会调用这个方法来决定如何调度runqput(_p_, newg, true)if mainStarted {wakep()}})
}
...if next {retryNext:oldnext := _p_.runnext//当next是true时总会将新进来的G放入下一次调度字段中if !_p_.runnext.cas(oldnext, guintptr(unsafe.Pointer(gp))) {goto retryNext}if oldnext == 0 {return}// Kick the old runnext out to the regular run queue.gp = oldnext.ptr()}

4、下面代码会输出什么?

type People struct{}func (p *People) ShowA() {fmt.Println("showA")p.ShowB()
}
func (p *People) ShowB() {fmt.Println("showB")
}type Teacher struct {People
}func (t *Teacher) ShowB() {fmt.Println("teacher showB")
}func main() {t := Teacher{}t.ShowA()
}

解析:

输出结果为showAshowB。golang 语言中没有继承概念,只有组合,也没有虚方法,更没有重载。因此,*TeacherShowB 不会覆写被组合的 People 的方法。

5、下面代码会触发异常吗?请详细说明

func main() {runtime.GOMAXPROCS(1)int_chan := make(chan int, 1)string_chan := make(chan string, 1)int_chan <- 1string_chan <- "hello"select {case value := <-int_chan:fmt.Println(value)case value := <-string_chan:panic(value)}
}

解析:

结果是随机执行。golang 在多个case 可读的时候会公平的选中一个执行。

6、下面代码输出什么?

func calc(index string, a, b int) int {ret := a + bfmt.Println(index, a, b, ret)return ret
}func main() {a := 1b := 2defer calc("1", a, calc("10", a, b))a = 0defer calc("2", a, calc("20", a, b))b = 1
}

解析:

输出结果为:

10 1 2 3
20 0 2 2
2 0 2 2
1 1 3 4

defer 在定义的时候会计算好调用函数的参数,所以会优先输出1020 两个参数。然后根据定义的顺序倒序执行。

7、请写出以下输入内容

func main() {s := make([]int, 5)s = append(s, 1, 2, 3)fmt.Println(s)
}

解析:

输出为 0 0 0 0 0 1 2 3

make 在初始化切片时指定了长度,所以追加数据时会从len(s) 位置开始填充数据。

8、下面的代码有什么问题?

type UserAges struct {ages map[string]intsync.Mutex
}func (ua *UserAges) Add(name string, age int) {ua.Lock()defer ua.Unlock()ua.ages[name] = age
}func (ua *UserAges) Get(name string) int {if age, ok := ua.ages[name]; ok {return age}return -1
}

解析:

在执行 Get方法时可能被panic。

虽然有使用sync.Mutex做写锁,但是map是并发读写不安全的。map属于引用类型,并发读写时多个协程见是通过指针访问同一个地址,即访问共享变量,此时同时读写资源存在竞争关系。会报错误信息:“fatal error: concurrent map read and map write”。

因此,在 Get 中也需要加锁,因为这里只是读,建议使用读写锁 sync.RWMutex

9、下面的迭代会有什么问题?

func (set *threadSafeSet) Iter() <-chan interface{} {ch := make(chan interface{})go func() {set.RLock()for elem := range set.s {ch <- elem}close(ch)set.RUnlock()}()return ch
}

解析:

默认情况下 make 初始化的 channel 是无缓冲的,也就是在迭代写时会阻塞。

10、以下代码能编译过去吗?为什么?

package mainimport ("fmt"
)type People interface {Speak(string) string
}type Student struct{}func (stu *Student) Speak(think string) (talk string) {if think == "bitch" {talk = "You are a good boy"} else {talk = "hi"}return
}func main() {var peo People = Student{}think := "bitch"fmt.Println(peo.Speak(think))
}

解析:

编译失败,值类型 Student{} 未实现接口People的方法,不能定义为 People类型。

在 golang 语言中,Student*Student 是两种类型,第一个是表示 Student 本身,第二个是指向 Student 的指针。

11、以下代码打印出来什么内容,说出为什么。。。

package mainimport ("fmt"
)type People interface {Show()
}type Student struct{}func (stu *Student) Show() {}func live() People {var stu *Studentreturn stu
}func main() {if live() == nil {fmt.Println("AAAAAAA")} else {fmt.Println("BBBBBBB")}
}

解析:

跟上一题一样,不同的是*Student 的定义后本身没有初始化值,所以 *Studentnil的,但是*Student 实现了 People 接口,接口不为 nil

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/20558.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

快速幂

a^b % q 给定整数 a b q&#xff0c; 求 a 的 b 次方 mod q 根据题目数字取值范围&#xff0c;不能暴力处理。 会有两个问题&#xff1a; 1、计算 a 的次方会超出范围 2、不能循环 b 次计算 a 的乘积&#xff0c;会超时 处理问题1&#xff1a; 每计算一次 a 的乘积&#xf…

视频汇聚平台EasyCVR对接GA/T 1400视图库结构化数据:人员/人脸、非/机动车、物品

在信息化浪潮席卷全球的背景下&#xff0c;公安信息化建设日益成为提升社会治理能力和维护社会稳定的关键手段。其中&#xff0c;GA/T 1400标准作为公安视频图像信息应用系统的核心规范&#xff0c;以其结构化数据处理与应用能力&#xff0c;为公安信息化建设注入了强大的动力。…

【图解IO与Netty系列】Reactor模型

Reactor模型 Reactor模型简介三类事件与三类角色Reactor模型整体流程 各种Reactor模型单Reactor单线程模型单Reactor多线程模型主从Reactor模型 Reactor模型简介 Reactor模型是服务器端用于处理高并发网络IO请求的编程模型&#xff0c;与传统的一请求一线程的同步式编程模型不…

翼龙面板是什么,如何进行搭建

翼龙面板是一个开源的&#xff0c;用于游戏服务器管理的程序&#xff0c;可以方便地在网页界面中创建Minecraft&#xff0c;起源引擎游戏和Teamspeak3 服务器。 它使用前后端程序&#xff0c;因此可以创建多后端节点&#xff0c;对游戏服务器和服务器节点进行统一管理。 对游戏…

Vue进阶之Vue无代码可视化项目(二)

Vue无代码可视化项目 项目初始化路由子路由错误示范正确示范App.vuerouter/index.tsAboutView.vueAboutAboutview.vuerouter/index.ts项目路由router/index.tsApp.vueActionsView.vueDataSourceView.vueLayoutView.vue路由样式App.vue进一步的App.vue项目初始化 路由 router i…

synchronized 锁的到底是什么?

通过8种情况演示锁运行案例&#xff0c;看看我们到底锁的是什么 1锁相关的8种案例演示code package com.bilibili.juc.lock;import java.util.concurrent.TimeUnit;/*** 题目&#xff1a;谈谈你对多线程锁的理解&#xff0c;8锁案例说明* 口诀&#xff1a;线程 操作 资源类* 8…

修改hostname导致RabbitMQ数据丢失

背景介绍 公司的很多关键服务都使用了RabbitMQ来作为消息队列服务, 可以说是非常地关键的一个环节, 最近由于业务量的上升, 导致RabbitMQ的CPU持续走高, 所以抽空研究了一下RabbitMQ的扩容, 利用我们自己运维平台使用的一个单节点的RabbitMQ来作为测试吧.看到这个单节点的Rabbi…

第十七节 huggingface的trainner的断点续训的Demo(resume)

文章目录 前言一、参数决定权重保存1、model.safetensors保存2、scaler.pt保存3、optimizer.pt与scheduler.pt保存4、self.state状态保存(trainer_state.json)5、rng_state.pth保存6、权重相关保存位置(huggingface)二、Resume的Demo1、Demo构建2、实现Resume方法三、Resume训…

005 CentOS 7.9 RabbitMQ安装及配置

https://github.com/rabbitmq/rabbitmq-server/releases https://www.rabbitmq.com/docs/download https://packagecloud.io/rabbitmq/rabbitmq-server https://www.erlang-solutions.com/downloads/ https://www.erlang.org/ 文章目录 卸载erlerl版本安装与下载版本不匹配正…

AI技术的深度探索:重塑未来的智能引擎

随着科技的迅猛进步&#xff0c;人工智能&#xff08;AI&#xff09;技术已经逐渐渗透到我们生活的每一个角落&#xff0c;从简单的智能助手到复杂的决策支持系统&#xff0c;AI技术以其独特的方式和前所未有的速度改变着我们的世界。本文将对AI技术进行深入探讨&#xff0c;从…

开源贡献 | 基于长安链去中心化数字身份合约标准协议(CMDID-1)的DID

DID为每个实体&#xff08;人、组织、物品等&#xff09;提供了一个唯一的全球身份标识符&#xff0c;让用户可以控制和管理的自己的数字身份&#xff0c;并在使用时以最小化的方式出示&#xff0c;将数据所有权归还用户的同时以区块链技术保证了身份的不可篡改性&#xff0c;以…

LeetCode875爱吃香蕉的阿珂

题目描述 珂珂喜欢吃香蕉。这里有 n 堆香蕉&#xff0c;第 i 堆中有 piles[i] 根香蕉。警卫已经离开了&#xff0c;将在 h 小时后回来。珂珂可以决定她吃香蕉的速度 k &#xff08;单位&#xff1a;根/小时&#xff09;。每个小时&#xff0c;她将会选择一堆香蕉&#xff0c;从…

IntelliJ IDEA / Android Studio 方法显示Git提交人

显示方法&#xff1a; 设置 > 编辑器 > 嵌入提示 > Code Vision > 代码作者&#xff08;勾选&#xff09; IntelliJ IDEA Android Studio

springboot编写日志环境搭建过程

AOP记录日志 AOP记录日志的主要优点包括&#xff1a; 1、低侵入性&#xff1a;AOP记录日志不需要修改原有的业务逻辑代码&#xff0c;只需要新增一个切面即可。 2、统一管理&#xff1a;通过AOP记录日志可以将各个模块中需要记录日志的部分进行统一管理&#xff0c;降低了代…

神经网络的工程基础(二)——随机梯度下降法|文末送书

相关说明 这篇文章的大部分内容参考自我的新书《解构大语言模型&#xff1a;从线性回归到通用人工智能》&#xff0c;欢迎有兴趣的读者多多支持。 本文涉及到的代码链接如下&#xff1a;regression2chatgpt/ch06_optimizer/stochastic_gradient_descent.ipynb 本文将讨论利用…

WinApp自动化测试之辅助工具介绍

前篇文章中&#xff0c;我们简单介绍了部分WinApp自动化测试脚本常规操作&#xff0c;今天我们来讲剩余的部分。 文件批量上传 文件批量上传和文件单个上传原理是相同的&#xff0c;单个上传直接传入文件路径即可&#xff0c;批量上传需要进入批量上传的文件所在目录&#xf…

Redis到底是AP还是CP?

这个问题差评&#xff0c;没问清楚。当然&#xff0c;网上一搜&#xff0c;各种各样的狗屁答案都有&#xff0c;有时候是AP的&#xff0c;有时候是CP的&#xff0c;薛定谔的Redis。 好的&#xff0c;那应该怎么问呢&#xff1f;Q1.Redis Cluster集群是AP还是CP&#xff1f; A…

uniapp创建支付密码实现(初始密码,第二次密码)

示例&#xff1a; 插件地址&#xff1a;自定义数字/身份证/密码输入框&#xff0c;键盘密码框可分离使 - DCloud 插件市场 1.下载插件并导入HBuilderX&#xff0c;找到文件夹&#xff0c;copy number-keyboard.vue一份为number-keyboard2.vue&#xff08;number-keyboard.vue是…

C++ STL map容器erase操作避坑

map容器的erase方法有三种重载形式&#xff1a; //1.删除迭代器所指向的元素 //返回值是指向下一个节点的迭代器 iterator erase(iterator it); //2.区间删除 iterator erase(iterator first, iterator last); //3.根据键值删除 //返回值为删除的元素个数 size_type erase(con…

民国漫画杂志《时代漫画》第37期.PDF

时代漫画37.PDF: https://url03.ctfile.com/f/1779803-1248636302-c017ee?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了&#xff0c;截止1937年6月战争来临被迫停刊共发行了39期。 ps: 资源来源网络!