Go 语言 在线

2185go-if-statement

Go 的 if 还有一个强大的地方就是条件判断语句里面允许声明一个变量,这个变量的作用域只能在该条件逻辑块内,其他地方就不起作用了,如下所示:

package main
  
import "fmt"
func main() {
    if num := 9; num < 0 {
        fmt.Println(num, "is negative")
    } else if num < 10 {
        fmt.Println(num, "has 1 digit")
    } else {
        fmt.Println(num, "has multiple digits")
    }
}

运行结果:

9 has 1 digit

2184go-if-statement

用 If 语句判断偶数:

package main

import "fmt"

func main() {
    var s int ;    // 声明变量 s 是需要判断的数
    fmt.Println("输入一个数字:")
    fmt.Scan(&s)

    if s%2 == 0  { //     取 s 处以 2 的余数是否等于 0
        fmt.Print("s 是偶数\n") ;//如果成立
    }else {
        fmt.Print("s 不是偶数\n") ;//否则
    }
    fmt.Print("s 的值是:",s) ;
}

2183Go 并发

形象说明一下无缓冲和有缓冲的区别:

无缓冲是同步的,例如 make(chan int),就是一个送信人去你家门口送信,你不在家他不走,你一定要接下信,他才会走,无缓冲保证信能到你手上。

有缓冲是异步的,例如 make(chan int, 1),就是一个送信人去你家仍到你家的信箱,转身就走,除非你的信箱满了,他必须等信箱空下来,有缓冲的保证信能进你家的邮箱。

修改一下上面笔记中的程序如下:

package main
import (
    "fmt"
    "time"
)

func sum(s []int, c chan int) {
    sum := 0
    for _, v := range s {
        sum += v
    }
    fmt.Printf("sum:")
    fmt.Printf("%#v\n", sum)
    c <- sum // 把 sum 发送到通道 c
    fmt.Println("after channel pro")
}

// 通道不带缓冲,表示是同步的,只能向通道 c 发送一个数据,只要这个数据没被接收然后所有的发送就被阻塞
func main() {
    s := []int{7, 2, 8, -9, 4, 0}
    c := make(chan int)
    fmt.Println("go [0,3]")
    go sum(s[:len(s)/2], c) //a

    //这里开启一个新的运行期线程,这个是需要时间的,本程序继续往下走

    fmt.Println("go [3,6]")
    go sum(s[len(s)/2:], c) //b
    fmt.Println("go2 [0,3]")
    go sum(s[:len(s)/2], c) //c
    fmt.Println("go2 [3,6]")
    go sum(s[len(s)/2:], c) //d

    /*
    a b c d和main一起争夺cpu的,他们的执行顺序完全无序,甚至里面不同的语句都相互穿插
    但无缓冲的等待是同步的,所以接下来a b c d都会执行,一直执行到c <- sum后,开始同步阻塞
    因此after channel pro是打印不出来的, 等要打印after channel pro的时候,main就结束了
    */

    fmt.Println("go3 start waiting...")
    time.Sleep(1000 * time.Millisecond)
    fmt.Println("go3 waited 1000 ms")

    //因为a b c d都在管道门口等着,这里度一个,a b c d就继续一个,这个结果的顺序可能是acbd
    aa := <-c
    bb := <-c
    fmt.Println(aa)
    fmt.Println(bb)
    x, y := <-c, <-c
    fmt.Println(x, y, x+y)
}

结果:

go [0,3]
go [3,6]
go2 [0,3]
go2 [3,6]
sum:sum:sum:17
go3 start waiting...
17
-5
sum:-5
go3 waited 1000 ms
17
17
-5 -5 -10

修改成 make(chan int, 2),同时合并:

fmt.Printf("sum:")
fmt.Printf("%#v\n", sum) 

为:

fmt.Printf("sum:%#v\n", sum)

可以看到 after channel pro 没有被阻塞了。

结果:

go [0,3]
go [3,6]
go2 [0,3]
go2 [3,6]
go3 start waiting...
sum:-5
sum:17
after channel pro
after channel pro
sum:17
sum:-5
go3 waited 1000 ms
-5
17
17 -5 12

2182Go 并发

Channel 是可以控制读写权限的 具体如下:

go func(c chan int) { //读写均可的channel c } (a)
go func(c <- chan int) { //只读的Channel } (a)
go func(c chan <- int) {  //只写的Channel } (a)

2181Go 并发

关闭通道并不会丢失里面的数据,只是让读取通道数据的时候不会读完之后一直阻塞等待新数据写入