字谜代码,协程线程 并发

105 阅读4分钟

字谜

制作猜谜游戏,生成一个随机数,玩家通过猜数字可以知道关于其随机数的大小,当输入这个数字的时候程序结束

首先我们要得到一个随机数,这个时候我们就用到math/rand这个包,把他填入 import里面

然后生成一个随机数

起初我们要知道是从0到多少的随机数,就比如100

所以就要设立一个变量

maxNum := 100

然后就用包里的Intn函数来生成一个随机数

secretNumber := rand.Intn(maxNum)

这样就得到了随机数字

但是发现这个数字在运行的时候总是不变的

因为使用他之前需要设置随机数种子,否则每一次调用都是一个相同的随机数,我们惯用的是启动的时间戳来初始话随机数种子

rand.Seed(time.Now().UnixNano())

这样就得到一个随机数

maxNum := 100 rand.Seed(time.Now().UnixNano()) secretNumber := rand.Intn(maxNum) fmt.Println("The secret number is ", secretNumber)

读取用户输入

import ( "bufio" "fmt" "math/rand" "os" "strconv" "strings" "time" )

fmt.Println("Please input your guess") reader := bufio.NewReader(os.Stdin) //直接操作很不方便 //所以用bufio来转化成只读的流 input, err := reader.ReadString('\n') //我们可以用ReadString里面去读取一行 if err != nil { fmt.Println("An error occured while reading input. Please try again", err) return } input = strings.Trim(input, "\r\n") //读取一行之后我们,我们会发现最后一个的字符是'\n'所以我们要删除他 guess, err := strconv.Atoi(input) //把input字符转化成10机制的数字 if err != nil { fmt.Println("Invalid input. Please enter an integer value") return } fmt.Println("You guess is", guess) }

但是这样输入的话无论数据对还是不对都会结束循环所以我们就加入for死循环,如果是error或者是猜错了都是continue,只有猜到正确的数字之后才会退出break

完整代码

package main import ( "bufio" "fmt" "math/rand" "os" "strconv" "strings" "time" ) func main() { maxNum := 100 rand.Seed(time.Now().UnixNano()) secretNumber := rand.Intn(maxNum) // fmt.Println("The secret number is ", secretNumber) fmt.Println("Please input your guess") reader := bufio.NewReader(os.Stdin) for { input, err := reader.ReadString('\n') if err != nil { fmt.Println("An error occured while reading input. Please try again", err) continue } input = strings.Trim(input, "\r\n") guess, err := strconv.Atoi(input) if err != nil { fmt.Println("Invalid input. Please enter an integer value") continue } fmt.Println("You guess is", guess) if guess > secretNumber { fmt.Println("Your guess is bigger than the secret number. Please try again") } else if guess < secretNumber { fmt.Println("Your guess is smaller than the secret number. Please try again") } else { fmt.Println("Correct, you Legend!") break } } }

第三节

并发和并行

并发和并行

并发和并行是两个相关但不同的概念:

并发:指的是多个任务在同一时间段内交替执行,通常是在单个CPU核心上。并发任务之间可能会有交错执行的情况,但并不一定同时进行。多线程程序在一个核的cpu上运行

并行:指的是多个任务在同一时刻同时执行,通常是在多个CPU核心上。并行任务之间是真正的同时进行。多线程程序在多个核的cpu上运行

go可以充分发挥多核优势,高运行

协程和线程

线程:是操作系统提供的轻量级执行单元,属于内核态。线程的创建、切换和停止都是相对较重的操作,消耗的资源较多。他的创建切换和停止都属于很重的操作,属于MB量级

协程:是用户态的轻量级线程,由程序员控制。协程的创建、切换和停止都非常轻量,消耗的资源较少。Go语言中的协程(goroutine)就是一种协程的实现,非常适合高并发的场景。他可以在go语言中直接运行,属于KB量级

这也是go语言更适合高并发场景的原因所在

开启一个协程

我们在实际的开发过程中如何开启一个协程

go语言开启一个协程是非常简单的,我们只需要在函数前面加一个go语言的关键字,这就为一个函数创建一个协程来运行

func hello(i int){

println("hello goroutine : " + fmt.Sprint(i))

}

func H(){

for i:=0 ; i < 5;i++{

go func ( j int){

hello(j)

}(i)

}

time.Sleep(time.Second)

//保证子协程未进行完之前,主协程不退出

//后续有更优雅的方式

}

输出结果可能是

hello goroutine : 4

hello goroutine : 1

hello goroutine : 0

hello goroutine : 2

hello goroutine : 3

可以看到是乱序输出的,通过并行来打印的输出

在Go语言中,开启一个协程非常简单。只需要在函数调用前加上go关键字即可。例如:

go

func hello(i int) {

    println("hello 

    goroutine : " + 

    fmt.Sprint(i))

}

func main() {

    for i := 0; i < 

    5; i++ {

        go hello(i)

    }

    time.Sleep(time.

    Second) // 确保主协

    程等待子协程执行完毕

}