golang学习笔记(流程控制)

if-else

语句模型

if 条件 1 {
分支 1
} else if 条件 2 {
分支 2
} else if 条件 … {
分支 …
} else {
分支 else
}

单分支

age := 20
    gender := "male"
    if (age > 18 && gender == "male") {
        fmt.Println("是成年男性")
    }

多分支

age := 20
    if age > 18 {
        fmt.Println("已经成年了")
    } else if age >12 {
        fmt.Println("已经是青少年了")
    } else {
        fmt.Println("还不是青少年")
    }

高级写法

if age >=18;sex == "男"{
	fmt.Println("成年人就该做成年人应该的事情")
}

switch-case

语句模型

switch 表达式 {
case 表达式1:
代码块
case 表达式2:
代码块
case 表达式3:
代码块
case 表达式4:
代码块
case 表达式5:
代码块
default:
代码块
}

1、简单示例

func main() {
    education := "本科"

    switch education {
    case "博士":
        fmt.Println("我是博士")
    case "研究生":
        fmt.Println("我是研究生")
    case "本科":
        fmt.Println("我是本科生")
    case "大专":
        fmt.Println("我是大专生")
    case "高中":
        fmt.Println("我是高中生")
    default:
        fmt.Println("学历未达标..")
    }
}

2、一个case多个条件

import "fmt"

func main() {
    month := 2

    switch month {
    case 3, 4, 5:
        fmt.Println("春天")
    case 6, 7, 8:
        fmt.Println("夏天")
    case 9, 10, 11:
        fmt.Println("秋天")
    case 12, 1, 2:
        fmt.Println("冬天")
    default:
        fmt.Println("输入有误...")
    }
}

3、case条件常量不能重复
4、switch后可接函数

import "fmt"

// 判断一个同学是否有挂科记录的函数
// 返回值是布尔类型
func getResult(args ...int) bool {
    for _, i := range args {
        if i < 60 {
            return false
        }
    }
    return true
}

func main() {
    chinese := 80
    english := 50
    math := 100

    switch getResult(chinese, english, math) {
    // case 后也必须 是布尔类型
    case true:
        fmt.Println("该同学所有成绩都合格")
    case false:
        fmt.Println("该同学有挂科记录")
    }
}

5、可不接表达式,当作if-else使用

score := 30

switch {
    case score >= 95 && score <= 100:
        fmt.Println("优秀")
    case score >= 80:
        fmt.Println("良好")
    case score >= 60:
        fmt.Println("合格")
    case score >= 0:
        fmt.Println("不合格")
    default:
        fmt.Println("输入有误...")
}

6、swithc穿透能力

s := "hello"
switch {
case s == "hello":
    fmt.Println("hello")
    fallthrough
case s != "world":
    fmt.Println("world")
}

fallthrough 只能穿透一层,意思是它让你直接执行下一个case的语句,而且不需要判断条件。

for循环

for循环的基本模型

for [condition | ( init; condition; increment ) | Range]
{
statement(s);
}

for后面可以接4种类型的表达式
1、接一个条件表达式

a := 1
for a <= 5{
	fmt.Println(a)
	a++
}

2、接三个条件表达式

for i := 0; i <= 5; i++{
	fmt.Println(i)
}

3、接一个range表达式

myarr := [...]string{"hello","world","!"}
for _, item := range myarr{
	fmt.Printf("heool,%s\n",item)
}

4、不接表达式(无限循环)

var i int = 1
    for {
        if i > 5 {
            break
        }
        fmt.Printf("hello, %d\n", i)
        i++
    }

goto无条件跳转

基本模型

goto 标签;


标签: 表达式;

1、最简单示例

import "fmt"

func main(){
	goto flag
	fmt.Println("B")
flag:
	fmt.Println("A")
}
输出
A

如何是用?
通常是与条件语句配合使用,可以用来实现条件转移,构成循环,跳出循环体的功能

func main(){
	i :=1
flag:
	if i == 5{
		fmt.Println(i)
		i++
		goto flag
	}
}
func main(){
	i := 1
	for {
		if i >=5{
			goto flag
		}
		fmt.Println(i)
		i++
	}
flag:
}

goto语句与标签之间不能有变量声明,否则编译错误

defer延迟语句

先进后出原则

import "fmt"

func main() {
    name := "go"
    defer fmt.Println(name) // 输出: go

    name = "python"
    defer fmt.Println(name) // 输出: python

    name = "java"
    fmt.Println(name)
}
输出
java
python
go

defer 和 return 谁先执行

import "fmt"

var name string = "go"

func myfunc() string {
    defer func() {
        name = "python"
    }()

    fmt.Printf("myfunc 函数里的name:%s\n", name)
    return name
}

func main() {
    myname := myfunc()
    fmt.Printf("main 函数里的name: %s\n", name)
    fmt.Println("main 函数里的myname: ", myname)
}
输出
myfunc 函数里的name:go
main 函数里的name: python
main 函数里的myname:  go

defer 是return 后才调用的。所以在执行 defer 前,myname 已经被赋值成 go 了。

select

仅能用做信道/通道的相关操作

select {
case 表达式1:
case 表达式2:
default:
}

package main

import (
    "fmt"
)

func main() {
    c1 := make(chan string, 1)
    c2 := make(chan string, 1)

    c2 <- "hello"

    select {
    case msg1 := <-c1:
      fmt.Println("c1 received: ", msg1)
    case msg2 := <-c2:
      fmt.Println("c2 received: ", msg2)
    default:
      fmt.Println("No data received.")
    }
}
在运行 select 时,会遍历所有(如果有机会的话)的 case 表达式,只要有一个信道有接收到数据,那么 select 就结束,所以输出如下

c2 received:  hello

避免造成死锁,select在执行过程中,必须命中其中的某一分支,如果在遍历完所有的case后,若没有命中,就会进入default里面的代码分支,但如果你没有哦写default分支,select就会阻塞,直到某个case可以命中,而如果一直没有命中,select就会抛出deadlock的错误

随机性,多个信道接收到数据,多个case命中,会随机一个分支执行

select的超时,当case里面的信道始终没有接收到数据时,而且也没有default语句时,select整体就会阻塞,我们可以手动设置一个超时时间避免阻塞

package main
import(
	"fmt"
	"time"
)

func main(){
	c1 := make(chan string,1)
	c2 := make(chan string,1)
	timeout := make(chan bool,1)
	go makeTimeout(timeout,2)
	select{
		case msg1 := <=c1:
			fmt.Println("c1 received:",msg1)
		case msg2 := <-c2:
			fmt.Println("c2 received:",msg2)
		case <-timeout:
			fmt.Println("Timeout,exit.")
	}
}

读取/写入都可以
select 里的 case 表达式只要求你是对信道的操作即可,不管你是往信道写入数据,还是从信道读出数据。

package main

import (
    "fmt"
)

func main() {
    c1 := make(chan int, 2)

    c1 <- 2
    select {
    case c1 <- 4:
        fmt.Println("c1 received: ", <-c1)
        fmt.Println("c1 received: ", <-c1)
    default:
        fmt.Println("channel blocking")
    }
}
输出
c1 received:  2
c1 received:  4

信道关闭也可命中

package main

import "fmt"

func main()  {
    c1 := make(chan int, 1)
    c2 := make(chan int, 1)
    close(c1)
    for {
        select {
        case <-c1:
            fmt.Println("stop");
                        return
        case <-c2:
            fmt.Println("hhh")

        }
    }
}
$ go run main.go
stop

总结

  1. select 只能用于 channel 的操作(写入/读出/关闭),而 switch 则更通用一些;
  2. select 的 case 是随机的,而 switch 里的 case 是顺序执行;
  3. select 要注意避免出现死锁,同时也可以自行实现超时机制;
  4. select 里没有类似 switch 里的 fallthrough 的用法;
  5. select 不能像 switch 一样接函数或其他表达式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值