格式化输入

函数 说明
fmt.Scanf(format string, a…interface{}) 格式化输⼊,空格作为分隔符,占位符和格式化输出⼀致
fmt.Scan(a …interface{}) 从终端获取⽤户输⼊,存储在Scanln中的参数⾥,空格和换⾏符作为分隔符
fmt.Scanln(a …interface{}) 从终端获取⽤户输⼊,存储在Scanln中的参数⾥,空格作为分隔符,遇到换⾏符结束

⽂件获取输⼊

fmt.Fscanf(file, format string, a…interface{}): 从⽂件格式化输⼊,空格作为分隔符, 占位符和格式化输出⼀致

fmt.Fscan(file, a …interface{}): 从⽂件获取⽤户输⼊,存储在Scanln中的参数⾥,空格和换⾏符作为分隔符

fmt.Fscanln(file, a …interface{}): 从⽂件获取⽤户输⼊,存储在Scanln中的参数⾥,空格作为分隔符,遇到换⾏符结束

格式化输出

在fmt包,有关格式化输入输出的方法就两大类:Scan 和 Print ,分别在scan.go 和 print.go 文件中。print.go文件中定义了如下函数:

  1. func Printf(format string, a ...interface{}) (n int, err error)
  2. func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
  3. func Sprintf(format string, a ...interface{}) string
  4. func Print(a ...interface{}) (n int, err error)
  5. func Fprint(w io.Writer, a ...interface{}) (n int, err error)
  6. func Sprint(a ...interface{}) string
  7. func Println(a ...interface{}) (n int, err error)
  8. func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
  9. func Sprintln(a ...interface{}) string
fmt.Printf(format string, a…interface{}) 格式化输出,并打印到终端
fmt.Println(a …interface{}) 把零个或多个变量打印到终端, 并换⾏
fmt.Print(a …interface{}) 把零个或多个变量打印到终端

输出到⽂件中

fmt.Fprintf(file, format string, a…interface{}): 格式化输出,并写⼊到⽂件中

fmt.Fprintln(file, a …interface{}): 把零个或多个变量写⼊到⽂件中, 并换⾏

fmt.Fprint(file, a …interface{}): 把零个或多个变量写⼊到⽂件

bufio

bufio库实现了I/O的缓冲操作,通过内嵌io.Reader、io.Writer接口,新建了Reader ,Writer 结构体。同时也实现了Reader 和 Writer 接口。

  1. type Reader struct {
  2. buf []byte
  3. rd io.Reader // reader provided by the client
  4. r, w int // buf read and write positions
  5. err error
  6. lastByte int
  7. lastRuneSize int
  8. }
  9. type Writer struct {
  10. err error
  11. buf []byte
  12. n int
  13. wr io.Writer
  14. }

实现了read writer 接口

  1. func (b *Reader) Read(p []byte) (n int, err error)
  2. func (b *Writer) Write(p []byte) (nn int, err error)

bufio 包通过 bufio.NewReader 和bufio.NewWriter 来创建I/O方法集

  1. package main
  2. import (
  3. "bufio"
  4. "io/ioutil"
  5. "os"
  6. "fmt"
  7. )
  8. func main() {
  9. ioutil.WriteFile("./tt.txt", []byte("WriteString writes a ## string"), 0666)
  10. fileObj, _ := os.Open("./tt.txt")
  11. Rd := bufio.NewReader(fileObj)
  12. content, _ := Rd.ReadSlice('#')
  13. fmt.Println(string(content))
  14. }

程序输出:

  1. WriteString writes a #

常用函数

  1. // NewReaderSize 将 rd 封装成一个带缓存的 bufio.Reader 对象,缓存大小由 size 指定(如果小于 16 则会被设置为 16)。
  2. func NewReaderSize(rd io.Reader, size int) *Reader
  3. // NewReader 相当于 NewReaderSize(rd, 4096)
  4. func NewReader(rd io.Reader) *Reader
  5. // Peek 返回缓存的一个切片,该切片引用缓存中前 n 个字节的数据。
  6. // 如果 n 大于缓存的总大小,则返回 当前缓存中能读到的字节的数据。
  7. func (b *Reader) Peek(n int) ([]byte, error)
  8. // Read 从 b 中读出数据到 p 中,返回读出的字节数和遇到的错误。
  9. // 如果缓存不为空,则只能读出缓存中的数据,不会从底层 io.Reader
  10. // 中提取数据,如果缓存为空,则:
  11. // 1、len(p) >= 缓存大小,则跳过缓存,直接从底层 io.Reader 中读出到 p 中。
  12. // 2、len(p) < 缓存大小,则先将数据从底层 io.Reader 中读取到缓存中,
  13. // 再从缓存读取到 p 中。
  14. func (b *Reader) Read(p []byte) (n int, err error)
  15. // Buffered 该方法返回从当前缓存中能被读到的字节数。
  16. func (b *Reader) Buffered() int
  17. // Discard 方法跳过后续的 n 个字节的数据,返回跳过的字节数。
  18. func (b *Reader) Discard(n int) (discarded int, err error)
  19. // ReadSlice 在 b 中查找 delim 并返回 delim 及其之前的所有数据。
  20. // 该操作会读出数据,返回的切片是已读出的数据的引用,切片中的数据在下一次
  21. // 读取操作之前是有效的。
  22. // 如果找到 delim,则返回查找结果,err 返回 nil。
  23. // 如果未找到 delim,则:
  24. // 1、缓存不满,则将缓存填满后再次查找。
  25. // 2、缓存是满的,则返回整个缓存,err 返回 ErrBufferFull。
  26. // 如果未找到 delim 且遇到错误(通常是 io.EOF),则返回缓存中的所有数据
  27. // 和遇到的错误。
  28. // 因为返回的数据有可能被下一次的读写操作修改,所以大多数操作应该使用
  29. // ReadBytes 或 ReadString,它们返回的是数据的拷贝。
  30. func (b *Reader) ReadSlice(delim byte) (line []byte, err error)
  31. // ReadLine 是一个低水平的行读取原语,大多数情况下,应该使用ReadBytes('\n')
  32. // 或 ReadString('\n'),或者使用一个 Scanner。
  33. // ReadLine 通过调用 ReadSlice 方法实现,返回的也是缓存的切片。
  34. // 用于读取一行数据,不包括行尾标记(\n 或 \r\n)。
  35. // 只要能读出数据,err 就为 nil。如果没有数据可读,则 isPrefix
  36. // 返回 false,err 返回 io.EOF。
  37. // 如果找到行尾标记,则返回查找结果,isPrefix 返回 false。
  38. // 如果未找到行尾标记,则:
  39. // 1、缓存不满,则将缓存填满后再次查找。
  40. // 2、缓存是满的,则返回整个缓存,isPrefix 返回 true。
  41. // 整个数据尾部“有一个换行标记”和“没有换行标记”的读取结果是一样。
  42. // 如果 ReadLine 读取到换行标记,则调用 UnreadByte 撤销的是换行标记,
  43. // 而不是返回的数据。
  44. func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)
  45. // ReadBytes 功能同 ReadSlice,只不过返回的是缓存的拷贝。
  46. func (b *Reader) ReadBytes(delim byte) (line []byte, err error)
  47. // ReadString 功能同 ReadBytes,只不过返回的是字符串。
  48. func (b *Reader) ReadString(delim byte) (line string, err error)
  49. // Reset 将 b 的底层 Reader 重新指定为 r,同时丢弃缓存中的所有数据,
  50. // 复位所有标记和错误信息。 bufio.Reader。
  51. func (b *Reader) Reset(r io.Reader)

31.3 ioutil包

下面代码使用ioutil包实现2种读文件,1种写文件的方法,其中 ioutil.ReadAll 可以读取所有io.Reader流。所以在网络连接中,也经常使用ioutil.ReadAll来读取流

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. )
  7. func main() {
  8. fileObj, err := os.Open("./tt.txt")
  9. defer fileObj.Close()
  10. Contents, _ := ioutil.ReadAll(fileObj)
  11. fmt.Println(string(contents))
  12. if contents, _ := ioutil.ReadFile("./tt.txt"); err == nil {
  13. fmt.Println(string(contents))
  14. }
  15. ioutil.WriteFile("./t3.txt", contents, 0666)
  16. }


31.4 bufio包

,利用缓冲来处理流,后面章节我们也会讲到这块内容。

程序输出:
WriteString writes a #
bufio包中,主要方法如下:
// NewReaderSize 将 rd 封装成一个带缓存的 bufio.Reader 对象,缓存大小由 size 指定(如果小于 16 则会被设置为 16)。
func NewReaderSize(rd io.Reader, size int) *Reader

// NewReader 相当于 NewReaderSize(rd, 4096)
func NewReader(rd io.Reader) *Reader

// Peek 返回缓存的一个切片,该切片引用缓存中前 n 个字节的数据。
// 如果 n 大于缓存的总大小,则返回 当前缓存中能读到的字节的数据。
func (b *Reader) Peek(n int) ([]byte, error)

// Read 从 b 中读出数据到 p 中,返回读出的字节数和遇到的错误。
// 如果缓存不为空,则只能读出缓存中的数据,不会从底层 io.Reader
// 中提取数据,如果缓存为空,则:
// 1、len(p) >= 缓存大小,则跳过缓存,直接从底层 io.Reader 中读出到 p 中。
// 2、len(p) < 缓存大小,则先将数据从底层 io.Reader 中读取到缓存中,
// 再从缓存读取到 p 中。
func (b *Reader) Read(p []byte) (n int, err error)

// Buffered 该方法返回从当前缓存中能被读到的字节数。
func (b *Reader) Buffered() int

// Discard 方法跳过后续的 n 个字节的数据,返回跳过的字节数。
func (b *Reader) Discard(n int) (discarded int, err error)

// ReadSlice 在 b 中查找 delim 并返回 delim 及其之前的所有数据。
// 该操作会读出数据,返回的切片是已读出的数据的引用,切片中的数据在下一次
// 读取操作之前是有效的。
// 如果找到 delim,则返回查找结果,err 返回 nil。
// 如果未找到 delim,则:
// 1、缓存不满,则将缓存填满后再次查找。
// 2、缓存是满的,则返回整个缓存,err 返回 ErrBufferFull。
// 如果未找到 delim 且遇到错误(通常是 io.EOF),则返回缓存中的所有数据
// 和遇到的错误。
// 因为返回的数据有可能被下一次的读写操作修改,所以大多数操作应该使用
// ReadBytes 或 ReadString,它们返回的是数据的拷贝。
func (b *Reader) ReadSlice(delim byte) (line []byte, err error)

// ReadLine 是一个低水平的行读取原语,大多数情况下,应该使用ReadBytes(‘\n’)
// 或 ReadString(‘\n’),或者使用一个 Scanner。
// ReadLine 通过调用 ReadSlice 方法实现,返回的也是缓存的切片。
// 用于读取一行数据,不包括行尾标记(\n 或 \r\n)。
// 只要能读出数据,err 就为 nil。如果没有数据可读,则 isPrefix
// 返回 false,err 返回 io.EOF。
// 如果找到行尾标记,则返回查找结果,isPrefix 返回 false。
// 如果未找到行尾标记,则:
// 1、缓存不满,则将缓存填满后再次查找。
// 2、缓存是满的,则返回整个缓存,isPrefix 返回 true。
// 整个数据尾部“有一个换行标记”和“没有换行标记”的读取结果是一样。
// 如果 ReadLine 读取到换行标记,则调用 UnreadByte 撤销的是换行标记,
// 而不是返回的数据。
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)

// ReadBytes 功能同 ReadSlice,只不过返回的是缓存的拷贝。
func (b *Reader) ReadBytes(delim byte) (line []byte, err error)

// ReadString 功能同 ReadBytes,只不过返回的是字符串。
func (b *Reader) ReadString(delim byte) (line string, err error)

// Reset 将 b 的底层 Reader 重新指定为 r,同时丢弃缓存中的所有数据,
// 复位所有标记和错误信息。 bufio.Reader。
func (b *Reader) Reset(r io.Reader)
下面一段代码是,里面有用到peek,Discard 等方法,可以修改方法参数值,仔细体会:
package main

import (
“bufio”
“fmt”
“strings”
)

func main() {
sr := strings.NewReader(“ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890”)
buf := bufio.NewReaderSize(sr, 0) //默认16
b := make([]byte, 10)

fmt.Println(“==”, buf.Buffered()) // 0
S, _ := buf.Peek(5)
fmt.Printf(“%d == %q\n”, buf.Buffered(), s) //
nn, er := buf.Discard(3)
fmt.Println(nn, er)

for n, err := 0, error(nil); err == nil; {
fmt.Printf(“Buffered:%d ==Size:%d== n:%d== b[:n] %q == err:%v\n”, buf.Buffered(), buf.Size(), n, b[:n], err)
n, err = buf.Read(b)
fmt.Printf(“Buffered:%d ==Size:%d== n:%d== b[:n] %q == err: %v == s: %s\n”, buf.Buffered(), buf.Size(), n, b[:n], err, s)
}

fmt.Printf(“%d == %q\n”, buf.Buffered(), s)
}

命令⾏参数

os.Arg

flag

flag 包实现了命令行参数的解析
第1个参数是用于存储该命令参数值的地址,具体到这里就是在声明的变量的地址了。
第2个参数是为了指定该命令参数的名称。
第3个参数是为了指定在未追加该命令参数时的默认值。
第4个函数参数是该命令参数的简要说明。

  1. import (
  2. "flag"
  3. "fmt"
  4. )
  5. func main() {
  6. var user string
  7. var passwd string
  8. var host string
  9. var port uint64
  10. flag.StringVar(&user,"u","","用户名")
  11. flag.StringVar(&passwd,"p","","密码")
  12. flag.StringVar(&host,"h","127.0.0.1" ,"主机名")
  13. flag.Uint64Var(&port,"P",3306,"端口号")
  14. flag.Parse()
  15. fmt.Printf("user=%v passwd=%v host=%v,port=%v\n",user,passwd,host,port)
  16. }

编译 go run main.go 文件 执行./main -help二进制 会有帮助提示文件

  1. ./main -help
  2. Usage of ./main:
  3. -P uint
  4. 端口号 (default 3306)
  5. -h string
  6. 主机名 (default "127.0.0.1")
  7. -p string
  8. 密码
  9. -u string
  10. 用户名

flag.Usage 的调用必须在flag.Parse函数之前
flag.Usage= func() {
fmt.Fprintf(os.Stderr,”Usage of %s:\n”,”question”)
flag.PrintDefaults()
}

  1. 启动网络服务,设置网络监听端口

-flag
-flag=x
-flag x // non-boolean flags only

  1. type BaseHander struct {
  2. }
  3. func (hander *BaseHander)ServeHTTP(resp http.ResponseWriter,req *http.Request){
  4. fmt.Println("url path=>",req.URL.Path)
  5. fmt.Println("url param a =>",req.URL.Query().Get("a"))
  6. resp.Write([]byte("hello world"))
  7. }
  8. var (
  9. port string
  10. )
  11. func main() {
  12. flag.StringVar(&port,"port",":8080","port ")
  13. flag.Parse()
  14. http.ListenAndServe(port,&BaseHander{});
  15. }

第三方

urfave/cli

https://github.com/urfave/cli

spf13/cobra

https://github.com/spf13/cobra