内容简介:如上所示,运行过程中会发生异常,原因是因为字典
1. 下面代码能运行吗?为什么
type Param map[string]interface{}
type Show struct {
Param
}
func main1() {
s := new(Show)
s.Param["RMB"] = 10000
}
运行结果:
panic: assignment to entry in nil map goroutine 1 [running]: main.main()
如上所示,运行过程中会发生异常,原因是因为字典 Param
的默认值为 nil
,当给字典 nil
增加键值对是就会发生运行时错误 panic: assignment to entry in nil map
。
正确的修改方案如下:
package main
import "fmt"
type Param map[string]interface{}
type Show struct {
Param
}
func main() {
// 创建Show结构体对象
s := new(Show)
// 为字典Param赋初始值
s.Param = Param{}
// 修改键值对
s.Param["RMB"] = 10000
fmt.Println(s)
}
运行结果如下:
&{map[RMB:10000]}
Process finished with exit code 0
2. 请说出下面代码存在什么问题
type student struct {
Name string
}
func f(v interface{}) {
switch msg := v.(type) {
case *student, student:
msg.Name
}
}
有两个问题:
-
问题一:
interface{}是一个没有声明任何方法的接口。 -
问题二:
Name是一个属性,而不是方法,interface{}类型的变量无法调用属性。
3. 写出打印的结果。
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)
}
输出内容如下:
people: {}
p中的属性值为空的原因是因为,name的首字母小写,修改成大写,重新运行即可。
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)
}
运行结果如下:
people: {11}
Process finished with exit code 0
4. 下面的代码是有问题的,请说明原因。
package main
import "fmt"
type People struct {
Name string
}
func (p *People) String() string {
return fmt.Sprintf("print: %v", p)
}
func main() {
p := &People{}
p.String()
}
运行结果如下:
runtime: goroutine stack exceeds 1000000000-byte limit fatal error: stack overflow runtime stack: runtime.throw(0x10c122b, 0xe)
如下所示,上面的代码出现了栈溢出,原因是因为%v格式化字符串是本身会调用String()方法,上面的栈溢出是因为无限递归所致。
5. 请找出下面代码的问题所在。
package main
import (
"fmt"
"time"
)
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)
}
运行结果如下:
panic: send on closed channel ok goroutine 5 [running]: main.main.func1(0xc420098000)
解析:出现上面错误的原因是因为提前关闭通道所致。
正确代码如下:
package main
import (
"fmt"
"time"
)
func main() {
// 创建一个缓冲通道
ch := make(chan int, 1000)
go func() {
for i := 0; i < 10; i++ {
ch <- i
}
}()
go func() {
for i := 0; i < 10; i++ {
a, ok := <-ch
if !ok {
fmt.Println("close")
close(ch)
return
}
fmt.Println("a: ", a)
}
}()
fmt.Println("ok")
time.Sleep(time.Second)
}
运行结果如下:
ok a: 0 a: 1 a: 2 a: 3 a: 4 a: 5 a: 6 a: 7 a: 8 a: 9
6. 请说明下面代码书写是否正确。
var value int32
func SetValue(delta int32) {
for {
v := value
if atomic.CompareAndSwapInt32(&value, v(v+delta)) {
break
}
}
}
atomic.CompareAndSwapInt32
里面一共三个参数,上面的书写错误,正确的书写是: atomic.CompareAndSwapInt32(&value, v,v+delta)
-
func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool) -
第一个参数的值应该是指向被操作值的指针值。该值的类型即为
*int32。 -
后两个参数的类型都是
int32类型。它们的值应该分别代表被操作值的旧值和新值 -
CompareAndSwapInt32·函数在被调用之后会先判断参数addr指向的被操作值与参数old`的值是否相等。 -
仅当此判断得到肯定的结果之后,该函数才会用参数
new代表的新值替换掉原先的旧值。否则,后面的替换操作就会被忽略。
完整代码如下:
package main
import (
"sync/atomic"
"fmt"
)
var value int32
func SetValue(delta int32) {
for {
v := value
// 比较并交换
if atomic.CompareAndSwapInt32(&value, v,v+delta) {
fmt.Println(value)
break
}
}
}
func main() {
SetValue(100)
}
运行结果为 100
.
7. 下面的程序运行后为什么会爆异常。
package main
import (
"fmt"
"time"
)
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 * 100)
}
func main() {
p := new(Project)
p.Main()
}
运行结果如下:
panic: interface conversion: interface {} is string, not int
goroutine 17 [running]:
main.(*Project).exec(0x1157c08, 0xc420068060)
出现异常的原因是因为写入到管道的数据类型为 string
,而 m := msg.(int)
这句代码里面却使用了 int
,修改方法,将 int
修改为 string
即可。
完整正确代码如下:
package main
import (
"fmt"
"time"
)
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.(string)
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 * 100)
}
func main() {
p := new(Project)
p.Main()
}
运行结果如下:
msg: 1 msg: 1 msg: 1 . . . msg: 1 msg: 1 msg: 1 msg: 1 msg: 1
8. 请说出下面代码哪里写错了。
func main() {
abc := make(chan int, 1000)
for i := 0; i < 10; i++ {
abc <- i
}
go func() {
for {
a := <-abc
fmt.Println("a: ", a)
}
}()
close(abc)
fmt.Println("close")
time.Sleep(time.Second * 100)
}
go中的for循环是死循环,应该设置出口。正确代码如下:
package main
import (
"fmt"
"time"
)
func main() {
abc := make(chan int, 1000)
for i := 0; i < 10; i++ {
abc <- i
}
go func() {
for {
a,ok := <-abc
if !ok {
fmt.Println("结束!")
return
}
fmt.Println("a: ", a)
}
}()
close(abc)
fmt.Println("close")
time.Sleep(time.Second * 100)
}
运行结果为:
close a: 0 a: 1 a: 2 a: 3 a: 4 a: 5 a: 6 a: 7 a: 8 a: 9 结束!
9. 请说出下面代码,执行时为什么会报错
type Student struct {
name string
}
func main() {
m := map[string]Student{"people": {"liyuechun"}}
m["people"].name = "wuyanzu"
}
答案:报错的原因是因为不能修改字典中 value
为结构体的属性值。
代码作如下修改方可运行:
package main
import "fmt"
type Student struct {
name string
}
func main() {
m := map[string]Student{"people": {"liyuechun"}}
fmt.Println(m)
fmt.Println(m["people"])
// 不能修改字典中结构体属性的值
//m["people"].name = "wuyanzu"
var s Student = m["people"] //深拷贝
s.name = "xietingfeng"
fmt.Println(m)
fmt.Println(s)
}
运行结果如下:
map[people:{liyuechun}]
{liyuechun}
map[people:{liyuechun}]
{wuyanzu}
10. 请说出下面的代码存在什么问题
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)
}
return <-ch
之执行一次,所以不管传入多少 query
函数,都只是读取最先执行完的 query
。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 威胁情报相关标准简介 (下篇)
- 【前端面试分享】- 寒冬求职下篇
- 【MyBatis源码分析】Configuration加载(下篇)
- 【MyBatis源码分析】Configuration加载(下篇)
- 系统架构系列(四):业务架构实战下篇
- Spring 源码学习(七)扩展功能 下篇
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
PHP for the World Wide Web, Second Edition (Visual QuickStart Gu
Larry Ullman / Peachpit Press / 2004-02-02 / USD 29.99
So you know HTML, even JavaScript, but the idea of learning an actual programming language like PHP terrifies you? Well, stop quaking and get going with this easy task-based guide! Aimed at beginning ......一起来看看 《PHP for the World Wide Web, Second Edition (Visual QuickStart Gu》 这本书的介绍吧!