Golang经典笔试题及答案(下篇)

栏目: Go · 发布时间: 6年前

内容简介:如上所示,运行过程中会发生异常,原因是因为字典

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
    }
}

有两个问题:

  1. 问题一: interface{} 是一个没有声明任何方法的接口。
  2. 问题二: 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


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming PHP

Programming PHP

Rasmus Lerdorf、Kevin Tatroe、Peter MacIntyre / O'Reilly Media / 2006-5-5 / USD 39.99

Programming PHP, 2nd Edition, is the authoritative guide to PHP 5 and is filled with the unique knowledge of the creator of PHP (Rasmus Lerdorf) and other PHP experts. When it comes to creating websit......一起来看看 《Programming PHP》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具