Go语言学习之7 接口实例、终端文件读写、异常处理
本节主要内容:
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
Go语言学习之7 接口实例、终端文件读写、异常处理的更多相关文章
- 51单片机C语言学习笔记7:关于.c文件和.h文件
1)h文件作用 1 方便开发:包含一些文件需要的共同的常量,结构,类型定义,函数,变量申明: 2 提供接口:对一个软件包来说可以提供一个给外界的接口(例如: stdio.h). 2)h文件里应该有什么 ...
- Python学习(九)IO 编程 —— 文件读写
Python 文件读写 Python内置了读写文件的函数,用法和C是兼容的.本节介绍内容大致有:文件的打开/关闭.文件对象.文件的读写等. 本章节仅示例介绍 TXT 类型文档的读写,也就是最基础的文件 ...
- android菜鸟学习笔记17----Android数据存储(一)文件读写
假如有如下需求,要求能够记录用户输入的用户名和密码,下次登录时,能直接获取之前保存的用户名密码,并在相应的EditText中显示. 要保存用户输入的数据,最先想到的应该就是文件读写了. 通过对andr ...
- 【python系统学习17】python中的文件读写
python中的文件读写 文件读写,是Python代码调用电脑文件的主要功能,能被用于读取和写入文本.音频片段.Excel文档.邮件以及任何保存在电脑上的东西. 可使用python批量的操作本地文件, ...
- Go语言学习笔记(9)——接口类型
接口 Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口. /* 定义接口 */ type interface_name in ...
- 吴裕雄--天生自然C++语言学习笔记:C++ 实例
C++ 实例 - 输出 "Hello, World!" #include <iostream> using namespace std; int main() { co ...
- AT&T汇编语言学习:利用c库、文件读写
AT&T汇编.调用C库函数.读/写文件 d0321:更新读文件代码(图片)以后会更新代码版. d0329:汇编文本读取.简单动画. ============================== ...
- 【原创】go语言学习(十六)接口
目录 接口介绍与定义 空接口和类型断言 指针接收和值接收区别 接口嵌套 接口介绍与定义 1. 接口定义了一个对象的行为规范 A. 只定义规范,不实现B. 具体的对象需要实现规范的细节 2.Go中接口定 ...
- python学习笔记:接口开发——flask Demo实例
举例1,返回当前时间接口 ''' 初始化:所有的Flask都必须创建程序实例, web服务器使用wsgi协议,把客户端所有的请求都转发给这个程序实例 程序实例是Flask的对象,一般情况下用如下方法实 ...
随机推荐
- [BeiJing wc2012]冻结 题解
HYSBZ - 2662 这个题如果我们先想用平常的方法来建图,因为我们无法确定是否使用卡片,如果我们每个点每个边都建图,那么非常耗时占空间:注意到k是比较小的,所以我们可以把k拆开,把一个点分为k个 ...
- win10 实现 iPad AVplayer 搭建 ftp 共享 PC 端
1.首先是 iPad 端直接去 App Store 下载 AVplayer 即可,我下载的时候这个APP收费 18 元.这个app内置了加速播放视频的功能,非常适合学习时使用. 2.PC 端搭建 ft ...
- 1. 元信息:Meta类 2. 基于对象查询的sql优化 3. 自定义:Group_Concat() 4. ajax前后台交互
一.元信息 ''' 1. 元信息 1. Model类可以通过元信息类设置索引和排序信息 2. 元信息是在Model类中定义一个Meta子类 class Meta: # 自定义表名 db_table = ...
- 【python003-变量】
变量 一.在使用变量之前,需要先对其进行赋值 二.变量命名的规则:可以包含字母,数字,下划线,但是不能以数字开头 三.字符串: 1.引号内的一切东西 2.python的字符串是要在两边加上引号,对于单 ...
- 1-1.flutter学习笔记(一)git入门(msysgit图文安装)
1.下载git-for-windows (1)常用的GitHub客户端msysgit,也就是git-for-windows. (2)登录官网 https://git-for-windows.githu ...
- debian下如何源码安装tmux
一.源码安装ncurses库 1.1 获取源码 wget https://invisible-island.net/datafiles/release/ncurses.tar.gz tar xvf n ...
- Newcoder 华华给月月出题(线筛)题解
题目描述: 华华刚刚帮月月完成了作业.为了展示自己的学习水平之高超,华华还给月月出了一道类似的题: Ans=⊕Ni=1(iNmod(109+7))Ans=⊕i=1N(iNmod(109+7)) ⊕⊕符 ...
- newcoder F石头剪刀布(DFS + 思维)题解
题意:wzms 今年举办了一场剪刀石头布大赛,bleaves 被选为负责人. 比赛共有 2n 个人参加, 分为 n 轮, 在每轮中,第 1 位选手和第 2 位选手对战,胜者作为新的第 1 位选手, 第 ...
- 【注册码】Matlab7.0(R14)注册码
Matlab 7 (R14) 注册码1:14-13299-56369-16360-32789-51027-35530-39910-50517-56079-43171-43696-14148-64597 ...
- [JavaScript] - 判断时间是否是当天
https://www.codewars.com/kata/is-the-date-today/train/javascript function isToday(date) { return new ...