📅 2024年4月28日

📦 使用版本为 1.21.5

输入输出

标准输出输入重定向

⭐️ 输入重定向是指把文件导入到命令中,输出重定向是指把原本要输出到屏幕的数据写入到指定文件中(这句话是我从我的linux笔记复制过来的)

  1. 标准输入重定向(STDNI,文件描述符为0):默认从键盘输入,也可以从其他文件或命令中输入。
  2. 标准输出重定向(STDOUT,文件描述符为1):默认输出到屏幕。
  3. 错误输出重定向(STDERR,文件描述符为2);默认输出到屏幕。

⭐️ 源代码

os包下的 file

1️⃣ 它们类型都是 *File(这个是一个结构体指针,它指向一个打开的文件,并提供了一些方法来操作这个文件,到文件应该会详细学)

// Stdin、Stdout和Stderr是指向标准输入的打开文件,
//标准输出和标准错误文件描述符。
//
//注意,Go运行时在发生严重错误和崩溃时将写入标准错误;
//关闭Stderr可能会导致这些消息转移到其他地方
//保存到稍后打开的文件。
var (
	Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
	Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
	Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)

输出

⭐️ 输出的方法在 Go中有三种

1️⃣ 推荐是使用 fmt,因为它会使用到反射,因此输出的内容通常更容易使人阅读,不过性能很差强人意

func main() {
	var name = "Sam"
	os.Stdout.WriteString(name + "\n") //调用os.Stdout
	fmt.Printf("type %T value %v", name, name) //fmt库的Printf或者Println
	println(name) //内置的println
}

格式化输出

⭐️ 需要调用 fmt包的 Sprintf/Pinrtf,使用方法和 C语言的 printf一样

0 格式化 描述 接收类型
1 %% 输出百分号 % 任意类型
2 %s 输出 string/[] byte string,[] byte
3 %q 格式化字符串,输出的字符串两端有双引号 "" string,[] byte
4 %d 输出十进制整型值 整型类型
5 %f 输出浮点数 浮点类型
6 %e 输出科学计数法形式 ,也可以用于复数 浮点类型
7 %E %e相同 浮点类型
8 %g 根据实际情况判断输出 %f或者 %e,会去掉多余的0 浮点类型
9 %b 输出整型的二进制表现形式 数字类型
10 %#b 输出二进制完整的表现形式 数字类型
11 %o 输出整型的八进制表示 整型
12 %#o 输出整型的完整八进制表示 整型
13 %x 输出整型的小写十六进制表示 数字类型
14 %#x 输出整型的完整小写十六进制表示 数字类型
15 %X 输出整型的大写十六进制表示 数字类型
16 %#X 输出整型的完整大写十六进制表示 数字类型
17 %v 输出值原本的形式,多用于数据结构的输出 任意类型
18 %+v 输出结构体时将加上字段名 任意类型
19 %#v 输出完整Go语法格式的值 任意类型
20 %t 输出布尔值 布尔类型
21 %T 输出值对应的Go语言类型值 任意类型
22 %c 输出Unicode码对应的字符 int32
23 %U 输出字符对应的Unicode码 rune,byte
24 %p 输出指针所指向的地址 指针类型

1️⃣ 演示代码

fmt.Printf("%%%s\n", "hello world")
 
fmt.Printf("%s\n", "hello world") 
fmt.Printf("%q\n", "hello world") 
fmt.Printf("%d\n", 2<<7-1)	

fmt.Printf("%f\n", 1e2)	
fmt.Printf("%e\n", 1e2)		
fmt.Printf("%E\n", 1e2)		
fmt.Printf("%g\n", 1e2)		

fmt.Printf("%b\n", 2<<7-1)	
fmt.Printf("%#b\n", 2<<7-1)	
fmt.Printf("%o\n", 2<<7-1)	
fmt.Printf("%#o\n", 2<<7-1)	
fmt.Printf("%x\n", 2<<7-1)	
fmt.Printf("%#x\n", 2<<7-1)	
fmt.Printf("%X\n", 2<<7-1)	
fmt.Printf("%#X\n", 2<<7-1)	

type person struct {
    name    string
    age     int
    address string
}
fmt.Printf("%v\n", person{"lihua", 22, "beijing"})
fmt.Printf("%+v\n", person{"lihua", 22, "beijing"})
fmt.Printf("%#v\n", person{"lihua", 22, "beijing"})
fmt.Printf("%t\n", true)					
fmt.Printf("%T\n", person{})				
fmt.Printf("%c%c\n", 20050, 20051)			
fmt.Printf("%U\n", '码')							   
fmt.Printf("%p\n", &person{})				


输入

⭐️ 如果需要使用到输入的话,就需要使用到 fmt包提供的三个函数

//源代码 scan.go
func Scan(a ...any) (n int, err error) {
	return Fscan(os.Stdin, a...)
}

// Scanln is similar to Scan, but stops scanning at a newline and
// after the final item there must be a newline or EOF.
func Scanln(a ...any) (n int, err error) {
	return Fscanln(os.Stdin, a...)
}

// Scanf scans text read from standard input, storing successive
// space-separated values into successive arguments as determined by
// the format. It returns the number of items successfully scanned.
// If that is less than the number of arguments, err will report why.
// Newlines in the input must match newlines in the format.
// The one exception: the verb %c always scans the next rune in the
// input, even if it is a space (or tab etc.) or newline.
func Scanf(format string, a ...any) (n int, err error) {
	return Fscanf(os.Stdin, format, a...)
}
// 扫描从os.Stdin读入的文本,根据空格分隔,换行也被当作空格
func Scan(a ...any) (n int, err error) 

// 与Scan类似,但是遇到换行停止扫描
func Scanln(a ...any) (n int, err error)

// 根据格式化的字符串扫描
func Scanf(format string, a ...any) (n int, err error)

⭐️ 它们三种使用方法也有不同,但是大致上都类似,它们和C语言很类似,传入一个参数的值需要使用到 &来传入这个值在内存中的地址,如果单纯不加 &那么传递的就是一个副本,在方法函数内部无论如何修改都不会影响到本体

1️⃣ Scanf方法,它的使用方法和 C语言及其相似(因为我不敢说一模一样)

func main() {
	var s, s2 string
	fmt.Scanf("%s %s", &s, &s2)
	fmt.Println(s, s2)
}

2️⃣ Scan和Scanln方法,它们两最大区别就是一个遇到回车停止一个遇到回车也把回车当作空格

func main() {
	var s, s2 string
	fmt.Scanln(&s, &s2)
    fmt.Scan(&s, &s2)
	fmt.Println(s, s2)
}

⭐️ go输入默认的分割符号位空格

func main() {
   var s, s2 string
   fmt.Scan(&s, &s2)
   fmt.Println(s, s2)
}



//输出:
a b  //输入
a b  //输出

缓冲

🌮 回马枪的时候在学习,找的资料简直就是一笔带过

⭐️ 当对性能有要求时可以使用 bufio包进行读取,例如下面这个输入的例子

func main() {
   // 读
   scanner := bufio.NewScanner(os.Stdin)
   scanner.Scan()
   fmt.Println(scanner.Text())
}
abcedfg
abcedfg

⭐️ 输出

func main() {
   // 写
   writer := bufio.NewWriter(os.Stdout)
   writer.WriteString("hello world!\n")
   writer.Flush()
   fmt.Println(writer.Buffered())
}
hello world!
0