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的对象,一般情况下用如下方法实 ...
随机推荐
- libvirt的security
1. libvirt支持SASL authentication and encryption MD5 hashes are considered unsafe and should not be us ...
- 如何在Windows中通过Cygwin来使用Linux命令行
PowerShell的出现让Windows的命令行工具有了很大的改进.但是多年以来,Linux一直拥有很多有用的终端.在这里通过Cygwin你可以同时拥有上面两种命令行工具,Cygwin是一个可以在W ...
- zynq基础-->linux下软件应用
操作系统:Ubuntu 16.04 LTS 应用软件:Vivado 2016.2 + petalinux 2016.2 参考官方应用手册:ug1144-petalinux-tools-referen ...
- 【Python020--内嵌函数和闭包】
一.内嵌函数&闭包 1.最好是访问全局变量而不是修改全局变量,修改全局变量Python会内部屏蔽(修改后,函数会内部创建一个和全局变量一抹一样的变量) >>> count = ...
- Node.js实践
在 iOS 模拟器中调试 Web 页面 safari调试iOS App web 1, npm init 2, npm install ejs --save 简单Node 指令 $ node -v / ...
- 探究is与==的区别
1.is 和 ==的区别: 主要参考内存地址: 部分字符串和数字有固定的小数据池: 比如: a="abc" a1="abc" print(id(a),id(a ...
- H5、React Native、Native性能区别选择
“存在即合理”.凡是存在的,都是合乎规律的.任何新事物的产生总要的它的道理:任何新事物的发展总是有着取代旧事物的能力.React Native来的正是时候,一则是因为H5发展到一定程度的受限:二则是移 ...
- Markdon 作图语法 CSDN
插入甘特图 gantt dateFormat YYYY-MM-DD title Adding GANTT diagram functionality to mermaid section 现有任务 已 ...
- ZOJ 3593 One Person Game(ExGcd + 最优解)题解
思路:题意转化为求 (ax+by=dis) || (ax+cy=dis) || (bx+cy=dis) 三个式子有解时的最小|x| + |y|.显然求解特解x,y直接用扩展欧几里得,那么怎么求|x| ...
- Windows,远程计算机:X.X.X.X,这可能是由于CredSSP加密Oracle修正
https://blog.csdn.net/wyhwlls/article/details/80320301 近期window 10家庭版更新后,远程桌面连不到服务器了 网上有卸载补丁,修改组策略什么 ...