格式化输入
函数 | 说明 |
---|---|
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文件中定义了如下函数:
func Printf(format string, a ...interface{}) (n int, err error)
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
func Sprintf(format string, a ...interface{}) string
func Print(a ...interface{}) (n int, err error)
func Fprint(w io.Writer, a ...interface{}) (n int, err error)
func Sprint(a ...interface{}) string
func Println(a ...interface{}) (n int, err error)
func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
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 接口。
type Reader struct {
buf []byte
rd io.Reader // reader provided by the client
r, w int // buf read and write positions
err error
lastByte int
lastRuneSize int
}
type Writer struct {
err error
buf []byte
n int
wr io.Writer
}
实现了read writer 接口
func (b *Reader) Read(p []byte) (n int, err error)
func (b *Writer) Write(p []byte) (nn int, err error)
bufio 包通过 bufio.NewReader 和bufio.NewWriter 来创建I/O方法集
package main
import (
"bufio"
"io/ioutil"
"os"
"fmt"
)
func main() {
ioutil.WriteFile("./tt.txt", []byte("WriteString writes a ## string"), 0666)
fileObj, _ := os.Open("./tt.txt")
Rd := bufio.NewReader(fileObj)
content, _ := Rd.ReadSlice('#')
fmt.Println(string(content))
}
程序输出:
WriteString writes a #
常用函数
// 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)
31.3 ioutil包
下面代码使用ioutil包实现2种读文件,1种写文件的方法,其中 ioutil.ReadAll 可以读取所有io.Reader流。所以在网络连接中,也经常使用ioutil.ReadAll来读取流
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
fileObj, err := os.Open("./tt.txt")
defer fileObj.Close()
Contents, _ := ioutil.ReadAll(fileObj)
fmt.Println(string(contents))
if contents, _ := ioutil.ReadFile("./tt.txt"); err == nil {
fmt.Println(string(contents))
}
ioutil.WriteFile("./t3.txt", contents, 0666)
}
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个函数参数是该命令参数的简要说明。
import (
"flag"
"fmt"
)
func main() {
var user string
var passwd string
var host string
var port uint64
flag.StringVar(&user,"u","","用户名")
flag.StringVar(&passwd,"p","","密码")
flag.StringVar(&host,"h","127.0.0.1" ,"主机名")
flag.Uint64Var(&port,"P",3306,"端口号")
flag.Parse()
fmt.Printf("user=%v passwd=%v host=%v,port=%v\n",user,passwd,host,port)
}
编译 go run main.go 文件 执行./main -help二进制 会有帮助提示文件
./main -help
Usage of ./main:
-P uint
端口号 (default 3306)
-h string
主机名 (default "127.0.0.1")
-p string
密码
-u string
用户名
flag.Usage 的调用必须在flag.Parse函数之前
flag.Usage= func() {
fmt.Fprintf(os.Stderr,”Usage of %s:\n”,”question”)
flag.PrintDefaults()
}
启动网络服务,设置网络监听端口
-flag
-flag=x
-flag x // non-boolean flags only
type BaseHander struct {
}
func (hander *BaseHander)ServeHTTP(resp http.ResponseWriter,req *http.Request){
fmt.Println("url path=>",req.URL.Path)
fmt.Println("url param a =>",req.URL.Query().Get("a"))
resp.Write([]byte("hello world"))
}
var (
port string
)
func main() {
flag.StringVar(&port,"port",":8080","port ")
flag.Parse()
http.ListenAndServe(port,&BaseHander{});
}