共计 2582 个字符,预计需要花费 7 分钟才能阅读完成。
面试题
这是 Go Quiz 系列的第 3 篇,对于 Go 语言的分号规定和 switch
的个性。
这道题比拟 tricky,通过这道题能够加深咱们对 Go 语言里的分号 :
规定和 switch
个性的了解。
package main
func f() bool {return false}
func main() {switch f()
{
case true:
println(1)
case false:
println(0)
default:
println(-1)
}
}
- A: 1
- B: 0
- C: -1
这道题次要考查以下知识点:
- Go 语言里的分号
:
规定 switch
前面的{
换行后编译器会在背地做什么?
解析
Go 语言和 C++
一样,在每行语句 (statement) 的开端是以分号 :
结尾的。
看到这里,你可能会有点懵,是不是在想:我写 Go 代码的时候也没有在语句开端加分号啊。。。
那是因为 Go 编译器的词法解析程序主动帮你做了这个事件,在须要加分号的中央给你加上了分号。
如果你在代码里显示地加上分号,编译器是不会报错的,只是 Go 不须要也不倡议显示加分号,所有交给编译器去主动实现。
那编译器是怎么往咱们代码里插入分号 :
的呢?规定是什么?咱们看看官网文档的说法:
When the input is broken into tokens, a semicolon is automatically inserted into the token stream immediately after a line’s final token if that token is
- an identifier
- an integer, floating-point, imaginary, rune, or string literal
- one of the keywords
break
,continue
,fallthrough
, orreturn
- one of the operators and punctuation
++
,--
,)
,]
, or}
- To allow complex statements to occupy a single line, a semicolon may be omitted before a closing
")"
or"}"
.
依据这 2 个规定,咱们来剖析下本文最开始的题目,switch
代码如下所示:
// 示例 1
switch f()
{
case true:
println(1)
case false:
println(0)
default:
println(-1)
}
下面的代码对于 switch f()
满足规定 1,会在 )
前面主动加上分号,等价于示例 2
// 示例 2
switch f();
{
case true:
println(1)
case false:
println(0)
default:
println(-1)
}
示例 2 的代码等价于示例 3,程序运行会进入到 case true
这个分支
// 示例 3
switch f();true {
case true:
println(1)
case false:
println(0)
default:
println(-1)
}
所以本题的答案是 1,抉择A
。
总结
-
Effective Go
官网倡议:除了for
循环之外,不要在代码里显示地加上分号:
。你可能在
if
和switch
关键字前面看到过分号:
,比方上面的例子。if i := 0; i < 1 {println(i) } switch os := runtime.GOOS; os { case "darwin": fmt.Println("OS X.") case "linux": fmt.Println("Linux.") default: // freebsd, openbsd, // plan9, windows... fmt.Printf("%s.\n", os) }
尽管代码能够失常工作,然而官网不倡议这样做。咱们能够把分号
:
后面的变量赋值提前,比方批改为上面的版本:i := 0 if i < 1 {println(i) } os := runtime.GOOS switch os { case "darwin": fmt.Println("OS X.") case "linux": fmt.Println("Linux.") default: // freebsd, openbsd, // plan9, windows... fmt.Printf("%s.\n", os) }
-
{
不要换行,如果对于if
,for
,switch
和select
把{
换行了,Go 编译器会主动增加分号:
,会导致预期之外的后果,比方本文最结尾的题目和上面的例子。// good if i < f() {g() } // wrong: compile error if i < f() // wrong! { // wrong! g()}
- 养成应用
go fmt
,go vet
做代码查看的习惯,能够帮咱们提前发现和躲避潜在隐患。
思考题
思考上面这 2 道题的运行后果是什么?大家能够在评论区留下你们的答案。
题目 1:
// Foo prints and returns n.
func Foo(n int) int {fmt.Println(n)
return n
}
func main() {switch Foo(2) {case Foo(1), Foo(2), Foo(3):
fmt.Println("First case")
fallthrough
case Foo(4):
fmt.Println("Second case")
}
}
题目 2:
a := 1
fmt.println(a++)
开源地址
文章和示例代码开源地址在 GitHub: https://github.com/jincheng9/…
公众号:coding 进阶
集体网站:https://jincheng9.github.io/
知乎:https://www.zhihu.com/people/…
好文举荐
- 被 defer 的函数肯定会执行么?
- Go 有援用变量和援用传递么?map,channel 和 slice 作为函数参数是援用传递么?
- new 和 make 的应用区别是什么?
- 一文读懂 Go 匿名构造体的应用场景
- 官网教程:Go 泛型入门
- 一文读懂 Go 泛型设计和应用场景
- Go Quiz: 从 Go 面试题看 slice 的底层原理和注意事项
- Go Quiz: 从 Go 面试题看 channel 的注意事项
References
- https://go101.org/quizzes/swi…
- https://go.dev/doc/effective_go
- https://go101.org/article/lin…
- https://yourbasic.org/golang/…