zoukankan      html  css  js  c++  java
  • Go语言学习之7 接口实例、终端文件读写、异常处理

    本节主要内容:

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

    1. 终端读写

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

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 var (
     8     firstName, lastName, s string
     9     i                      int
    10     f                      float32
    11     input                  = "56.12 / 5212 / Go"
    12     format                = "%f / %d / %s"
    13 )
    14 
    15 func main() {
    16     fmt.Println("Please enter your full name: ") //Chris Naegels
    17     fmt.Scanln(&firstName, &lastName) //和下面等价
    18     // fmt.Scanf("%s %s", &firstName, &lastName)
    19     fmt.Printf("Hi %s %s!
    ", firstName, lastName) // Hi Chris Naegels!
    20     fmt.Sscanf(input, format, &f, &i, &s)
    21     fmt.Println("From the string we read: ", f, i, s) //From the string we read:  56.12 5212 Go
    22 }
    example
     1 package main 
     2 
     3 import (
     4     "bufio"
     5     "fmt"
     6     "os"
     7 )
     8 
     9 func main() {
    10     fmt.Println("Input string >>")
    11     reader := bufio.NewReader(os.Stdin)
    12     res, err := reader.ReadString('
    ')
    13     if err != nil {
    14         fmt.Println("Read failed, Error: ", err)
    15     }
    16     fmt.Printf("Read success, content: ", res)
    17 }
    从终端读入
     1 package main 
     2 
     3 import (
     4     "fmt"
     5     "os"
     6     "bufio"
     7 )
     8 
     9 func main() {
    10     // fmt.Fprintf(os.Stdout, "%s
    ", "hello world")
    11 
    12     buf := bufio.NewWriter(os.Stdout)
    13     fmt.Fprintf(buf, "%s
    ", "hello world")
    14     buf.Flush()
    15 }
    带缓冲区的终端读写

    2. 文件读写

       (1)文件读取

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

     1 package main 
     2 
     3 import (
     4     "os"
     5     "fmt"
     6     "bufio"
     7 )
     8 
     9 func main() {
    10     var input *bufio.Reader
    11     var str string
    12     var err error
    13 
    14     input = bufio.NewReader(os.Stdin)
    15     str, err = input.ReadString('
    ') //注意:ReadString会返回读取的字符串(包括分隔符'
    ')
    16     if err != nil {
    17         fmt.Println("Read failed")
    18     }
    19     fmt.Println("Read success, content: ", str)
    20 }
    example

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

     1 package main 
     2 
     3 import (
     4     "fmt"
     5     "os"
     6     "bufio"
     7     "strings"
     8 )
     9 
    10 type CharCount struct {
    11     ChCount int
    12     NumCount int
    13     SpaceCount int
    14     OtherCount int
    15 }
    16 
    17 func Count(str string, cc *CharCount) {
    18     runeArr := []rune(str)
    19     for _, v := range runeArr {
    20         fmt.Printf("--%v
    ",v)
    21         switch {
    22         case v >= 'A' && v <= 'Z':
    23             fallthrough
    24         case v >= 'a' && v <= 'z':
    25             cc.ChCount++
    26         case v >= '0' && v <= '9':
    27             cc.NumCount++
    28         case v == ' ':
    29             cc.SpaceCount++
    30         default:
    31             cc.OtherCount++
    32         }
    33     }
    34 }
    35 
    36 func main() {
    37     var cc CharCount
    38 
    39     fmt.Println("Input string >>")
    40     reader := bufio.NewReader(os.Stdin)
    41     str, err := reader.ReadString('
    ')
    42     if err != nil {
    43         fmt.Println("Read failed")
    44     }
    45 
    46     str = strings.Trim(string(str), "
    ") //去掉末尾的
    ,否则OtherCount会多加2
    47 
    48     Count(string(str), &cc)
    49     fmt.Println(cc)
    50 }
    从terminal读取

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

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

     1 package main
     2 
     3 import (
     4     "fmt"
     5     "io/ioutil"
     6 )
     7 
     8 func main() {
     9     fileName := "F:\Go\project\src\go_dev\day7\test.txt"
    10     data, err := ioutil.ReadFile(fileName)
    11     if err != nil {
    12     fmt.Println("File reading error", err)
    13     return
    14     }
    15     fmt.Println("Contents of file: ", string(data))
    16 }
    读取整个文件

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

     1 package main
     2 
     3 import (
     4     "bufio"
     5     "fmt"
     6     "log"
     7     "os"
     8     "io"
     9 )
    10 
    11 func EmptyArray(arr []byte) {
    12     for i := 0; i < len(arr); i++ {
    13         arr[i] = 0
    14     }
    15 }
    16 
    17 func main() {
    18     fileName := "F:\Go\project\src\go_dev\day7\test.txt"
    19 
    20     f, err := os.Open(fileName)
    21     if err != nil {
    22         log.Fatal(err)
    23     }
    24 
    25     defer func() {
    26         if err = f.Close(); err != nil {
    27             log.Fatal(err)
    28         }
    29     }()
    30 
    31     var str string
    32     r := bufio.NewReader(f)
    33     b := make([]byte, 3)  //每次读取3个字节
    34 
    35     for {
    36         EmptyArray(b)
    37 
    38         _, err := r.Read(b)
    39         if err == io.EOF {
    40             fmt.Println("Read finish")
    41             break
    42         }
    43 
    44         if err != nil {
    45             fmt.Println("Error reading file: ", err)
    46             break
    47         }
    48         str = string(b)
    49         fmt.Printf("%s", str)
    50     }
    51 }
    分块读取

        3)逐行读取文件

     1 package main
     2 
     3 import (
     4     "bufio"
     5     "fmt"
     6     "log"
     7     "os"
     8 )
     9 
    10 func main() {
    11     fileName := "F:\Go\project\src\go_dev\day7\test.txt"
    12 
    13     f, err := os.Open(fileName)
    14     if err != nil {
    15         log.Fatal(err)
    16     }
    17 
    18     defer func() {
    19         if err = f.Close(); err != nil {
    20         log.Fatal(err)
    21     }
    22     }()
    23 
    24     s := bufio.NewScanner(f)
    25     for s.Scan() {
    26         fmt.Println(s.Text())
    27     }
    28     
    29     if err = s.Err(); err != nil {
    30         log.Fatal(err)
    31     }
    32 }
    逐行读取

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

     1 package main
     2 
     3 // 引入所需包
     4 import (
     5     "os"
     6     "compress/gzip"
     7     "io/ioutil"
     8     "fmt"
     9 )
    10 
    11 // gzip文件
    12 
    13 
    14 func main() {
    15     fileName := "F:\Go\project\src\go_dev\day7\test.zip"
    16     // 打开本地gz格式压缩包
    17     fr, err := os.Open(fileName)
    18     if err != nil {
    19         panic(err)
    20     } else {
    21         println("open file success!")
    22     }
    23 
    24     // defer: 在函数退出时,执行关闭文件
    25     defer fr.Close()
    26 
    27     // 创建gzip文件读取对象
    28     gr, err := gzip.NewReader(fr)
    29     if err != nil {
    30             panic(err)
    31         }
    32 
    33     // defer: 在函数退出时,执行关闭gzip对象
    34     defer gr.Close()
    35 
    36     // 读取gzip对象内容
    37     rBuf, err := ioutil.ReadAll(gr)
    38     if err != nil {
    39         fmt.Println("[read gzip data err]: ", err)
    40     }
    41 
    42     // 以文本形式输出
    43     fmt.Printf("%s
    ", rBuf)
    44 }
    读取压缩文件示例

       (2)文件写入

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

    第二个参数:文件打开模式:
    1. os.O_WRONLY:只写
    2. os.O_CREATE:创建文件
    3. os.O_RDONLY:只读
    4. os.O_RDWR:读写
    5. os.O_TRUNC :清空
    第三个参数:权限控制:
    r ——> 004
    w ——> 002
    x ——> 001
     1 package main 
     2 
     3 import (
     4     "fmt"
     5     "os"
     6     "bufio"
     7 )
     8 
     9 func main() {
    10     filePath := "F:\Go\project\src\go_dev\day7\write_test.txt"
    11     outFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
    12     if err != nil {
    13         fmt.Println("Failed to write file")
    14         return
    15     }
    16     defer outFile.Close()
    17 
    18     outWrite := bufio.NewWriter(outFile)
    19     des := "hello world!
    "
    20     for i := 0; i < 10; i++ {
    21         outWrite.WriteString(des)
    22     }
    23     outWrite.Flush()
    24 }
    example

        (3)拷贝文件

     1 package main 
     2 
     3 import (
     4     "fmt"
     5     "os"
     6     "io"
     7 )
     8 
     9 //A successful Copy returns err == nil, not err == EOF
    10 func CopyFile(destName, srcName string) (written int64, err error) {
    11     src, err := os.Open(srcName)
    12     if err != nil {
    13         panic(err)
    14     }
    15     defer src.Close()
    16 
    17     dest, err := os.OpenFile(destName, os.O_WRONLY|os.O_CREATE, 0666)
    18     if err != nil {
    19         panic(err)
    20     }
    21     defer dest.Close()
    22 
    23     return io.Copy(dest, src)
    24 }
    25 
    26 func main() {
    27     srcName := "F:\Go\project\src\go_dev\day7\write_test.txt"
    28     destName := "F:\Go\project\src\go_dev\day7\dest_test.txt"
    29 
    30     wByte, err := CopyFile(destName, srcName)
    31     if err != nil {
    32         fmt.Println("Copy failed")
    33     } else {
    34         fmt.Printf("Copy %d byte from src to dest
    ", wByte)
    35     }
    36 }
    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", 1001, "print on newline")
     1 package main
     2 
     3 import (
     4     "fmt"
     5     "os"
     6 )
     7 
     8 func main() {
     9     fmt.Printf("len of args:%d
    ", len(os.Args))
    10     for i, v := range os.Args {
    11         fmt.Printf("args[%d]=%s
    ", i, v)
    12     }
    13 }
    14 
    15 //输入:
    16 //go run main7.go hello world
    17 // 输出:
    18 // len of args:3
    19 // args[0]=C:UsersADMINI~1AppDataLocalTempgo-build596136718command-line-argu
    20 // ments\_objexemain7.exe
    21 // args[1]=hello
    22 // args[2]=world
    example
     1 package main
     2 
     3 import (
     4     "fmt"
     5     "flag"
     6 )
     7 
     8 func main() {
     9     var configPath string
    10     var logLevel int
    11 
    12     flag.StringVar(&configPath, "c", "", "Please config path")
    13     flag.IntVar(&logLevel, "d", 10, "Please log level")
    14 
    15     flag.Parse()
    16 
    17     fmt.Println("configPath: ", configPath)
    18     fmt.Println("logLevel: ", logLevel)
    19 }
    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序列化结构体

     1 package main
     2 
     3 import (
     4     "encoding/json"
     5     "fmt"
     6 )
     7 
     8 type User struct {
     9     UserName string `json:"username"`
    10     NickName string `json:"nickname"`
    11     Age      int
    12     Birthday string
    13     Sex      string
    14     Email    string
    15     Phone    string
    16 }
    17 
    18 func testStruct() {
    19     user1 := &User{
    20         UserName: "user1",
    21         NickName: "上课看似",
    22         Age:      18,
    23         Birthday: "2008/8/8",
    24         Sex:      "",
    25         Email:    "mahuateng@qq.com",
    26         Phone:    "110",
    27     }
    28 
    29     data, err := json.Marshal(user1)
    30     if err != nil {
    31         fmt.Printf("json.marshal failed, err:", err)
    32         return
    33     }
    34 
    35     fmt.Printf("%s
    ", string(data))
    36 }
    37 
    38 func testInt() {
    39     var age = 100
    40     data, err := json.Marshal(age)
    41     if err != nil {
    42         fmt.Printf("json.marshal failed, err:", err)
    43         return
    44     }
    45 
    46     fmt.Printf("%s
    ", string(data))
    47 }
    48 
    49 func testMap() {
    50     var m map[string]interface{}
    51     m = make(map[string]interface{})
    52     m["username"] = "user1"
    53     m["age"] = 18
    54     m["sex"] = "man"
    55 
    56     data, err := json.Marshal(m)
    57     if err != nil {
    58         fmt.Printf("json.marshal failed, err:", err)
    59         return
    60     }
    61 
    62     fmt.Printf("%s
    ", string(data))
    63 }
    64 
    65 func testSlice() {
    66     var m map[string]interface{}
    67     var s []map[string]interface{}
    68     m = make(map[string]interface{})
    69     m["username"] = "user1"
    70     m["age"] = 18
    71     m["sex"] = "man"
    72 
    73     s = append(s, m)
    74 
    75     m = make(map[string]interface{})
    76     m["username"] = "user2"
    77     m["age"] = 29
    78     m["sex"] = "female"
    79     s = append(s, m)
    80 
    81     data, err := json.Marshal(s)
    82     if err != nil {
    83         fmt.Printf("json.marshal failed, err:", err)
    84         return
    85     }
    86 
    87     //[{"age":18,"sex":"man","username":"user1"},{"age":29,"sex":"female","username":"user2"}]
    88     fmt.Printf("%s
    ", string(data))
    89 }
    90 
    91 func main() {
    92     //testStruct()
    93     //testInt()
    94     //testMap()
    95     testSlice()
    96 }
    序列化结构体

    练习:json序列化map

     1 package main
     2 
     3 import (
     4     "encoding/json"
     5     "fmt"
     6 )
     7 
     8 type User struct {
     9     UserName string `json:"username"`
    10     NickName string `json:"nickname"`
    11     Age      int
    12     Birthday string
    13     Sex      string
    14     Email    string
    15     Phone    string
    16 }
    17 
    18 func testStruct() (ret string, err error) {
    19     user1 := &User{
    20         UserName: "user1",
    21         NickName: "上课看似",
    22         Age:      18,
    23         Birthday: "2008/8/8",
    24         Sex:      "",
    25         Email:    "mahuateng@qq.com",
    26         Phone:    "110",
    27     }
    28 
    29     data, err := json.Marshal(user1)
    30     if err != nil {
    31         err = fmt.Errorf("json.marshal failed, err:", err)
    32         return
    33     }
    34 
    35     ret = string(data)
    36     return
    37 }
    38 
    39 func testMap() (ret string, err error) {
    40     var m map[string]interface{}
    41     m = make(map[string]interface{})
    42     m["username"] = "user1"
    43     m["age"] = 18
    44     m["sex"] = "man"
    45 
    46     data, err := json.Marshal(m)
    47     if err != nil {
    48         err = fmt.Errorf("json.marshal failed, err:", err)
    49         return
    50     }
    51 
    52     ret = string(data)
    53     return
    54 }
    55 
    56 func test2() {
    57     data, err := testMap()
    58     if err != nil {
    59         fmt.Println("test map failed, ", err)
    60         return
    61     }
    62 
    63     var m map[string]interface{}
    64     err = json.Unmarshal([]byte(data), &m)
    65     if err != nil {
    66         fmt.Println("Unmarshal failed, ", err)
    67         return
    68     }
    69     fmt.Println(m)
    70 }
    71 
    72 func test() {
    73     data, err := testStruct()
    74     if err != nil {
    75         fmt.Println("test struct failed, ", err)
    76         return
    77     }
    78 
    79     var user1 User
    80     err = json.Unmarshal([]byte(data), &user1)
    81     if err != nil {
    82         fmt.Println("Unmarshal failed, ", err)
    83         return
    84     }
    85     fmt.Println(user1)
    86 }
    87 
    88 func main() {
    89     test()
    90     test2()
    91 }
    序列化map

    5. 自定义错误

    type error interface { 
         Error() string 
    } 
     1 package main
     2 
     3 import (
     4     "errors"
     5     "fmt"
     6 )
     7 
     8 var errNotFound error = errors.New("Not found error")
     9 
    10 func main() {
    11     fmt.Printf("error: %v", errNotFound)
    12 }
    example
     1 package main
     2 import (
     3     "fmt"
     4 )
     5 type PathError struct {
     6     Op   string
     7     Path string
     8     Err string
     9 }
    10 
    11 func (e *PathError) Error() string {
    12     return e.Op + " " + e.Path + ": " + e.Err
    13 }
    14 
    15 func test() error {
    16     return &PathError{
    17         Op:   "op",
    18         Path: "path",
    19         Err:  "err",
    20     }
    21 }
    22 func main() {
    23     if err := test(); err != nil {
    24         fmt.Println(err)  //op path: err
    25     }
    26 }
    自定义错误

    如何判断自定义错误?

    switch err := err.(type) {
        case ParseError:
            PrintParseError(err)
        case PathError:
            PrintPathError(err)
        default: 
    ... }
     1 package main
     2 
     3 import (
     4     "fmt"
     5     "os"
     6     "time"
     7 )
     8 
     9 type PathError struct {
    10     path       string
    11     op         string
    12     createTime string
    13     message    string
    14 }
    15 
    16 func (p *PathError) Error() string {
    17     return fmt.Sprintf("path=%s op=%s createTime=%s message=%s", p.path,
    18         p.op, p.createTime, p.message)
    19 }
    20 
    21 func Open(filename string) error {
    22     file, err := os.Open(filename)
    23     if err != nil {
    24         return &PathError{
    25             path:       filename,
    26             op:         "read",
    27             message:    err.Error(), //注意这块的Error是系统的error定义的接口Error()
    28             createTime: fmt.Sprintf("%v", time.Now()),
    29         }
    30     }
    31 
    32     defer file.Close()
    33     return nil
    34 }
    35 
    36 func main() {
    37     err := Open("C:/sdklflakfljdsafjs.txt")
    38     switch v := err.(type) {
    39     case *PathError:
    40         fmt.Println("get path error,", v) //v.Error() 类似于打印fmt.Println(err),其实内部实现fmt.Println(err.Error())
    41     default:
    42 
    43     }
    44 
    45 }
    自定义错误

    Panic&Recover

     1 package main
     2 
     3 import (
     4     "fmt"
     5 )
     6 
     7 func badCall() {
     8     panic("bad end")
     9 }
    10 
    11 func test() {
    12     defer func() {
    13         if e := recover(); e != nil { //在这块通过recover捕获panic错误并处理
    14             fmt.Printf("Panicking %s
    ", e)
    15         }
    16     }()
    17 
    18     badCall()
    19     fmt.Printf("After bad call
    ")
    20 }
    21 
    22 func main() {
    23     fmt.Printf("Calling test
    ")
    24     test()
    25     fmt.Printf("Test completed
    ")
    26 }
    recover捕获panic错误

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

    参考文献:

    • https://studygolang.com/articles/14669
  • 相关阅读:
    SQL注入详解7
    第3章 ES文档和故障处理
    SQL注入详解6
    第7章 处理串行线路和帧中继连接故障
    SQL注入详解2
    第5章 Cisco测试命令和TCP/IP连接故障处理
    cmd执行sql
    初探Android程序框架PhoneGap
    AlertDialog中的样式设置
    json对象的多个json对象的循环读取
  • 原文地址:https://www.cnblogs.com/xuejiale/p/10410183.html
Copyright © 2011-2022 走看看