Go语言学习之路-5-Go语言基础用户输入&流程控制

获取用户输入

有时候程序需要根据用户的选择来执行不同的代码逻辑,这个时候就需要获取用户的输入了

  • fmt.Scan
  • fmt.Scanln
  • fmt.Scanf

fmt.Scan

例子

import "fmt"

func main() {
	fmt.Print("请输入用户名和年龄通过空格区别:")
	var user string
	var age int8
	// &符可以获取变量的内存地址
	// 通过fmt.Scan方法可以把用户输入的内容,写入到这个内存地址
	// 默认通过空格区分
	count, err := fmt.Scan(&user, &age)

	fmt.Println(count, err, user, age)
	fmt.Printf("输入的个数:%d, 错误:%s, 用户输入user值:%s, 用户输入的age值:%d\n", count, err, user, age)
}

注意事项

上面的情况fmt.Scan需要捕获两个值,但是如果我们输入完一个值后一直敲回车是获取不到第二个值得

go run main.go
请输入用户名和年龄通过空格区别:eson



# 上面的空白是我一直在敲回车
1
# 输出结果
2 <nil> eson 1
输入的个数:2, 错误:%!s(<nil>), 用户输入user值:eson, 用户输入的age值:1

fmt.Scanln

例子

package main

import "fmt"

func main() {
	fmt.Print("请输入用户名和年龄通过空格区别:")
	var user string
	var age int8
	// &符可以获取变量的内存地址
	// 通过fmt.Scan方法可以把用户输入的内容,写入到这个内存地址
	// 这个和Scan的区别在于它的终止是通过换行符的当用户输入换行符后就会终止用户输入
	// 同样是空格分隔
	count, err := fmt.Scanln(&user, &age)

	fmt.Println(count, err, user, age)
	fmt.Printf("输入的个数:%d, 错误:%s, 用户输入user值:%s, 用户输入的age值:%d\n", count, err, user, age)
}

fmt.Scanf

例子

package main

import "fmt"

func main() {
	fmt.Print("请输入用户名和年龄通过空格区别:")
	var user string
	// var age int8
	// &符可以获取变量的内存地址
	// 通过fmt.Scanf方法可以把用户输入的内容
	// 和上面的两个区别: 可以通过特定格式获取变量
	// 比如这里面用户输入:我叫X
	// 就可以从用户输入的内容获取X的值
	count, err := fmt.Scanf("我叫%s", &user)

	fmt.Println(count, err, user)
	fmt.Printf("输入的个数:%d, 错误:%s, 用户输入user值:%s\n", count, err, user)
}

注意事项

虽然是可以通过特定的格式获取,但是如果占位符后面没有区分会有错误处理,后续的话或许可以优化

package main

import "fmt"

func main() {
	fmt.Print("请输入用户名和年龄通过空格区别:")
	var user string
	// 如果提取占位符后面没有空格,go这里就不好判断
	// 如果我输入我叫eson属小猪的,本意是想获取eson这个值
	// 结果变成了:eson属小猪的
	// 加个空格就能解决这个问题
	count, err := fmt.Scanf("我叫%s属小猪的", &user)

	fmt.Println(count, err, user)
	fmt.Printf("输入的个数:%d, 错误:%s, 用户输入user值:%s\n", count, err, user)
}

读取一行数据

上面的情况默认都是空格但是如果想获取一行输入怎么搞

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	fmt.Print("请输入一行数据:")

	reader := bufio.NewReader(os.Stdin)
	// line从stdin中读取一行数据(一个换行符是1行)它是一个字节的集合
	// 我们输入的内容都会放在一个缓冲区里面直到我们输入回车
	// 如果我们一次性输入的内如果过多超过了这个缓冲区
	// 那么isPrefix将会设置为True
	// 意思是可以循环读取它暂时用不到先忽略
	line, isPrefix, err := reader.ReadLine()
	// 我们在把字节转换成字符串
	data := string(line)
	fmt.Printf("用户输入的一行数据:%s, 是否读取完了:%t, 错误:%v\n", data, isPrefix, err)
}

流程控制

  • 一门语言的流程控制主要的作用做判断,类似我们平时的,如果...那么...否则....的概念
  • 用它来解决需要判断的场景

流程控制有:iffor,switch语句是编写一系列if-else语句的较短方法、后面函数会有一个goto它解决的问题是

if else(如果那么)

if else语法

if 表达式1 {
    如果表达式1,成立执行的代码
} else if 表达式2 {
    如果表达式2,成立执行的代码
} else{
    上面的表达式都不成立执行的代码
}

if else例子

  • if逻辑从上至下运行,如果上面的匹配了就不往下走了
  • if 或者else if必须和表达式和{ 在同一行 else 也得和{在同一行

例子:

package main

import "fmt"

func main() {
	var name string
	fmt.Print("请输入您的用户:")
	fmt.Scanln(&name)

	if name == "admin" {
		fmt.Println("欢迎您:管理员")
	} else if name == "eson" {
		fmt.Println("欢迎你:豆豆")
	} else {
		fmt.Printf("欢迎您:%s\n", name)
	}
}

switch case

我们使用上面的if else,如果需要判断的太多了怎么办?有没有精简点的?

package main

import "fmt"

func main() {
	var name string
	fmt.Print("请输入您的用户:")
	fmt.Scanln(&name)

	if name == "admin" {
		fmt.Println("欢迎您:管理员")
	} else if name == "eson" {
		fmt.Println("欢迎你:豆豆")
	} else if name == "alex" {
		fmt.Println("欢迎你:alex")
	}else {
		fmt.Printf("欢迎您:%s\n", name)
	}
}

可以通过switch case来搞定,看着就比较舒服了

package main

import "fmt"

func main() {
	var name string
	fmt.Print("请输入您的用户:")
	fmt.Scanln(&name)

	switch name {
	case "admin":
		fmt.Println("欢迎您:admin")
	case "eson":
		fmt.Println("欢迎您:eson")
	case "alex":
		fmt.Println("欢迎您:alex")
	default:
		fmt.Printf("欢迎您:%s\n", name)
	}
}

当然也可以在分支进行判断

package main

import "fmt"

func main() {
	var age int
	fmt.Print("请输入您的年龄:")
	fmt.Scanln(&age)

	switch {
	case age > 60:
		fmt.Println("老年人")
	case age > 30:
		fmt.Println("中年人")
	case age > 18:
		fmt.Println("成年人")
	default:
		fmt.Println("未成年人")
	}
}

注意事项

  • switch只能有一个default

for 循环

在Go语言中可以通过for来解决所有需要,重复循环的逻辑

for循环语句格式

for 初始语句;条件表达式;结束语句{
    循环体语句
}
  • 如果for循环表达式结果一直为true那么将一直运行,直到条件表达式返回false时才自动退出循环

无限循环

package main

import (
	"fmt"
	"time"
)

func main() {
	for {
		fmt.Println(time.Now())
		time.Sleep(time.Second * 1)
	}
}

非无限循环

package main

import (
	"fmt"
	"time"
)

func main() {
	// i初始值为0 ; 当i小于等于0时结束; 每次循环i自动+1
	for i := 0; i <= 10; i++ {
		fmt.Println(time.Now())
		time.Sleep(time.Second * 1)
	}
}

continue停止运行continue后面的逻辑,开始继续循环

package main

import (
	"fmt"
	"time"
)

func main() {
	// i初始值为0 ; 当i小于等于0时结束; 每次循环i自动+1
	for i := 0; i <= 10; i++ {
		fmt.Println(time.Now())
		time.Sleep(time.Second * 1)

		// 当i大于等于6 且 小于等于8的时候后面的逻辑就不执行了,继续循环
		if i >= 6 && i <= 8 {
			continue
		}

		fmt.Printf("当前时间是第%d执行\n", i)
	}
}

// 效果就是: 6~8不会输出当前是第几次执行

break停止for循环

package main

import (
	"fmt"
	"time"
)

func main() {
	// i初始值为0 ; 当i小于等于0时结束; 每次循环i自动+1
	for i := 0; i <= 10; i++ {
		fmt.Println(time.Now())
		time.Sleep(time.Second * 1)

		// 当i大于等于5的时候,整个for循环就直接退出了
		if i >= 5{
			break
		}

		fmt.Printf("当前时间是第%d执行\n", i)
	}
}

goto通过标签进行代码间的无条件跳转

看下面的场景,再去嵌套循环的场景需要break两次才能退出

package main

import "fmt"

func main() {
	breakFlag := false

	for i := 0; i <= 10; i++ {
		for j := 0; j <= 10; j++ {
			if j == 3 {
				breakFlag = true // 内层循环设置breakFlag为true
				break
			}
			fmt.Printf("%v-%v\n", i, j)
		}
		// 放成循环监听这个breakFlag为True的时候退出外城循环
		if breakFlag {
			break
		}
	}
}

使用goto来解决

package main

import "fmt"

func main() {

	for i := 0; i <= 10; i++ {
		for j := 0; j <= 10; j++ {
			if j == 3 {
				goto breakFlag // 内层循环直接调到指定的flag

			}
			fmt.Printf("%v-%v\n", i, j)
		}
	}
breakFlag:
	fmt.Println("got直接跳到这里退出逻辑")

}

输出结果:
0-0
0-1
0-2
got直接跳到这里退出逻辑

posted @ 2020-12-26 21:39  天帅  阅读(225)  评论(0编辑  收藏  举报