# go 面试题
# 第一天
# 1. 下面这段代码输出什么?
type Direction int
const (
North Direction = iota + 1
East
South
West
)
func (d Direction) String() string {
return [...]string{"North", "East", "South", "West"}[d]
}
func main() {
fmt.Println(South)
}
参考答案及解析:
答案:West。
知识点:iota 的用法、类型的 String() 方法。根据 iota 的用法推断出 South 的值是 3;另外,如果类型定义了 String() 方法,当使用 fmt.Printf()、fmt.Print() 和 fmt.Println() 会自动使用 String() 方法,实现字符串的打印。
# 2. 下面代码输出什么?
type Math struct {
x, y int
}
var m = map[string]Math{
"foo": Math{2, 3},
}
func main() {
m["foo"].x = 4
fmt.Println(m["foo"].x)
}
- A. 4
- B. compilation error
参考答案及解析:
答案:B,编译报错 cannot assign to struct field m[“foo”].x in map。 错误原因:对于类似 X = Y的赋值操作,必须知道 X 的地址,才能够将 Y 的值赋给 X,但 go 中的 map 的 value 本身是不可寻址的。 有两个解决办法: 1.使用临时变量
type Math struct {
x, y int
}
var m = map[string]Math{
"foo": Math{2, 3},
}
func main() {
tmp := m["foo"]
tmp.x = 4
m["foo"] = tmp
fmt.Println(m["foo"].x)
}
2.修改数据结构
type Math struct {
x, y int
}
var m = map[string]*Math{
"foo": &Math{2, 3},
}
func main() {
m["foo"].x = 4
fmt.Println(m["foo"].x)
fmt.Printf("%#v", m["foo"]) // %#v 格式化输出详细信息
}
# 第二天
# 1. 下面的代码有什么问题?
func main() {
fmt.Println([...]int{1} == [2]int{1})
fmt.Println([]int{1} == []int{1})
}
参考答案及解析:
答案:有两处错误。
1. go 中不同类型是不能比较的,而数组长度是数组类型的一部分,所以 […]int{1} 和 [2]int{1} 是两种不同的类型,不能比较;
2. 切片是不能比较的;
# 2.下面这段代码输出什么?
var p *int
func foo() (*int, error) {
var i int = 5
return &i, nil
}
func bar() {
//use p
fmt.Println(*p)
}
func main() {
p, err := foo()
if err != nil {
fmt.Println(err)
return
}
bar()
fmt.Println(*p)
}
- A. 5 5
- B. runtime error
参考答案及解析:B。
知识点:变量作用域。问题出在操作符:=,对于使用:=定义的变量,如果新变量与同名已定义的变量不在同一个作用域中,那么 Go 会新定义这个变量。对于本例来说,main() 函数里的 p 是新定义的变量,会遮住全局变量 p,导致执行到bar()时程序,全局变量 p 依然还是 nil,程序随即 Crash。
正确的做法是将 main() 函数修改为:
func main() {
var err error
p, err = foo()
if err != nil {
fmt.Println(err)
return
}
bar()
fmt.Println(*p)
}
这道题目引自 Tony Bai 老师的一篇文章,原文讲的很详细,推荐。https://tonybai.com/2015/01/13/a-hole-about-variable-scope-in-golang/
# 第三天
通过让 IPAddr 类型实现 fmt.Stringer 来打印点号分隔的地址。
例如,IPAddr{1, 2, 3, 4} 应当打印为 “1.2.3.4”。
package main
import (
"fmt"
)
type IPAddr [4]byte
func main() {
hosts := map[string]IPAddr{
"loopback": {127, 0, 0, 1},
"googleDNS": {8, 8, 8, 8},
}
for name, ip := range hosts {
fmt.Printf("%v: %v\n", name, ip)
}
}
// TODO: 给 IPAddr 添加一个 "String() string" 方法
func (ip IPAddr) String() string {
var str string
for _, i := range ip {
str = str + fmt.Sprintf("%v.", i)
}
return str[:len(str)-1]
}