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的对象,一般情况下用如下方法实 ...
随机推荐
- BootstrapTable(附源码)
Bootstrap结合BootstrapTable的使用,分为两种模试显示列表. 引用的css: <link href="@Url.Content("~/Css/bootst ...
- 学习MFC的建议
1.继续深入学习C++的内容,打好面向对象的程序综合设计与编程基础,参考书籍<C++Primer>. 2.打好Windows编程基础(参考书<Windows程序设计>(第五版) ...
- tr 命令用法
tr a. 替换全部字符 [root@bogon scripts]# tr [a-z] [A-Z] < /etc/fstab 将读出的结果全部替换成大写字母 (取一行作为展示效果) ...
- iOS 允许后台任务吗?
个人整理 1,用户层: 低电量模式 App后台数据刷新 的开关会影响App后台运行 2, 10分钟时间 后台任务: 在AppDelegate中加入以下代码:不受1影响 - (void)applic ...
- An error occurred (500 Error)
Centos7 部署知乎出现上图问题 解决方法: [root@web02 ~]# vim /etc/php.ini #修改配置文件 session.auto_start = 0 #这条设置成0 [ro ...
- selinux权限问题【转】
本文转载自:https://blog.csdn.net/u011386173/article/details/83339770 版权声明:本文为博主原创文章,未经博主允许不得转载. https://b ...
- 常用linux,DOS命令——持续更新
cd 文件夹名 进入某个文件夹 cd ../ 退出该级目录进入上一级 cd ../../ 退出该级目录进入上上级 cd ../../demo 退出该级目录进入上上级的目录 d: 回车 进入d盘 ls ...
- Transaction2
5. 事务状态 TransactionInformation 上面讲解过事务分为本地事务与分布式事务,而Transaction类的TransactionInformation是事务状态的记录,它可以跟 ...
- pom.xml中build标签
1.分类 (1)全局配置(project build) 针对整个项目的所有情况都有效 (2)配置(profile build) 针对不同的profile配置 <project xmlns=&qu ...
- 转入Python3.5
Future 我决定从python2.7转到python3.5,毕竟python3才是未来,业余程序员也是有追求的 嵌入发布 版本3.5中的新特性.可以将python嵌入用户程序,变成程序的一部分,随 ...