读写数据

读取用户输入

  • 类似于 C 中的 scanf() 函数, Go 中也有对应的针对标准输入输出函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main
import "fmt"

var (
str string
input = "11.22 / 12 / Python"
format = "%f / %d / %s"
f_num float32
i_num int
s string
)

func main(){
// 从标准输出框中读取
fmt.Println("This is a test for a scanf function...")
fmt.Scanln(&str) // Scanln 扫描来自标准输入的文本,空格分割
// fmt.Scanf("%s", str) // Scanf 扫描来自标准输入的文本,参数第一个为格式

// 从字符串中读取
fmt.Sscanf(input, format, &f_num, &i_num, &s)

fmt.Printf("Hello %s", str)
fmt.Printf("Load from str %f %i %s", f_num, i_num, s)
}

  • 使用 bufio 包提供缓冲读取数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

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

var (
inputReader *bufio.Reader
input string
err error
)

func main() {
inputReader = bufio.NewReader(os.Stdin)
fmt.Println("Please enter some input:")
if input, err = inputReader.ReadString('\n'); err == nil {
fmt.Printf("The input was %s\n", input)
}
}

inputReader 是一个指向 bufio.Reader 的指针,第一行代码会创建一个读取器与标准输入绑定。

文件读写

读文件

在 Go 语言中,文件使用指向 os.File 类型的指针来表示,之前提到的 os.Stdin 的类型都是 *os.File

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

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

func main() {
if inputFile, err := os.Open("test.dat"); err != nil{
return
}

defer inputFile.Close()

inputReader := bufio.NewReader(inputFile) // 将待读取的内容从标准输入变为文件

for {
inputString, err := inputReader.ReadString('\n')
fmt.Printf("The input is %s", inputString)
if err == io.EOF {
return
}
}
}

其他类似的函数如下:

  • 将整个文件内容读入一个字符串中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"fmt"
"io/ioutil"
"os"
)

func main() {
inputFile := "testi.txt"
outputFile := "testo.txt"
if buf, err := ioutil.ReadFile(inputFile); err != nil {
fmt.Fprintf(os.Stderr, "File Error: %s", err)
}

fmt.Printf("%s\n", string(buf))
err = ioutil.WriteFile(outputFile, buf, 0644) // oct
if err != nil {
panic(err.Error())
}
}

  • 带缓冲的读取
1
2
3
4
5
buf := make([]byte, 1024)
// ...
n, err := inputReader.Read(buf)
if ( n==0 ) {break}

写文件

OpenFile 函数的三个参数:文件名、一个或多个标志(使用逻辑标识符 | 连接)和使用文件的权限

标志名称 标志内涵
os.O_RDONLY 只读
os.O_WRONLY 只写
os.O_CREATE 文件不存咋则创建
os.O_TRUNC 截断

文件拷贝

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
"fmt"
"io"
"os"
)

func main() {
CopyFile("test1.txt", "test2.txt")
fmt.Println("Copy finished!")
}

func CopyFile(dstName,srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}

defer src.Close()

dst, err := os.Create(dstName)
if err != nil {
return
}

defer dst.Close() // 文件打开后能保证它能关闭

return io.Copy(dst, src)
}

从命令行读取参数

os 包

os 包中有一个 string 类型的切片变量 os.Args,用来处理一些基本的命令行参数,它在程序启动后读取命令行输入的参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import (
"fmt"
"os"
"strings"
)

func main() {
who := "Tau"
if len(os,Args) > 1 {
who += strings.Join(os.Args[1:], ", ")
fmt.Printlln("Hello", who)
}
}

flag 包

flag 包有一个扩展功能用来解析命令行选项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

import (
"flag"
"os"
)

var NewLine = flag.Bool("n", false, "print new line")

const (
Space = " "
Newline = "\n"
)

func main() {
flag.PrintDefaults()
flag.Parse()

var s string = ""

for i := 0, i < flag.NArg(); i++ {
if i > 0 {
s += " "
if *NewLine {
s += NewLine
}
}
s += flag.Arg(i)
}

os.Stdout.WriteString(s)
}

用 buffer 读取文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main

import (
"bufio"
"flag"
"fmt"
"io"
"os"
)

func cat(r *bufio.Reader) {
for {
buf, err := r.ReadBytes('\n')
if err == io.EOF {
break
}
fmt.Fprintf(os.Stdout, "%s", buf)
}
return
}

func main() {
flag.Parse()
if flag.NArg() == 0 {
cat(bufio.NewReader(os.Stdin))
}

for i:=0; i<flag.NArg(); i++ {
f, err := os.Open(flag.Arg(i))
if err != nil {
fmt.Fprintf(os.Stderr, "%s: error reading from %s: %s\n", os.Args[0], flag.Arg(i), err)
continue
}
cat(bufio.NewReader(f))
}
}

用切片读写文件

PASSED

用 defer 关闭文件

PASSED

使用接口的实际例子 fmt.Fprintf

PASSED

格式化 json 数据

含义解释

名称 数据转化方向
序列化(编码) 数据结构 -> 指定格式
反序列化(解码) 指定格式 -> 数据结构
  • 序列化代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"encoding/json"
"fmt"
"log"
"os"
)

type Address struct {
Type string
City string
Country string
}

func main() {
pa := &Address{"private", "Shanghai", "xuhui"}
js, _ := json.Marshal(pa)
}

  • 反序列化代码
1
2
3
b := []byte(`{"name":"tau", "city":"shanghai"}`)
var c interface{}
err = json.Unmarshal(b, &c)

XML 数据格式

PASSED

用 Gob 传输数据

PASSED

Go 中的密码学

PASSED