条件结构和分支结构:
- if-else 结构
- switch 结构
- select 结构,用于 channel 的选择
使用迭代或循环结构来重复执行一次或多次某段代码(任务):
0x01 if-else 结构
基本用法
1
2
3
4
5
6
7
8
|
// initialization 完成变量初始化,可有可无,condition1 主要是 bool 类型即可
if initialization; condition1 {
// do something
} else if condition2 {
// do something else
} else {
// catch-all or default
}
|
为了代码的可读性,还是不要在 if 后面加入太多的 else-if 结构。如果你必须使用这种形式,则把尽可能先满足的条件放在前面
常见写法是省略 else 部分。无论满足哪个条件都会返回 x 或者 y 时,一般使用以下写法:
1
2
3
4
|
if condition {
return x
}
return y
|
有用示例
1、判断一个字符串是否为空
1
2
3
4
|
// 方法1
if str == "" { ... }
// 方法2
if len(str) == 0 {...}
|
2、判断运行 Go 程序的操作系统类型,这可以通过常量 runtime.GOOS 来判断
1
2
3
4
5
|
if runtime.GOOS == "windows" {
. ..
} else { // Unix-like
. ..
}
|
一般会放在init()函数中执行。
例如:
1
2
3
4
5
6
7
8
9
|
var prompt = "Enter a digit, e.g. 3 "+ "or %s to quit."
func init() {
if runtime.GOOS == "windows" {
prompt = fmt.Sprintf(prompt, "Ctrl+Z, Enter")
} else { //Unix-like
prompt = fmt.Sprintf(prompt, "Ctrl+D")
}
}
|
3、函数 Abs() 用于返回一个整型数字的绝对值
1
2
3
4
5
6
|
func Abs(x int) int {
if x < 0 {
return -x
}
return x
}
|
4、isGreater 用于比较两个整型数字的大小
1
2
3
4
5
6
|
func isGreater(x, y int) bool {
if x > y {
return true
}
return false
}
|
5、if 条件中 声明变量
1
2
3
4
5
|
// 使用 := 简短方式声明变量
if val := 10; val > max {
// do something
}
// val 作用域 在 if-else 代码块中
|
等价于
1
2
3
4
|
val := 10
if val > max {
// do something
}
|
0x02 测试多返回值函数的错误
comma,ok 模式(pattern)
如果确实存在错误,则会打印相应的错误信息然后通过 return 提前结束函数的执行,习惯写法:
1
2
3
4
5
6
|
value, err := pack1.Function1(param1)
if err != nil {
fmt.Printf("An error occured in pack1.Function1 with parameter %v", param1)
return err
}
// 未发生错误,继续执行:
|
错误发生的同时终止程序的运行,习惯写法:
1
2
3
4
|
if err != nil {
fmt.Printf("Program stopping with error %v", err)
os.Exit(1) // 终止退出程序
}
|
将错误的获取放置在 if 语句的初始化部分
1
2
3
4
|
if err := file.Chmod(0664); err != nil {
fmt.Println(err)
return err
}
|
将 ok-pattern 的获取放置在 if 语句的初始化部分,然后进行判断
1
2
3
|
if value, ok := readData(); ok {
…
}
|
什么时候进行错误判断?
- 当打印到控制台时,可以将该函数返回的错误忽略;
- 当输出到文件流、网络流等具有不确定因素的输出对象时,应该始终检查是否有错误发生
0x03 switch 结构
1. 基本用法:
1
2
3
4
5
6
7
8
|
switch var1 {
case val1:
...
case val2:
...
default:
...
}
|
说明:
- 接受任意形式的表达式
- 同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1, val2, val3
- 不使用break语句结束分支,匹配到某个分支,执行相应代码后,自动退出switch代码块
- 执行下一个分支的代码,使用 fallthrough 关键字来达到目的
2. 高级用法:
不提供任何被判断的值,对每一个分支条件进行判断,相当于链式 if-else
1
2
3
4
5
6
7
8
|
switch {
case condition1:
...
case condition2:
...
default:
...
}
|
示例
1
2
3
4
5
6
7
8
|
switch {
case i < 0:
f1()
case i == 0:
f2()
case i > 0:
f3()
}
|
3. 第三种用法
包含一个初始化语句
1
2
3
4
5
6
7
8
|
switch initialization {
case val1:
...
case val2:
...
default:
...
}
|
这种形式可以非常优雅地进行条件判断:
1
2
3
4
5
6
7
8
|
switch result := calculate(); {
case result < 0:
...
case result > 0:
...
default:
// 0
}
|
4. 类型判断:type-switch
对接口变量的类型进行类型判断
1
2
3
4
5
6
7
8
9
10
|
switch t := areaIntf.(type) {
case *Square:
fmt.Printf("Type Square %T with value %v\n", t, t)
case *Circle:
fmt.Printf("Type Circle %T with value %v\n", t, t)
case nil:
fmt.Printf("nil value: nothing to check?\n")
default:
fmt.Printf("Unexpected type %T\n", t)
}
|
0x 04 for 结构
1. 基于计数器的迭代
基本形式
1
2
3
|
for 初始化语句; 条件语句; 修饰语句 {
}
|
注意,永远不要在循环体内修改计数器,这在任何语言中都是非常差的实践!
2. 基于条件判断的迭代
只有条件语句。
基本形式为:
3. 无限循环
连条件语句都不要了
基本形式为:
循环体内必须有退出机制,
- break : 退出当前循环体,循环体后续的代码还会执行
- return :提前对函数进行返回,不会执行后续的代码
4. for-range 结构
作用:迭代任何一个集合
基本形式:
1
2
3
|
for ix, val := range coll {
}
|
说明:
val使用为集合中对应索引的值拷贝,一般只有只读性质,对其做任何修改都不会影响到集合中原有的值
如果val为指针,产生指针拷贝,依旧不会修改集合中的原值
一个字符串是 Unicode 编码的字符(或称之为 rune)集合
原文地址:
http://www.manoner.com/post/GoLand/Go%E8%AF%AD%E8%A8%80%E5%85%A5%E9%97%A8%E6%8C%87%E5%8D%97%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-%E6%8E%A7%E5%88%B6%E7%BB%93%E6%9E%84/
|