切换导航
{{systemName}}
{{ info.Title }}
{{info.Title}}
{{ menu.Title }}
{{menu.Title}}
登录
|
退出
搜索
常见语法题目1
作者:ych
### 1、下面代码能运行吗?为什么。 ```go type Param map[string]interface{} type Show struct { Param } func main1() { s := new(Show) s.Param["RMB"] = 10000 } ``` **解析** 共发现两个问题: 1. `main` 函数不能加数字。 2. `new` 关键字无法初始化 `Show` 结构体中的 `Param` 属性,所以直接对 `s.Param` 操作会出错。 ### 2、请说出下面代码存在什么问题。 ```go type student struct { Name string } func zhoujielun(v interface{}) { switch msg := v.(type) { case *student, student: msg.Name } } ``` **解析:** golang中有规定,`switch type`的`case T1`,类型列表只有一个,那么`v := m.(type)`中的`v`的类型就是T1类型。 如果是`case T1, T2`,类型列表中有多个,那`v`的类型还是多对应接口的类型,也就是`m`的类型。 所以这里`msg`的类型还是`interface{}`,所以他没有`Name`这个字段,编译阶段就会报错。具体解释见:
### 3、写出打印的结果。 ```go 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) } ``` **解析:** 按照 golang 的语法,小写开头的方法、属性或 `struct` 是私有的,同样,在`json` 解码或转码的时候也无法上线私有属性的转换。 题目中是无法正常得到`People`的`name`值的。而且,私有属性`name`也不应该加`json`的标签。 ### 4、下面的代码是有问题的,请说明原因。 ```go type People struct { Name string } func (p *People) String() string { return fmt.Sprintf("print: %v", p) } func main() { p := &People{} p.String() } ``` **解析:** 在golang中`String() string` 方法实际上是实现了`String`的接口的,该接口定义在`fmt/print.go` 中: ```go type Stringer interface { String() string } ``` 在使用 `fmt` 包中的打印方法时,如果类型实现了这个接口,会直接调用。而题目中打印 `p` 的时候会直接调用 `p` 实现的 `String()` 方法,然后就产生了循环调用。 ### 5、请找出下面代码的问题所在。 ```go func main() { ch := make(chan int, 1000) go func() { for i := 0; i < 10; i++ { ch <- i } }() go func() { for { a, ok := <-ch if !ok { fmt.Println("close") return } fmt.Println("a: ", a) } }() close(ch) fmt.Println("ok") time.Sleep(time.Second * 100) } ``` **解析:** 在 golang 中 `goroutine` 的调度时间是不确定的,在题目中,第一个写 `channel` 的 `goroutine` 可能还未调用,或已调用但没有写完时直接 `close` 管道,可能导致写失败,既然出现 `panic` 错误。 ### 6、请说明下面代码书写是否正确。 ```go var value int32 func SetValue(delta int32) { for { v := value if atomic.CompareAndSwapInt32(&value, v, (v+delta)) { break } } } ``` **解析:** `atomic.CompareAndSwapInt32` 函数不需要循环调用。 ### 7、下面的程序运行后为什么会爆异常。 ```go type Project struct{} func (p *Project) deferError() { if err := recover(); err != nil { fmt.Println("recover: ", err) } } func (p *Project) exec(msgchan chan interface{}) { for msg := range msgchan { m := msg.(int) fmt.Println("msg: ", m) } } func (p *Project) run(msgchan chan interface{}) { for { defer p.deferError() go p.exec(msgchan) time.Sleep(time.Second * 2) } } func (p *Project) Main() { a := make(chan interface{}, 100) go p.run(a) go func() { for { a <- "1" time.Sleep(time.Second) } }() time.Sleep(time.Second * 100000000000000) } func main() { p := new(Project) p.Main() } ``` **解析:** 有一下几个问题: 1. `time.Sleep` 的参数数值太大,超过了 `1<<63 - 1` 的限制。 2. `defer p.deferError()` 需要在协程开始出调用,否则无法捕获 `panic`。 ### 8、请说出下面代码哪里写错了 ```go func main() { abc := make(chan int, 1000) for i := 0; i < 10; i++ { abc <- i } go func() { for a := range abc { fmt.Println("a: ", a) } }() close(abc) fmt.Println("close") time.Sleep(time.Second * 100) } ``` **解析:** 协程可能还未启动,管道就关闭了。 ### 9、请说出下面代码,执行时为什么会报错 ```go type Student struct { name string } func main() { m := map[string]Student{"people": {"zhoujielun"}} m["people"].name = "wuyanzu" } ``` **解析:** map的value本身是不可寻址的,因为map中的值会在内存中移动,并且旧的指针地址在map改变时会变得无效。故如果需要修改map值,可以将`map`中的非指针类型`value`,修改为指针类型,比如使用`map[string]*Student`. ### 10、请说出下面的代码存在什么问题? ```go type query func(string) string func exec(name string, vs ...query) string { ch := make(chan string) fn := func(i int) { ch <- vs[i](name) } for i, _ := range vs { go fn(i) } return <-ch } func main() { ret := exec("111", func(n string) string { return n + "func1" }, func(n string) string { return n + "func2" }, func(n string) string { return n + "func3" }, func(n string) string { return n + "func4" }) fmt.Println(ret) } ``` **解析:** 依据4个goroutine的启动后执行效率,很可能打印111func4,但其他的111func*也可能先执行,exec只会返回一条信息。 ### 11、下面这段代码为什么会卡死? ```go package main import ( "fmt" "runtime" ) func main() { var i byte go func() { for i = 0; i <= 255; i++ { } }() fmt.Println("Dropping mic") // Yield execution to force executing other goroutines runtime.Gosched() runtime.GC() fmt.Println("Done") } ``` **解析:** Golang 中,byte 其实被 alias 到 uint8 上了。所以上面的 for 循环会始终成立,因为 i++ 到 i=255 的时候会溢出,i <= 255 一定成立。 也即是, for 循环永远无法退出,所以上面的代码其实可以等价于这样: ```go go func() { for {} } ``` 正在被执行的 goroutine 发生以下情况时让出当前 goroutine 的执行权,并调度后面的 goroutine 执行: - IO 操作 - Channel 阻塞 - system call - 运行较长时间 如果一个 goroutine 执行时间太长,scheduler 会在其 G 对象上打上一个标志( preempt),当这个 goroutine 内部发生函数调用的时候,会先主动检查这个标志,如果为 true 则会让出执行权。 main 函数里启动的 goroutine 其实是一个没有 IO 阻塞、没有 Channel 阻塞、没有 system call、没有函数调用的死循环。 也就是,它无法主动让出自己的执行权,即使已经执行很长时间,scheduler 已经标志了 preempt。 而 golang 的 GC 动作是需要所有正在运行 `goroutine` 都停止后进行的。因此,程序会卡在 `runtime.GC()` 等待所有协程退出。
相关推荐
golang 中解析 tag 是怎么实现的?反射原理是什么?(中高级肯定会问,比较难,需要自己多去总结)
使用gorm不当出现too Many Connections的问题
golang map 使用注意的点,是否并发安全?
uint 类型溢出问题
Golang中defer和return执行的先后顺序
golang orm框架 gorm
讲讲 Go 的 select 底层数据结构和一些特性?(难点,没有项目经常可能说不清,面试一般会问你项目中怎么使用select)
golang中两个变量值的4种交换方式
golang进行封包和拆包的完整解决方案
对已经关闭的 chan 进行读写,会怎么样?为什么?
调用函数传入结构体时,应该传值还是指针? (Golang 都是传值)
为 sync.WaitGroup 中Wait函数支持 WaitTimeout 功能.
单例模式的应用场景
Golang判断slice是否相等
Golang空结构体 struct{} 的使用
讲讲 Go 的 defer 底层数据结构和一些特性?
go defer,多个 defer 的顺序,defer 在什么时机会修改返回值?
序列化协议
Golang 单引号,双引号,反引号的区别?
Golang表示枚举类型的详细讲解
昨天那个在for循环里append元素的同事,今天还在么?
什么是死锁?死锁产生的原因?如何避免死锁?
golang并发题目测试
交替打印数字和字母
golang面试题
for range 的时候它的地址会发生变化么?
B+树为什么快
数组和切片的区别 (基本必问)
实现阻塞读且并发安全的map
机器人坐标问题
复利计算 递归/非递归
在 golang 协程和channel配合使用
MySQL索引原理
写出以下逻辑,要求每秒钟调用一次proc并保证程序不退出?
讲讲 Go 的 slice 底层数据结构和一些特性?
高并发下的锁与map的读写
Redis的优点
常见语法题目2
判断两个给定的字符串排序后是否一致
字符串替换问题
ElasticSearch使用场景
golang 中 make 和 new 的区别?(基本必问)
七道语法找错题目
判断字符串中字符是否全都不同
golang 实现一个负载均衡案例(随机,轮训)
redis缓存穿透、缓存击穿、缓存雪崩原因+解决方案
基本数据结构和算法
消息队列使用的场景介绍
操作系统基本原理
翻转字符串
redis在项目中的使用
TiDB使用场景
评论区
先去登录
版权所有:机遇屋在线 Copyright © 2021-2025 jiyuwu Co., Ltd.
鲁ICP备16042261号-1