Go语言格式化输入输出

1.格式化输入

1.从终端获取用户输入

1.fmt.Scanf(format string, a ...interface{}):格式化输入,空格作为分隔符,占位符(%s %d %f)和格式化输出一致
  • 1.单行读入
package main

import "fmt"

func main()  {
    var a int
    var b string
    var c float64
    fmt.Scanf("%d%s%f", &a, &b, &c)
    fmt.Printf("a=%d b=%s c=%.2f\n", a, b, c)
}
10 hello  9.8345
a=10 b=hello c=9.83

Process finished with exit code 0
  • 2.多行读入
package main

import "fmt"

func main()  {
    var a int
    var b string
    var c float64
    /*
    // 在命令行输入时会有问题(goland編輯器没问题)
    fmt.Scanf("%d", &a)  // 当输入1后需要回车才能输入下一个值,但是Scanf是以回车作为结束符,所以最终只能接收到第一个输入的值
    fmt.Scanf("%s", &b)
    fmt.Scanf("%f", &c)

    1
    hello
    a=1 b= c=0.00
    */
    
    // 手动处理\n换行,告知编译器将\n作为输入的结束
    fmt.Scanf("%d\n", &a)  // 或者 fmt.Scanf("%d\r", &a)
    fmt.Scanf("%s\n", &b)
    fmt.Scanf("%f\n", &c)
    /*
    1
    hello
    3.45
    a=1 b=hello c=3.45
    */    
    fmt.Printf("a=%d b=%s c=%.2f\n", a, b, c)
}
  • 3.固定文本输入
package main

import "fmt"

func main()  {
    var a int
    var b string
    var c float64
    /*
    测试发现有标点符号就会出现异常,找不到第三个值,不知道什么原因
    count, err := fmt.Scanf("我今年%d岁了,我的名字是%s,我考了%f分", &a, &b, &c)
    
    我今年22岁了,我的名字是sfd,我考了98.4分
    input does not match format
    a=22 b=sfd,我考了98.4分 c=0.00

    */
    count, err := fmt.Scanf("我今年%d岁了 我的名字是%s 我考了%f分", &a, &b, &c)
    if err != nil {
	fmt.Println(err)
    } else {
	fmt.Println(count)
    }
    fmt.Printf("a=%d b=%s c=%.2f\n", a, b, c)
}

/*
没有按照固定格式文本输入(失败)
22 lucy 87.9
input does not match format
a=0 b= c=0.00

按照固定文本输入(成功)
我今年22岁了 我的名字是lucy 我考了89.9分
3
a=22 b=lucy c=89.90

修改文本部分信息(失败)
我今年22岁了 我的名字是lucy 我这次考了89.9分
input does not match format
a=22 b=lucy c=0.00
*/
  • 4.注意:Scanf没有办法读取一行数据,如果数据中有空格的话,Scanf默认将空格作为分隔符,可以使用bufio实现
2.fmt.Scan(a ...interface{}):从终端获取用户输入,存储在Scan中的参数里,空格和换行符作为分隔符。两个返回值:count:用户输入了几个值,err: 用户输入错误,提示错误信息
  • 1.单行读入
func main()  {
    var a int
    var b string
    var c float64
    fmt.Scan(&a, &b, &c)
    fmt.Printf("a=%d b=%s c=%.2f\n", a, b, c)
}
/*
一行输入
1 hello 3.45
a=1 b=hello c=3.45

换行输入
1
a
3.45
a=1 b=a c=3.45
*/
  • 2.多行读入
package main

import "fmt"

func main()  {
    var a int
    var b string
    var c float64
    fmt.Scan(&a)
    fmt.Scan(&b)
    fmt.Scan(&c)
    fmt.Printf("a=%d b=%s c=%.2f\n", a, b, c)
}

/*
1
hello
3.4
a=1 b=hello c=3.40
*/
  • 3.提示:要求如果要输入两个值,必须输入两个,如果是三个值,就必须是三个。否则会一直等待,不会执行下面的程序
3.fmt.Scanln(a ...interface{}):从终端获取用户输入,存储在Scanln中的参数里,空格作为分隔符,遇到换行符结束
  • 1.单行读入
func main()  {
    var a int
    var b string
    var c float64
    fmt.Scan(&a, &b, &c)
    fmt.Printf("a=%d b=%s c=%.2f\n", a, b, c)
}
/*
只能一行输入
1 hello 3.45
a=1 b=hello c=3.45
*/
  • 2.多行读入
package main

import "fmt"

func main()  {
    var a int
    var b string
    var c float64
    fmt.Scan(&a)
    fmt.Scan(&b)
    fmt.Scan(&c)
    fmt.Printf("a=%d b=%s c=%.2f\n", a, b, c)
}

/*
1
hello
3.4
a=1 b=hello c=3.40
*/
  • 3.单行输入只要回车就结束,多行输入回车就跳过,使用零值,如果输入值和接收值不匹配,缺少的会以接收值类型的零值填充,多余的忽略。
4.区别
  • fmt.Scanf如果有固定格式,就必须遵守,换行被作为结束符,如果输入不够直接换行,未输入的值就使用接收类型的零值

  • fmt.Scan 要求 如果要输入两个值,必须输入两个,如果是三个值,就必须是三个。否则他会一直等待,不会执行下面的程序。

  • fmt.Scanln 没有这个强制的要求,如果要求我们输入两个值,但是我们只输入一个值,我们回车之后就阔以直接执行程序,但是会报错,我们可以判断返回值err,会报错值为输入。这就是他们两个的不同。

  • Scan必须等待所要求的值输入完成才能执行程序,但是Scanln不管输入的数据是否完成,只要回车就直接执行。

2.从字符串中获取输入

1.fmt.Sscanf(str, format string, a ...interface{}):格式化输入,空格作为分隔符,占位符和格式化输出一致
package main

import "fmt"

func main()  {
    var a int
    var b string
    var c float64
    str := "88hello 8.8"
    fmt.Sscanf(str, "%d%s%f", &a, &b, &c)
    fmt.Printf("a=%d b=%s c=%.2f\n", a, b, c)  // a=88 b=hello c=8.80
}
2.fmt.Sscan(str strinf, a ...interface{}):从终端获取用户输入,存储在Scnaln中的参数里,空格和换行符作为分隔符
package main

import "fmt"

func main()  {
    var a int
    var b string
    var c float64
    str := "88hello\n8.8"
    fmt.Sscan(str, &a, &b, &c)
    fmt.Printf("a=%d b=%s c=%.2f\n", a, b, c)  // a=88 b=hello c=8.80
}
3.fmt.Sscanln(str strinf, a ...interface{}):从终端获取用户输入,存储在Scnaln中的参数里,空格作为分隔符,遇到换行符\n结束
// ln:line
package main

import "fmt"

func main()  {
    var a int
    var b string
    var c float64
  
    /*
    str := "88hello8.8"
    fmt.Sscanln(str, &a, &b, &c)
    fmt.Printf("a=%d b=%s c=%.2f\n", a, b, c)  // a=88 b=hello8.8 c=0.00
    */

    /*
    str := "88hello\n8.8"
    fmt.Sscanln(str, &a, &b, &c)
    fmt.Printf("a=%d b=%s c=%.2f\n", a, b, c)  // a=88 b=hello c=0.00
    */

    str := "88hello 8.8"
    fmt.Sscanln(str, &a, &b, &c)
    fmt.Printf("a=%d b=%s c=%.2f\n", a, b, c)  // a=88 b=hello c=8.80
}

2.格式化输出

1.输出到终端

1.fmt.Printf(format string, a ...interface{}):格式化输出到终端
2.fmt.Println(a ...interface{}):把零个或多个变量打印到终端,并换行
3.fmt.Print(a ...interface{}):把零个或多个变量打印到终端,不换行

2.输出到字符串(格式化后返回一个字符串)

1.fmt.Sprintf(format string, a ...interface{}):格式化并返回字符串
package main

import "fmt"

func main()  {
    const name, age, score = "Kim", 22, 89.7
    // Kim今年22岁了考试考了89.70分
    ret := fmt.Sprintf("%s今年%d岁了考试考了%.2f分", name, age, score)
    fmt.Println(ret)
}
2.fmt.Sprintln(a ...interface{}):把零个或多个变量按空格进行格式化并换行,返回字符串
package main

import "fmt"

func main()  {
    const name, age, score = "Kim", 22, 89.7
    ret := fmt.Sprintln(name, "今年", age, "岁", "这次考试得了", score, "分.")
    // 自动以空格进行分割
    fmt.Println(ret)  // Kim 今年 22 岁 这次考试得了 89.7 分.
}
3.fmt.Sprint(a ...interface{}):把零个或多个变量按空格进行格式化
package main

import (
    "fmt"
)

func main()  {
    const name, age, score = "Kim", 22, 89.7
    ret := fmt.Sprint(name, " 今年 ", age, " 岁 ", "这次考试得了 ", score, " 分.\n")
    fmt.Println(ret)  // Kim 今年 22 岁 这次考试得了 89.7 分.
}

3.终端输入输出背后的原理

1.终端其实是一个文件

  • os.Stdin:标准输入的文件实例,类型为*File
  • os.Stdout:标准输出的文件实例,类型为*File
  • os.Stderr:标准错误输出的文件实例,类型为*File

2.以文件的方式操做终端

1.终端读取
  • File.Read(b []byte)
package main

import (
    "fmt"
    "os"
)

func main()  {
    buf := [16]byte{}
    os.Stdin.Read(buf[:])
    fmt.Println(string(buf[:])) 
}
/*
this is a test
this is a test
*/
2.终端输出
  • File.Write[b []byte]
  • File.WriteSting(str string)
package main

import (
    "os"
)

func main()  {
    buf := [16]byte{}
    os.Stdin.Read(buf[:])
    os.Stdout.WriteString(string(buf[:]))
    // os.Stdout.Write(buf[:])
}
/* 
this is a test
this is a test
*/

4.从文件中获取输入输出

1.从文件中获取用户输入
  • 1.fmt.Fscanf(file, format string, a ...interface{}):从文件格式化输入,空格作为分隔符,占位符和格式化输出一致
package main

import (
    "fmt"
    "os"
)

func main()  {
    var a int
    var b string
    var c float64
    fmt.Fscanf(os.Stdin, "%d%s%f", &a, &b, &c)
    fmt.Println(a, b, c)
}

/*
10 a 29.2
10 a 29.2
*/
package main

import (
    "fmt"
    "os"
)

func main()  {
    var a int
    var b string
    var c float64
    // 测试一直获取不到第三个参数输入的值
    fmt.Fscanf(os.Stdin, "%d岁的%s考了%d分", &a, &b, &c)
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
}
/*
10 xiaohong 23.9
10

0

12岁的小宏考了67.5分
12
小宏考了67.5分
0

12岁的 小宏 考了67.5分
12
小宏
0

12岁的 小宏 考了 67.5 分
12
小宏
0
*/
  • 2.fmt.Fscan(file, a ...interface{}):从文件获取用户输入,存储在Scanln中的参数里,空格和换行符作为分隔符
package main

import (
	"fmt"
	"os"
)

func main()  {
    var a int
    var b string
    var c float64
    fmt.Fscan(os.Stdin, &a, &b, &c)
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
}
/*
22 小亮 76.4
22
小亮
76.4
*/
  • 3.fmt.Fsacnln(file, a ...interface{}):从文件获取用户输入,存储在Scanln中的参数里,空格作为分隔符,遇到换行符结束
2.格式化输出到文件中
  • 1.fmt.Fpcanf(file, format string, a ...interface{}):格式化输出,并写入到文件中
package main

import (
    "fmt"
    "os"
)

func main()  {
    var a int
    var b string
    var c float64
    fmt.Fscanln(os.Stdin, &a, &b, &c)
    fmt.Fprintf(os.Stdout, "%d岁的%s考了%.2f分", a, b, c)
}
/*
22 小亮 89.3
22岁的小亮考了89.30分
*/
  • 2.fmt.Fpcan(file, a ...interface{}):把零个或多个变量写入到文件中,并换行
package main

import (
    "fmt"
    "os"
)

func main()  {
    var a int
    var b string
    var c float64
    fmt.Fscanln(os.Stdin, &a, &b, &c)
    fmt.Fprint(os.Stdout, a, "岁的", b, "考了", c, "分")
}
/*
22 小亮 89
22岁的小亮考了89分
*/
  • 3.fmt.Fpacnln(file, a ...interface{}):把零个或多个变量写入到文件中
package main

import (
    "fmt"
    "os"
)

func main()  {
    var a int
    var b string
    var c float64
    fmt.Fscanln(os.Stdin, &a, &b, &c)
    fmt.Fprintln(os.Stdout, a)
    fmt.Fprintln(os.Stdout, b)
    fmt.Fprintln(os.Stdout, c)
}
/*
22 小亮 89.2
22
小亮
89.2

Process finished with exit code 0
*/

5.带缓冲区的读写

  • 实现终端读取一整行数据(数据带空格)
package main

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

func main()  {
    reader := bufio.NewReader(os.Stdin)
    str, _ := reader.ReadString('\n')
    fmt.Println(str)
}
/*
this is a test
this is a test
*/

6.命令行参数的处理

1.os.Args命令行参数的切片
package main

import (
    "fmt"
    "os"
)

func main()  {
    // 输入带空格字符串需要使用""
    fmt.Println("args[0]=", os.Args[0])
    if len(os.Args) > 1 {
	for index, v := range os.Args {
	    if index == 0 {
		continue
	    }
	    fmt.Printf("args[%d]=%v\n", index, v)
	}
    }
}

/*
>>> go run main.go a b "c d"
args[0]= /xxx/xxx/main.exe
args[1]=a
args[2]=b
args[3]=c d
*/
2.使用flag包获取命令行参数
  • flag.IntVar(&length, "l", 16, "-l 生成密码的长度")
    • &length:用户真实输入的值
    • l:参数名称
    • 16:默认值
    • -l xxx:参数说明
package main

import (
    "flag"
    "fmt"
)

var recusive bool
var test string
var level int

func init()  {
    // 布尔类型只要参数指定了就可以了,不需要写 -r true
    flag.BoolVar(&recusive, "r", false, "这是一个布尔值")
    flag.StringVar(&test, "t", "我是默认值", "这是一个字符串的值")
    flag.IntVar(&level, "l", 1, "整型,级别信息")

    flag.Parse()  // 解析命令行参数
}

func main()  {
    fmt.Printf("recusive: %v\n", recusive)
    fmt.Printf("test: %v\n", test)
    fmt.Printf("level: %v\n", level)
}

/*
>>> go run main.go -r -t 姚明 -l 2
recusive: true
test: 姚明
level: 2
*/
3.urfave/cli包的使用
  • 1.获取包
go get github.com/urfave/cli
  • 2.编码
package main

import (
    "fmt"
    "github.com/urfave/cli"
    "os"
)

func main() {
    var language string
    var recusive bool
    app := cli.NewApp()
    app.Name = "cli"  // 工具名称,可以使用 --help查看
    app.Flags = []cli.Flag{
	cli.StringFlag{
	    Name:        "lang, l",
	    Usage:       "language for the greeting",  // 描述
	    EnvVar:      "",
	    FilePath:    "",
	    Required:    false,
	    Hidden:      false,
	    TakesFile:   false,
	    Value:       "english",
	    Destination: &language,  // 接收命令行输入值的变量
	},
	cli.BoolFlag{
	    Name:        "recusive, r",
	    Usage:       "recusive for the greeting",
	    EnvVar:      "",
	    FilePath:    "",
	    Required:    false,
	    Hidden:      false,
	    Destination: &recusive,
	},
    }
    app.Action = func(c *cli.Context) error {
	var cmd string
	if c.NArg() > 0 {
	    cmd = c.Args()[0]
	    fmt.Println("cmd is ", cmd)
	 }
	fmt.Println("recusive is", recusive)
	fmt.Println("language is", language)
        return nil
    }
    app.Run(os.Args)
}
  • 3.查看帮助文档
>>> go run main.go --help

NAME:
   cli - A new cli application

USAGE:
   main.exe [global options] command [command options] [arguments...]

COMMANDS:
   help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --lang value, -l value  language for the greeting (default: "english")
   --recusive, -r          recusive for the greeting
   --help, -h              show help
  • 4.使用
>>> go run main.go
recusive is false
language is english

>>> go run main.go -l chinese
recusive is false
language is chinese

>>> go run main.go -l chinese -r
recusive is true
language is chinese
posted @ 2022-09-22 15:32  fatpuffer  阅读(306)  评论(0)    收藏  举报