Go语言入门基础(五)——条件语句和循环

175 阅读4分钟

阅读本文前,建议已掌握基本C语言语法及规范,本文将更加侧重Go语言和C系列语言的区别以达到快速上手的目的

本文主要参考《Go语言圣经(中文版)》及个人实践撰写,具体可参考: Go语言圣经

本文作为该系列第五篇,将重点介绍条件语句/循环

条件语句

条件语句用于程序根据给定的一个或多个条件的满足性,选择执行的语句。C语言中的if-else就是典型的条件分支,Go语言中的条件语句可以分为if-else语句/switch-case语句/select-case语句

if-(else)

Go语言中的if和C语言中格式唯一的不同是条件无括号,标准语句如下:

if 布尔表达式 {
    /* 布尔表达式为真时执行 */
}

同理else if后的条件表达式也不需要括号。注意else if和else的前后括号必须在同一行,标准语句如下:

if 布尔表达式1 {
    ...
} else if 布尔表达式2 {
    ...
} else {
    ...
}

以下是使用if-else条件实现的猜数游戏实例,代码如下:

package main

import "fmt"

func main() {
	var num int
	fmt.Print("Please input a number: ")   //输入要猜的数字
	fmt.Scanf("%d\n", &num)
	for {
		var x int
		fmt.Print("Guess a number: ")
		fmt.Scanf("%d\n", &x)
		if x < num {
			fmt.Println("too small")
		} else if x > num {
			fmt.Println("too big")
		} else {
			fmt.Println("right")
			break
		}
	}
}

运行结果如下: image.png

和C语言中一样,if-else可以层层嵌套。

switch-case

Go语言中的switch-case多分支和C语言中几乎一样,但使用相对灵活。以下是一段标准的Go语言case语句:

switch var {
    case val1:
        ...
    case val2:
        ...
    default:
        ...
}

总结下来Go语言的case和C语言有以下区别:

  • case后无需加break语句,自动匹配到合适的case项后自动执行break(即不会运行其他case语句)
  • case后的变量val1/val2...可以是同类型的任意值

以下为一段最基础的switch-case语句实例,列举两种主要使用方式:

package main

import "fmt"

type person struct {
	age    int
	gender string
}

func main() {
	var Jack person
	Jack.age = 30
	Jack.gender = "Male"

	//switch-case 1
	switch Jack.age {
	case 10:
		fmt.Println("Jack is 10 years old")
	case 20:
		fmt.Println("Jack is 20 years old")
	case 30:
		fmt.Println("Jack is 30 years old")
	case 40:
		fmt.Println("Jack is 40 years old")
	default:
		fmt.Println("Jack's age is unknown")
	}

	//switch-case 2
	switch {
	default:
		fmt.Println("what the hell is Jack")
	case Jack.gender == "Male":
		fmt.Println("Jack is male")
	case Jack.gender == "Female":
		fmt.Println("Jack is female")
	}
}

运行结果如下: image.png

可以看到case后既可以跟常量,也可以跟表达式。第二个switch-case中default虽然位置在第一个,但是仍然能找到合适的匹配项,说明default语句的位置对程序运行结果没有影响。

下面介绍几种特殊的switch-case语句:

Type Switch用于判断interface变量实际存储的数据类型,使用方法如下例:

package main

import "fmt"

func main() {
	var s interface{}
	switch s.(type) {
	case int:
		fmt.Println("type : int")
	case string:
		fmt.Println("type : string")
	case nil:
		fmt.Println("type : nil")
	}
}

运行结果如下: image.png

fallthrough语句会强制执行后一个case(即在该case中取消默认的break操作),使用方法如下例(可以和上面的示例代码相对照):

package main

import "fmt"

type person struct {
	age    int
	gender string
}

func main() {
	var Jack person
	Jack.age = 30
	Jack.gender = "Male"

	//switch-case 1
	switch Jack.age {
	case 10:
		fmt.Println("Jack is 10 years old")
		fallthrough
	case 20:
		fmt.Println("Jack is 20 years old")
		fallthrough
	case 30:
		fmt.Println("Jack is 30 years old")
		fallthrough
	case 40:
		fmt.Println("Jack is 40 years old")
		fallthrough
	default:
		fmt.Println("Jack's age is unknown")
	}

	//switch-case 2
	switch {
	default:
		fmt.Println("what the hell is Jack")
		fallthrough
	case Jack.gender == "Male":
		fmt.Println("Jack is male")
		fallthrough
	case Jack.gender == "Female":
		fmt.Println("Jack is female")
	}
}

运行结果如下,自行对照case执行顺序: image.png

select-case

select-case和switch-case相似,但是主要用于通道操作,选用合适的通道,标准语法如下:

select {  
  case <- channel1:  
    ...  
  case value := <- channel2:  
    ...  
  case channel3 <- value:  
    ...
    ...
  default:  
    // 所有通道都没有准备好
    ...
}

关于通道channel可以参考本人另一篇文章《Go语言进阶(一)——并发编程》:Go语言进阶(一) 并发编程 - 掘金 (juejin.cn) --Author : Henry_Tjcs

该部分可以仅作了解(因为我也不会),并发编程在实际工程开发中使用较多,但对于初学者(比如我)并不友好。

循环

相比于C语言中多种循环(for/while...),Go语言中仅有for循环,但有较多的使用扩展。

基本for循环

基本for循环的标准语法有三种,可以分别和C语言中对应:

  1. for init; condition; post { }对应C语言标准for()循环,只不过没有括号
  2. for condition { }对应C语言中标准while()循环,同样去掉括号
  3. for { }对应C语言中死循环,即while(true)

参照以下示例代码,介绍了三种具体使用方式:

package main

import "fmt"

func main() {
	// for usage 1
	var num int
	for num = 1; num < 10; num++ {
		fmt.Printf("test1: num = %d\n", num)
	}
	//for usage 2
	for num >= 0 {
		fmt.Printf("test2: num = %d\n", num)
		num--
	}
	//for usage 3
	for {
		fmt.Printf("test3: num = %d\n", num)
		num++
		if num == 5 {
			break
		}
	}
}

运行结果如下: image.png

for-range格式

for-range可以实现的是对一个数据组的迭代,如slice/map/数组/字符串,标准语法如下:

for key, value := range MapName {     //同时用两个变量key和value存储键值和实际值
    newMap[key] = value
}

可以省略key和value中的一个,使用下划线_代替,如:

for _, value := range MapName
//或
for key,_ := range MapName

以下示例代码实现的是将字符串的每个字符分解并输出:

package main

import "fmt"

func main() {
	str := "Dongji University"   //东急大学是我的母校,用以下循环将其分解
	for _, value := range str {
		fmt.Printf("%s ", string(value))
	}
}

运行结果如下: image.png

for嵌套

和C语言中一样,Go语言中的for循环也可以嵌套。 以9*9乘法表为例:

package main 

import "fmt"

func main() {
    for m := 1; m < 10; m++ {
        for n := 1; n <= m; n++ {
            fmt.Printf("%dx%d=%d ",n,m,m*n)
        }
        fmt.Println("")
    }
}

运行结果如下: image.png

循环控制

Go语言中的循环控制语句主要有break/continue,使用方法和C语言完全相同,在此不作赘述。若不清楚可参考:

本篇主要涉及Go语言数据类型中的条件语句和循环语句,也将是基础篇的倒数第二篇,最后一篇将介绍函数。自此掌握Go语言最基础的语法规则,可自行实现Go语言年历打印程序。后续将继续跟进Go语言进阶篇。