千万别给自己的懒惰
找借口
千万别给自己的愚昧
找理由
千万别给自己的无知
找台阶
——实干《实干日记》
第6关 条件语句和循环语句
- 6-1 if条件控制语句
- 6-2 go语言的for循环
- 6-3 go语言的for range用法
- 6-4 goto语句能帮我们完成什么功能?
- 6-5 switch语句能让代码可读性更高
- 6-6 python中如何实现switch的效果?
6-1 if条件控制语句
实例代码:【着重看简化写法,还有if语句代码块的变量的作用域】
package main
import "fmt"
func main(){
// if 语句
num := 12
if num % 2 == 0{
fmt.Println("偶数") // 偶数
}else {
fmt.Println("奇数")
}
score := 99
if score >= 90 {
fmt.Println("优秀") // 优秀
}else if score >=60{
fmt.Println("一般")
}else {
fmt.Println("不合格")
}
// 简化写法 if statement;condition
if age :=18;age % 2 == 0{
fmt.Println("偶数") // 偶数
}else{
fmt.Println(age)
}
//fmt.Println(age) // undefined: age 因为age的作用域在if代码块里
}
6-2 go语言的for循环
示例代码如下:
package main
import "fmt"
func main(){
// for init;condition;post{} 计算 1-10的和
sum := 0
for i:=1;i<=10;i++{
sum += i
} // i 是局部变量
fmt.Println(sum) // 55
// for 循环执行逻辑
//1.只执行1次 i:=1
//2.判断i<=10
//3.sum+=1,此时sum=0+1=1
//4.执行i++,此时i=1+1=2
//5.判断i<=10
//6.执行sum+=i,此时sum=1+2=3
//7.执行i++,此时i=2+1=3
// 死循环
//for {
// fmt.Println("die for loop")
//}
// 注意一下三种写法
j := 0
for j <= 9 {
fmt.Println(j)
j++
}
for ;j <= 9; {
fmt.Println(j)
j++
}
for ;j <= 9; j++{
fmt.Println(j)
}
}
6-3 go语言的for range用法
示例代码1:
package main
import "fmt"
func main(){
// 循环字符串
name := "keegan"
//for index,value := range name{
// // value为什么是数字?ascii值
// //fmt.Println(index,value)
// // 格式化输出,打印index和value
// fmt.Printf("index:%d,value:%c\n",index,value)
//}
/*
0 107
1 101
2 101
3 103
4 97
5 110
*/
/*
index:0,value:k
index:1,value:e
index:2,value:e
index:3,value:g
index:4,value:a
index:5,value:n
*/
for _,value := range name{
// value为什么是数字?ascii值
//fmt.Println(index,value)
// 格式化输出,只打印value的值
fmt.Printf("%c\n",value)
}
/*
k
e
e
g
a
n
*/
// 1.name是一个字符串 2.字符串是一个字符数组,索引取值
}
示例代码2:【问题来了】
package main
import "fmt"
func main(){
// 循环字符串
name := "keegan:代码写注释"
fmt.Printf("%c\n",name[0])
fmt.Printf("%c\n",name[7])
/*
k
ä
*/
}
我们期望的输出结果是:
k
代
然而实际输出结果是:
k
ä
why呢?
utf-8编码问题,用rune处理。
这个时候怎么办?
第五关讲过,统一转成rune。
import "fmt"
func main(){
// 循环字符串
name := "keegan:代码写注释"
name_arr := []rune(name)
for i := 0;i<len(name_arr);i++{
fmt.Printf("%c\n",name_arr[i])
}
}
/*输出结果:
k
e
e
g
a
n
:
代
码
写
注
释
*/
在字符串遍历的时候,尽量使用range。
对于含有中文的字符串遍历的乱码问题,统一转成rune数组。然后对数组遍历。
package main
import "fmt"
func main(){
// 循环字符串
name := "keegan:代码写注释"
name_arr := []rune(name)
for _,value := range(name_arr){
fmt.Printf("%c\n",value)
}
}
/*输出结果:
k
e
e
g
a
n
:
代
码
写
注
释
*/
6-4 goto语句能帮我们完成什么功能?
看定义:
Go 语言的 goto 语句可以无条件地转移到过程中指定的行。
goto 语句通常与条件语句配合使用。可用来实现条件转移, 构成循环,跳出循环体等功能。
但是,在结构化程序设计中一般不主张使用 goto 语句, 以免造成程序流程的混乱,使理解和调试程序都产生困难。
能不用就不用。
看代码:
小试牛刀:
package main
import "fmt"
func main() {
// 定义局部变量
var a int = 10
// 循环效果:跳出15的打印。【就是不打印15,打印其他的东西】
LOOP:for a < 20{
// 如果等于15
if a == 15 {
// 累加器
a++
// 跳出循环 执行LOOP对应的语句,执行下一次循环
goto LOOP
// 这里的循环效果还可以用continue和break来实现
}
// 如果不等于15就正常打印
fmt.Printf("a的值为:%d\n",a)
a++
}
}
应用场景:使用goto退出多层循环
package main
import "fmt"
func main() {
var breakAgain bool
// 外循环
for x := 0; x < 10; x++ {
// 内循环
for y := 0; y < 10; y++ {
// 满足某个条件时, 退出循环
if y == 2 {
// 设置退出标记
breakAgain = true
// 退出本次循环
break
}
}
// 根据标记, 还需要退出一次循环
if breakAgain {
break
}
}
fmt.Println("done")
}
/*输出结果
done
*/
优化后:
package main
import "fmt"
func main() {
for x := 0; x < 10; x++ {
for y := 0; y < 10; y++ {
if y == 2 {
// 跳转到标签
goto breakHere
}
}
}
// 手动返回, 避免执行进入标签
return
// 标签
breakHere:
fmt.Println("done")
}
/*输出结果
done
*/
秀的一批,蒂花之秀~
应用场景:使用goto集中处理错误
多处错误处理存在代码重复时是非常棘手的,例如:
package main
import "fmt"
func main() {
err := firstCheckError()
if err != nil {
// 代码重复,同样逻辑
fmt.Println(err)
exitProcess()
return
}
err = secondCheckError()
if err != nil {
// 代码重复,同样逻辑
fmt.Println(err)
exitProcess()
return
}
fmt.Println("done")
}
上述代码修改一下:【goto处理】
package main
import "fmt"
func main() {
err := firstCheckError()
if err != nil {
goto onExit
}
err = secondCheckError()
if err != nil {
goto onExit
}
fmt.Println("done")
return
onExit:
fmt.Println(err)
exitProcess()
}
goto语句能不用就不用,写的爽,维护的麻烦。因为代码执行的逻辑一般都是自顶向下的【大家都习惯了】,一行一行执行的,最容易维护。
6-5 switch语句能让代码可读性更高
来看这样的代码:
package main
import "fmt"
func main(){
score := 75
grade := "A"
if score >= 90{
grade = "A"
}else if 80 <= score && score <= 89{
grade = "B"
}else if 70 <= score && score <= 79{
grade = "C"
}else if 60 <= score && score <= 69 {
grade = "D"
}else {
grade = "E"
}
fmt.Println(grade) // C
}
大量的if-else if分支语句看起来并不是很优雅。
用switch处理之后:
package main
import "fmt"
func main() {
/* 定义局部变量 */
score := 99
grade := "A"
switch {
case score >= 90: grade = "A"
case 80 <= score && score <= 89: grade = "B"
case 70 <= score && score <= 79: grade = "C"
case 60 <= score && score <= 69: grade = "D"
default: grade = "E"
}
fmt.Printf("你的等级是 %s\n", grade ); // 你的等级是 A
}
上述代码默认有break效果的。【跟c语言用法一样的】
如果不想break,像第1个case执行完之后接着执行第2个case … 一直执行到default语句然后退出switch语句 怎么做?
用fallthrough
package main
import "fmt"
func main() {
/* 定义局部变量 */
score := 99
grade := "A"
switch {
case score >= 90: grade = "A";fallthrough
case 80 <= score && score <= 89: grade = "B"
case 70 <= score && score <= 79: grade = "C"
case 60 <= score && score <= 69: grade = "D"
default: grade = "E"
}
fmt.Printf("你的等级是 %s\n", grade ); // 你的等级是 B
}
执行到 score >= 90的时候,score := 99符合该case,但是加了fallthrough,继续往下走,
执行到80 <= score && score <= 89,此时grade= “B”,默认有break效果,退出switch语句,执行Printf输出语句,
输出 你的等级是 B
现在加点东西,对分数判断,是打印优秀,还是打印良好?【不需要加fallthrough,不合逻辑】
package main
import "fmt"
func main() {
/* 定义局部变量 */
score := 9
grade := "A"
switch {
case score >= 90:
grade = "A";
fmt.Println("优秀");
case 80 <= score && score <= 89:
grade = "B";
fmt.Println("良好")
case 70 <= score && score <= 79:
grade = "C";
fmt.Println("中等")
case 60 <= score && score <= 69:
grade = "D";
fmt.Println("合格")
default:
grade = "E";
fmt.Println("请准备补考")
}
fmt.Printf("你的等级是 %s\n", grade ); // 你的等级是 A
}
再来看一个case满足多种情况的输出:
package main
import "fmt"
func main() {
/* 定义局部变量 */
var grade string = "B"
var marks int = 60
switch marks {
case 90: grade = "A"
case 80: grade = "B"
// 一个case满足多种情况.即一分支多值
case 70,60:grade = "C";fmt.Println("都是合格")
default: grade = "D"
}
fmt.Printf("你的等级是 %s\n", grade ); // 你的等级是 C
}
6-6 python中如何实现switch的效果?
查看Python官方:PEP 3103-A Switch/Case Statement
发现其实实现Switch Case需要被判断的变量是可哈希的和可比较的,这与Python倡导的灵活性有冲突。在实现上,优化不好做,可能到最后最差的情况汇编出来跟If Else组是一样的。所以Python没有支持。
但是,也可以实现类似switch的效果:
# https://www.python.org/dev/peps/pep-3103/
score = 90
switch = {
90: lambda : print("A"),
80: lambda : print("B"),
70: lambda : print("C"),
}
switch[score]() # A
以下代码仅供参考:
class switch(object):
def __init__(self, value):
self.value = value
self.fall = False
def __iter__(self):
"""Return the match method once, then stop"""
yield self.match
raise StopIteration
def match(self, *args):
"""Indicate whether or not to enter a case suite"""
if self.fall or not args:
return True
elif self.value in args: # changed for v1.5, see below
self.fall = True
return True
else:
return False
# The following example is pretty much the exact use-case of a dictionary,
# but is included for its simplicity. Note that you can include statements
# in each suite.
v = 'ten'
for case in switch(v):
if case('one'):
print 1
break
if case('two'):
print 2
break
if case('ten'):
print 10
break
if case('eleven'):
print 11
break
if case(): # default, could also just omit condition or 'if True'
print "something else!"
# No need to break here, it'll stop anyway
# break is used here to look as much like the real thing as possible, but
# elif is generally just as good and more concise.
# Empty suites are considered syntax errors, so intentional fall-throughs
# should contain 'pass'
c = 'z'
for case in switch(c):
if case('a'): pass # only necessary if the rest of the suite is empty
if case('b'): pass
# ...
if case('y'): pass
if case('z'):
print "c is lowercase!"
break
if case('A'): pass
# ...
if case('Z'):
print "c is uppercase!"
break
if case(): # default
print "I dunno what c was!"
# As suggested by Pierre Quentel, you can even expand upon the
# functionality of the classic 'case' statement by matching multiple
# cases in a single shot. This greatly benefits operations such as the
# uppercase/lowercase example above:
import string
c = 'A'
for case in switch(c):
if case(*string.lowercase): # note the * for unpacking as arguments
print "c is lowercase!"
break
if case(*string.uppercase):
print "c is uppercase!"
break
if case('!', '?', '.'): # normal argument passing style also applies
print "c is a sentence terminator!"
break
if case(): # default
print "I dunno what c was!"
# Since Pierre's suggestion is backward-compatible with the original recipe,
# I have made the necessary modification to allow for the above usage.