Golang面试题解析(五)
41.执行下面的代码发生什么?
package main type Param map[string]interface{} type Show struct { *Param } func main() { s := new(Show) s.Param["RMB"] = 10000 }
考点:map初始化
map需要初始化后才能使用。
编译错误:invalid operation: s.Param["RMB"] (type *Param does not support indexing)
42.执行下面的代码发生什么?
package main import "fmt" type student struct { Name string } func zhoujielun(v interface{}) { switch msg := v.(type) { case *student, student: msg.Name = "qq" fmt.Print(msg) } }
考点:类型转换
msg不属于student类型,所以没有Name字段。
改为:
s := v.(student) s.Name = "qq"
43.执行下面的代码发生什么?
package main import ( "encoding/json" "fmt" ) type People struct { name string `json:"name"` } func main() { js := `{ "name":"11" }` var p People err := json.Unmarshal([]byte(js), &p) if err != nil { fmt.Println("err: ", err) return } fmt.Println("people: ", p) }
考点:结构体访问控制
这道题坑很大,很多同学一看就以为是p
的初始化问题,实际上是因为name
首字母是小写,导致其他包不能访问,所以输出为空结构体。
改为:
type People struct { Name string `json:"name"` }
44.以下代码有什么问题?
package main func Stop(stop <-chan bool) { close(stop) }
考点:close channel
有方向的channel不可被关闭
45.实现一个函数可以根据指定的size切割切片为多个小切片
解析
func main() { lenth := 11 size := 5 list := make([]int, 0, lenth) for i := 0; i < lenth; i++ { list = append(list, i) } SpiltList(list, size) } func SpiltList(list []int, size int) { lens := len(list) mod := math.Ceil(float64(lens) / float64(size)) spliltList := make([][]int, 0) for i := 0; i < int(mod); i++ { tmpList := make([]int, 0, size) fmt.Println("i=", i) if i == int(mod)-1 { tmpList = list[i*size:] } else { tmpList = list[i*size : i*size+size] } spliltList = append(spliltList, tmpList) } for i, sp := range spliltList { fmt.Println(i, " ==> ", sp) } }
46.实现两个go轮流输出:A1B2C3.....Z26
解析
方法一:有缓冲chan
func ChannelFunc() { zimu := make(chan int, 1) suzi := make(chan int, 1) zimu <- 0 // zimu go func() { for i := 65; i <= 90; i++ { <-zimu fmt.Printf("%v", string(rune(i))) suzi <- i } return }() go func() { for i := 1; i <= 26; i++ { <-suzi fmt.Printf("%v", i) zimu <- i } return }() time.Sleep(1 * time.Second) fmt.Println() }
方法二:无缓冲chan
func Channel1Func() { zimu := make(chan int) suzi := make(chan int) // zimu go func() { for i := 65; i <= 90; i++ { fmt.Printf("%v", string(rune(i))) zimu <- i <-suzi } return }() go func() { for i := 1; i <= 26; i++ { <-zimu fmt.Printf("%v", i) suzi <- i } return }() time.Sleep(10 * time.Second) fmt.Println() }
方法三:使用锁
大家可以自己实现,把结果留言给我,答案后续公布。
47.执行下面代码输出什么?
package main // 47.执行下面代码输出什么? import "fmt" func main() { five := []string{"Annie", "Betty", "Charley", "Doug", "Edward"} for _, v := range five { five = five[:2] fmt.Printf("v[%s]\n", v) } }
考点:range副本机制
循环内的切片值会缩减为2,但循环将在切片值的自身副本上进行操作。 这允许循环使用原始长度进行迭代而没有任何问题,因为后备数组仍然是完整的。
结果:
v[Annie] v[Betty] v[Charley] v[Doug] v[Edward]
48.for 和 for range有什么区别?
考点:for range
- 使用场景不同 for可以
- 遍历array和slice
- 遍历key为整型递增的map
- 遍历string for range可以完成所有for可以做的事情,却能做到for不能做的,包括
- 遍历key为string类型的map并同时获取key和value
- 遍历channel
- 实现不同 for可以获取到的是被循环对象的元素本身,可以对其进行修改; for range使用值拷贝的方式代替被遍历的元素本身,是一个值拷贝,而不是元素本身。
49.解决下面问题:输出MutilParam= [ssss [1 2 3 4]]如何做到输出为[ssss 1 2 3 4]?
package main import "fmt" func MutilParam(p ...interface{}) { fmt.Println("MutilParam=", p) } func main() { MutilParam("ssss", 1, 2, 3, 4) //[ssss 1 2 3 4] iis := []int{1, 2, 3, 4} MutilParam("ssss", iis) //输出MutilParam= [ssss [1 2 3 4]]如何做到输出为[ssss 1 2 3 4] }
考点:函数变参
这样的情况会在开源类库如xorm升级版本后出现Exce函数不兼容的问题。 解决方式有两个:
方法一:interface[]
tmpParams := make([]interface{}, 0, len(iis)+1) tmpParams = append(tmpParams, "ssss") for _, ii := range iis { tmpParams = append(tmpParams, ii) } MutilParam(tmpParams...)
方法二:反射
f := MutilParam value := reflect.ValueOf(f) pps := make([]reflect.Value, 0, len(iis)+1) pps = append(pps, reflect.ValueOf("ssss")) for _, ii := range iis { pps = append(pps, reflect.ValueOf(ii)) } value.Call(pps)
50.编译并运行如下代码会发生什么?
package main // 50.编译并运行如下代码会发生什么? import "fmt" func main() { mmap := make(map[map[string]string]int, 0) mmap[map[string]string{"a": "a"}] = 1 mmap[map[string]string{"b": "b"}] = 1 mmap[map[string]string{"c": "c"}] = 1 fmt.Println(mmap) }
考点:map key类型
golang中的map,的 key 可以是很多种类型,比如 bool, 数字,string, 指针, channel , 还有 只包含前面几个类型的 interface types, structs, arrays。
显然,slice, map 还有 function 是不可以了,因为这几个没法用 ==
来判断,即不可比较类型。 可以将map[map[string]string]int
改为map[struct]int
。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
自动化流程开源框架BotSharp
BotSharp是一款为方便构建智能对话机器人平台而开发的开源框架,最大的特点是所有模型算法都是基于.NET Core开发实现,甚至最基本的Penn Treebank分词标准,都重新用C#实现了。在机器学习python占绝对优势的时代算是不可多得的项目。该项目涉及自然语言理解,计算机视觉和音频处理技术,旨在促进智能机器人助手在信息系统中的开发和应用。目前里面的NLP部分实现的比较多一些,比如n-gram, TF-IDF, CRF, SVM和Bayes。Chabot所需要的算法都已经有了,大家下载完源代码就可以开始搭建Chabot平台了,开箱即用的机器学习算法使.NET程序员能够更快,更轻松地开发对话式人工智能应用程序。 BotSharp的目标是帮助.NET开发者构建自己的流程自动化机器人,以自然语言对话交流的方式让电脑完成一些机械重复的劳动,并加入智能感知进去。让机器人能在声音,图像和语言方面都能与使用者沟通。项目分成几个项目,封装在不同的Dll里,有基本数据算法库,自然语言库,计算机视觉库和语音识别及合成库,最后通过即时通讯通道和使用者进行互动,像Slack和Facebook Mes...
- 下一篇
教你一招如何使用 php 父子进程坑人
现在项目中大多都会使用MQ(消息队列)用来解耦和提升服务稳定性,然后都会面临一个问题,就是消息积压,解决这个问题除了提升处理消息的速度以外,另外就是多开些消费者进程,并发的消费数据。 如果是其他语言可以多开些线程或协程消费数据,但是这些东西,在 php 里并没有很好地支持,所以大家多采用多进程的方式来增加消费者,然后这里又有了两种方式,父子多进程和普通多进程。 然后这里就有了一个有趣的坑人方法,小小一技就能把人坑的想打你,那就是使用父子进程。 这是 php 使用父子进程的一个伪代码 $pid = pcntl_fork(); //父进程和子进程都会执行下面代码 if ($pid == -1) { //错误处理:创建子进程失败时返回-1. die('could not fork'); } else if ($pid) { //父进程会得到子进程号,所以这里是父进程执行的逻辑 pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。 } else { //子进程得到的$pid为0, 所以这里是子进程执行的逻辑。 } 那么怎么坑人呢? 坑人第一步,监听 signa...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS关闭SELinux安全模块
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2全家桶,快速入门学习开发网站教程