本节主要内容:

1. 终端读写
2. 文件读写
3. 命令行参数
4. Json
5. 自定义错误

1. 终端读写

操作终端相关文件句柄常量
    os.Stdin:标准输入
    os.Stdout:标准输出
    os.Stderr:标准错误输出

 package main

 import (
"fmt"
) var (
firstName, lastName, s string
i int
f float32
input = "56.12 / 5212 / Go"
format = "%f / %d / %s"
) func main() {
fmt.Println("Please enter your full name: ") //Chris Naegels
fmt.Scanln(&firstName, &lastName) //和下面等价
// fmt.Scanf("%s %s", &firstName, &lastName)
fmt.Printf("Hi %s %s!\n", firstName, lastName) // Hi Chris Naegels!
fmt.Sscanf(input, format, &f, &i, &s)
fmt.Println("From the string we read: ", f, i, s) //From the string we read: 56.12 5212 Go
}

example

 package main 

 import (
"bufio"
"fmt"
"os"
) func main() {
fmt.Println("Input string >>")
reader := bufio.NewReader(os.Stdin)
res, err := reader.ReadString('\n')
if err != nil {
fmt.Println("Read failed, Error: ", err)
}
fmt.Printf("Read success, content: ", res)
}

从终端读入

 package main 

 import (
"fmt"
"os"
"bufio"
) func main() {
// fmt.Fprintf(os.Stdout, "%s\n", "hello world") buf := bufio.NewWriter(os.Stdout)
fmt.Fprintf(buf, "%s\n", "hello world")
buf.Flush()
}

带缓冲区的终端读写

2. 文件读写

   (1)文件读取

bufio模块通过对io模块的封装,提供了数据缓冲功能,能够一定程度减少大块数据读写带来的开销。
    实际上在bufio各个组件内部都维护了一个缓冲区,数据读写操作都直接通过缓存区进行。当发起一次读写操作时,会首先尝试从缓冲区获取数据;只有当缓冲区没有数据  时,才会从数据源获取数据更新缓冲。

 package main 

 import (
"os"
"fmt"
"bufio"
) func main() {
var input *bufio.Reader
var str string
var err error input = bufio.NewReader(os.Stdin)
str, err = input.ReadString('\n') //注意:ReadString会返回读取的字符串(包括分隔符'\n')
if err != nil {
fmt.Println("Read failed")
}
fmt.Println("Read success, content: ", str)
}

example

练习: 从终端读取一行字符串,统计英文、数字、空格以及其他字符的数量。

 package main 

 import (
"fmt"
"os"
"bufio"
"strings"
) type CharCount struct {
ChCount int
NumCount int
SpaceCount int
OtherCount int
} func Count(str string, cc *CharCount) {
runeArr := []rune(str)
for _, v := range runeArr {
fmt.Printf("--%v\n",v)
switch {
case v >= 'A' && v <= 'Z':
fallthrough
case v >= 'a' && v <= 'z':
cc.ChCount++
case v >= '' && v <= '':
cc.NumCount++
case v == ' ':
cc.SpaceCount++
default:
cc.OtherCount++
}
}
} func main() {
var cc CharCount fmt.Println("Input string >>")
reader := bufio.NewReader(os.Stdin)
str, err := reader.ReadString('\n')
if err != nil {
fmt.Println("Read failed")
} str = strings.Trim(string(str), "\r\n") //去掉末尾的\r\n,否则OtherCount会多加2 Count(string(str), &cc)
fmt.Println(cc)
}

从terminal读取

os.File封装所有文件相关操作,之前讲的 os.Stdin,os.Stdout, os.Stderr都是*os.File
     a. 打开一个文件进行读操作: os.Open(name string) (*File, error)
     b. 关闭一个文件:File.Close()

  1)将整个文件读取到内存

 package main

 import (
"fmt"
"io/ioutil"
) func main() {
fileName := "F:\\Go\\project\\src\\go_dev\\day7\\test.txt"
data, err := ioutil.ReadFile(fileName)
if err != nil {
fmt.Println("File reading error", err)
return
}
fmt.Println("Contents of file: ", string(data))
}

读取整个文件

2)分块读取文件
         在前面的章节,我们学习了如何把整个文件读取到内存。当文件非常大时,尤其在 RAM 存储量不足的情况下,把整个文件都读入内存是没有意义的。更好的方法是分块读取文件。这可以使用 bufio 包来完成。

 package main

 import (
"bufio"
"fmt"
"log"
"os"
"io"
) func EmptyArray(arr []byte) {
for i := ; i < len(arr); i++ {
arr[i] =
}
} func main() {
fileName := "F:\\Go\\project\\src\\go_dev\\day7\\test.txt" f, err := os.Open(fileName)
if err != nil {
log.Fatal(err)
} defer func() {
if err = f.Close(); err != nil {
log.Fatal(err)
}
}() var str string
r := bufio.NewReader(f)
b := make([]byte, ) //每次读取3个字节 for {
EmptyArray(b) _, err := r.Read(b)
if err == io.EOF {
fmt.Println("Read finish")
break
} if err != nil {
fmt.Println("Error reading file: ", err)
break
}
str = string(b)
fmt.Printf("%s", str)
}
}

分块读取

    3)逐行读取文件

 package main

 import (
"bufio"
"fmt"
"log"
"os"
) func main() {
fileName := "F:\\Go\\project\\src\\go_dev\\day7\\test.txt" f, err := os.Open(fileName)
if err != nil {
log.Fatal(err)
} defer func() {
if err = f.Close(); err != nil {
log.Fatal(err)
}
}() s := bufio.NewScanner(f)
for s.Scan() {
fmt.Println(s.Text())
} if err = s.Err(); err != nil {
log.Fatal(err)
}
}

逐行读取

练习:读取压缩文件(zip)

 package main

 // 引入所需包
import (
"os"
"compress/gzip"
"io/ioutil"
"fmt"
) // gzip文件 func main() {
fileName := "F:\\Go\\project\\src\\go_dev\\day7\\test.zip"
// 打开本地gz格式压缩包
fr, err := os.Open(fileName)
if err != nil {
panic(err)
} else {
println("open file success!")
} // defer: 在函数退出时,执行关闭文件
defer fr.Close() // 创建gzip文件读取对象
gr, err := gzip.NewReader(fr)
if err != nil {
panic(err)
} // defer: 在函数退出时,执行关闭gzip对象
defer gr.Close() // 读取gzip对象内容
rBuf, err := ioutil.ReadAll(gr)
if err != nil {
fmt.Println("[read gzip data err]: ", err)
} // 以文本形式输出
fmt.Printf("%s\n", rBuf)
}

读取压缩文件示例

   (2)文件写入

os.OpenFile("output.dat", os.O_WRONLY|os.O_CREATE, 0666)

第二个参数:文件打开模式:
. os.O_WRONLY:只写
. os.O_CREATE:创建文件
. os.O_RDONLY:只读
. os.O_RDWR:读写
. os.O_TRUNC :清空
第三个参数:权限控制:
r ——>
w ——>
x ——>
 package main 

 import (
"fmt"
"os"
"bufio"
) func main() {
filePath := "F:\\Go\\project\\src\\go_dev\\day7\\write_test.txt"
outFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, )
if err != nil {
fmt.Println("Failed to write file")
return
}
defer outFile.Close() outWrite := bufio.NewWriter(outFile)
des := "hello world!\n"
for i := ; i < ; i++ {
outWrite.WriteString(des)
}
outWrite.Flush()
}

example

    (3)拷贝文件

 package main 

 import (
"fmt"
"os"
"io"
) //A successful Copy returns err == nil, not err == EOF
func CopyFile(destName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
panic(err)
}
defer src.Close() dest, err := os.OpenFile(destName, os.O_WRONLY|os.O_CREATE, )
if err != nil {
panic(err)
}
defer dest.Close() return io.Copy(dest, src)
} func main() {
srcName := "F:\\Go\\project\\src\\go_dev\\day7\\write_test.txt"
destName := "F:\\Go\\project\\src\\go_dev\\day7\\dest_test.txt" wByte, err := CopyFile(destName, srcName)
if err != nil {
fmt.Println("Copy failed")
} else {
fmt.Printf("Copy %d byte from src to dest\n", wByte)
}
}

Copy

3. 命令行参数

os.Args是一个string的切片,用来存储所有的命令行参数
    flag包的使用,用来解析命令行参数:

flag.BoolVar(&test, "b", false, "print on newline")
flag.StringVar(&str, "s", "", "print on newline")
flag.IntVar(&count, "c", , "print on newline")
 package main

 import (
"fmt"
"os"
) func main() {
fmt.Printf("len of args:%d\n", len(os.Args))
for i, v := range os.Args {
fmt.Printf("args[%d]=%s\n", i, v)
}
} //输入:
//go run main7.go hello world
// 输出:
// len of args:3
// args[0]=C:\Users\ADMINI~1\AppData\Local\Temp\go-build596136718\command-line-argu
// ments\_obj\exe\main7.exe
// args[1]=hello
// args[2]=world

example

 package main

 import (
"fmt"
"flag"
) func main() {
var configPath string
var logLevel int flag.StringVar(&configPath, "c", "", "Please config path")
flag.IntVar(&logLevel, "d", , "Please log level") flag.Parse() fmt.Println("configPath: ", configPath)
fmt.Println("logLevel: ", logLevel)
}

example2

4. Json数据协议

func Marshal(v interface{}) ([]byte, error)
func Unmarshal(data []byte, v interface{}) error
导入包:import "encoding/json"
序列化: json.Marshal(data interface{})
反序列化: json.UnMarshal(data []byte, v interface{})

练习:json序列化结构体

 package main

 import (
"encoding/json"
"fmt"
) type User struct {
UserName string `json:"username"`
NickName string `json:"nickname"`
Age int
Birthday string
Sex string
Email string
Phone string
} func testStruct() {
user1 := &User{
UserName: "user1",
NickName: "上课看似",
Age: ,
Birthday: "2008/8/8",
Sex: "男",
Email: "mahuateng@qq.com",
Phone: "",
} data, err := json.Marshal(user1)
if err != nil {
fmt.Printf("json.marshal failed, err:", err)
return
} fmt.Printf("%s\n", string(data))
} func testInt() {
var age =
data, err := json.Marshal(age)
if err != nil {
fmt.Printf("json.marshal failed, err:", err)
return
} fmt.Printf("%s\n", string(data))
} func testMap() {
var m map[string]interface{}
m = make(map[string]interface{})
m["username"] = "user1"
m["age"] =
m["sex"] = "man" data, err := json.Marshal(m)
if err != nil {
fmt.Printf("json.marshal failed, err:", err)
return
} fmt.Printf("%s\n", string(data))
} func testSlice() {
var m map[string]interface{}
var s []map[string]interface{}
m = make(map[string]interface{})
m["username"] = "user1"
m["age"] =
m["sex"] = "man" s = append(s, m) m = make(map[string]interface{})
m["username"] = "user2"
m["age"] =
m["sex"] = "female"
s = append(s, m) data, err := json.Marshal(s)
if err != nil {
fmt.Printf("json.marshal failed, err:", err)
return
} //[{"age":18,"sex":"man","username":"user1"},{"age":29,"sex":"female","username":"user2"}]
fmt.Printf("%s\n", string(data))
} func main() {
//testStruct()
//testInt()
//testMap()
testSlice()
}

序列化结构体

练习:json序列化map

 package main

 import (
"encoding/json"
"fmt"
) type User struct {
UserName string `json:"username"`
NickName string `json:"nickname"`
Age int
Birthday string
Sex string
Email string
Phone string
} func testStruct() (ret string, err error) {
user1 := &User{
UserName: "user1",
NickName: "上课看似",
Age: ,
Birthday: "2008/8/8",
Sex: "男",
Email: "mahuateng@qq.com",
Phone: "",
} data, err := json.Marshal(user1)
if err != nil {
err = fmt.Errorf("json.marshal failed, err:", err)
return
} ret = string(data)
return
} func testMap() (ret string, err error) {
var m map[string]interface{}
m = make(map[string]interface{})
m["username"] = "user1"
m["age"] =
m["sex"] = "man" data, err := json.Marshal(m)
if err != nil {
err = fmt.Errorf("json.marshal failed, err:", err)
return
} ret = string(data)
return
} func test2() {
data, err := testMap()
if err != nil {
fmt.Println("test map failed, ", err)
return
} var m map[string]interface{}
err = json.Unmarshal([]byte(data), &m)
if err != nil {
fmt.Println("Unmarshal failed, ", err)
return
}
fmt.Println(m)
} func test() {
data, err := testStruct()
if err != nil {
fmt.Println("test struct failed, ", err)
return
} var user1 User
err = json.Unmarshal([]byte(data), &user1)
if err != nil {
fmt.Println("Unmarshal failed, ", err)
return
}
fmt.Println(user1)
} func main() {
test()
test2()
}

序列化map

5. 自定义错误

type error interface {
Error() string
}
 package main

 import (
"errors"
"fmt"
) var errNotFound error = errors.New("Not found error") func main() {
fmt.Printf("error: %v", errNotFound)
}

example

 package main
import (
"fmt"
)
type PathError struct {
Op string
Path string
Err string
} func (e *PathError) Error() string {
return e.Op + " " + e.Path + ": " + e.Err
} func test() error {
return &PathError{
Op: "op",
Path: "path",
Err: "err",
}
}
func main() {
if err := test(); err != nil {
fmt.Println(err) //op path: err
}
}

自定义错误

如何判断自定义错误?

switch err := err.(type) {
case ParseError:
PrintParseError(err)
case PathError:
PrintPathError(err)
default:
...
}
 package main

 import (
"fmt"
"os"
"time"
) type PathError struct {
path string
op string
createTime string
message string
} func (p *PathError) Error() string {
return fmt.Sprintf("path=%s op=%s createTime=%s message=%s", p.path,
p.op, p.createTime, p.message)
} func Open(filename string) error {
file, err := os.Open(filename)
if err != nil {
return &PathError{
path: filename,
op: "read",
message: err.Error(), //注意这块的Error是系统的error定义的接口Error()
createTime: fmt.Sprintf("%v", time.Now()),
}
} defer file.Close()
return nil
} func main() {
err := Open("C:/sdklflakfljdsafjs.txt")
switch v := err.(type) {
case *PathError:
fmt.Println("get path error,", v) //v.Error() 类似于打印fmt.Println(err),其实内部实现fmt.Println(err.Error())
default: } }

自定义错误

Panic&Recover

 package main

 import (
"fmt"
) func badCall() {
panic("bad end")
} func test() {
defer func() {
if e := recover(); e != nil { //在这块通过recover捕获panic错误并处理
fmt.Printf("Panicking %s\r\n", e)
}
}() badCall()
fmt.Printf("After bad call\r\n")
} func main() {
fmt.Printf("Calling test\r\n")
test()
fmt.Printf("Test completed\r\n")
}

recover捕获panic错误

图书管理系统v3:
    实现一个图书管理系统v3,具有以下功能:
     a. 增加持久化存储的功能
     b. 增加日志记录的功能

参考文献:

  • https://studygolang.com/articles/14669

最新文章

  1. Set up VLAN (802.1q) tagging on a network interface?
  2. WPF的ComboBox 数据模板自定义
  3. Ubuntu 12.04 安装 Chrome浏览器
  4. PLSQL_性能优化系列11_Oracle Bulk Collect批处理
  5. 高达渐出现效果Shader
  6. Recommender Systems基于内容的推荐
  7. ios开发中button控件的属性及常见问题
  8. NDK开发之ndk-build命令详解
  9. HDU 3068 最长回文 【最长回文子串】
  10. Cocos2dx使用网络图片
  11. 二分 Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) D
  12. BZOJ1119[POI2009]SLO &amp;&amp; BZOJ1697[Usaco2007 Feb]Cow Sorting牛排序
  13. iOS 手机摇一摇功能
  14. Chrome调试工具developer tool技巧
  15. Oracle总结第一篇【基本SQL操作】
  16. 关于sping quartz定时执行理解与思考
  17. 画流程图挺好的软件---visio
  18. Excel自动建组
  19. 【做题】51Nod1766树上的最远点对——直径&amp;线段树
  20. RabbitMQ python模块pika生产者消费者轮询模型。

热门文章

  1. 支持图片上传预览的 uploadPreview.js 插件
  2. kaggle竞赛_mnist_10%
  3. Codeforces 817C Really Big Numbers - 二分法 - 数论
  4. Win10子系统Ubuntu安装llvm+clang
  5. JS获取节点的兄弟,父级,子级元素
  6. 题解——loj6279 数列分块入门3 (分块)
  7. C++笔记(2018/2/7)
  8. Qt实在太漂亮了
  9. layui upload 后台获取不到值
  10. SqlParameter 多个参数动态拼接解决参数化问题