go语言之行--文件操作、命令行参数、序列化与反序列化详解

前端之家收集整理的这篇文章主要介绍了go语言之行--文件操作、命令行参数、序列化与反序列化详解前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

一、简介

文件操作对于我们来说也是非常常用的,在python中使用open函数来对文件进行操作,而在go语言中我们使用os.File对文件进行操作。

二、终端读写

操作终端句柄常量

os.Stdin: 标准输入

os.Stdout: 标准输出

os.Stderr: 标准错误输出

读写示例:

import (
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">os<span style="color: #800000;">"<span style="color: #000000;">
)

<span style="color: #0000ff;">var<span style="color: #000000;">(
username,password <span style="color: #0000ff;">string<span style="color: #000000;">
)

func main() {
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">请输入用户名:<span style="color: #800000;">"<span style="color: #000000;">)
fmt.Scanf(<span style="color: #800000;">"<span style="color: #800000;">%s<span style="color: #800000;">",&username) <span style="color: #008000;">//<span style="color: #008000;"> 键盘输入
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">请输入密码:<span style="color: #800000;">"<span style="color: #000000;">)
fmt.Scanf(<span style="color: #800000;">"<span style="color: #800000;">%s<span style="color: #800000;">",&<span style="color: #000000;">password)
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">username:%s password:%s\n<span style="color: #800000;">"<span style="color: #000000;">,username,password)
<span style="color: #0000ff;">var msg [<span style="color: #800080;">5]<span style="color: #0000ff;">byte<span style="color: #000000;">
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">请输入名称:<span style="color: #800000;">"<span style="color: #000000;">)
n,err :=<span style="color: #000000;"> os.Stdin.Read(msg[:])
<span style="color: #0000ff;">if err ==<span style="color: #000000;"> nil {
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">len: %d,msg : %s<span style="color: #800000;">"<span style="color: #000000;">,n,msg[:])
<span style="color: #0000ff;">return<span style="color: #000000;">
}
}
<span style="color: #008000;">//<span style="color: #008000;">请输入用户名
<span style="color: #008000;">//<span style="color: #008000;">wd
<span style="color: #008000;">//<span style="color: #008000;">请输入密码:
<span style="color: #008000;">//<span style="color: #008000;">123
<span style="color: #008000;">//<span style="color: #008000;">username:wd password:123
<span style="color: #008000;">//<span style="color: #008000;">请输入名称
<span style="color: #008000;">//<span style="color: #008000;">ad
<span style="color: #008000;">//<span style="color: #008000;">len: 3,msg : ad

三、文件操作

os.File是一个结构体,其封装了诸多操作文件方法

func Create(name ) (*File,error) 文件,如果文件已存在会截断它(为空文件)。如果成功,返回的文件对象可用于I/O;对应的文件描述符具有O_RDWR模式。如果出错,错误底层类型是*PathError。 func NewFile(fd uintptr,name ) *File 文件描述符和名称创建一个文件 func Open(name ) (*File,error) 文件用于读取。如果操作成功,返回的文件对象的方法可用于读取数据;对应的文件描述符具有O_RDONLY模式。如果出错,错误底层类型是*PathError。 func OpenFile(name ,flag ,perm FileMode) (*File,error) 文件打开函数,大多数调用者都应用Open或Create代替本函数。它会使用指定的选项(如O_RDONLY等)、指定的模式(如0666等)打开指定名称文件。如果操作成功,返回的文件对象可用于I/O。如果出错,错误底层类型是*PathError。 func Pipe() (r *File,w *File,err error) 文件对象。从r的读取将返回写入w的数据。本函数会返回两个文件对象和可能的错误 func (f *File) Chdir() error 修改为f,f必须是一个目录。如果出错,错误底层类型是*PathError。 func (f *File) Chmod(mode FileMode) error 修改文件权限。如果出错,错误底层类型是*PathError。 func (f *File) Chown(uid,gid ) error 修改文件文件用户id和组id func (f *File) Close() error 关闭文件f,使文件不能用于读写。它返回可能出现的错误 func (f *File) Fd() uintptr 文件f对应的整数类型的Unix文件描述符。 func (f *File) Name() 方法返回(提供给Open/Create等方法的)文件名称 func (f *File) Read(b []) (n ,err error) 方法从f中读取最多len(b)字节数据并写入b。它返回读取的字节数和可能遇到的任何错误文件终止标志是读取0个字节且返回值err为io.EOF。 func (f *File) ReadAt(b [],off int64) (n ,err error) 文件开始位置)读取len(b)字节数据并写入b。它返回读取的字节数和可能遇到的任何错误。当n方法总是会返回错误;如果是因为到达文件结尾,返回值err会是io.EOF。 func (f *File) Readdir(n ) ([]FileInfo,error) 内容,返回一个有n个成员的[]FileInfo,这些FileInfo是被Lstat返回的,采用目录顺序。对本函数的下一次调用会返回上一次调用剩余未读取的内容的信息。 如果n>函数会返回一个最多n个成员的切片。这时,如果Readdir返回一个空切片,它会返回一个非nil的错误说明原因。如果到达了目录f的结尾,返回值err会是io.EOF。 如果n<=函数返回目录中剩余所有文件对象的FileInfo构成的切片。此时,如果Readdir调用成功(读取所有内容直到结尾),它会返回该切片和nil的错误值。如果在到达结尾前遇到错误,会返回之前成功读取的FileInfo构成的切片和该错误。 func (f *File) Readdirnames(n ) (names [],err error) 内容,返回一个有n个成员的[]string,切片成员为目录中文件对象的名字,采用目录顺序。对本函数的下一次调用会返回上一次调用剩余未读取的内容的信息。 如果n>函数会返回一个最多n个成员的切片。这时,如果Readdir返回一个空切片,它会返回一个非nil的错误说明原因。如果到达了目录f的结尾,返回值err会是io.EOF。 如果n<=函数返回目录中剩余所有文件对象的名字构成的切片。此时,如果Readdir调用成功(读取所有内容直到结尾),它会返回该切片和nil的错误值。如果在到达结尾前遇到错误,会返回之前成功读取的名字构成的切片和该错误。 func (f *File) Seek(offset int64,whence ) (ret int64,err error) 文件开头,1为相对当前位置,2为相对文件结尾。它返回新的偏移量(相对开头)和可能的错误 func (f *File) SetDeadline(t time.Time) error 文件读取和写入时间,超时返回错误 func (f *File) SetReadDeadline(t time.Time) error 文件读取时间 func (f *File) SetWriteDeadline(t time.Time) error 文件写入时间 func (f *File) Stat() (FileInfo,error) 文件f的FileInfo类型值。如果出错,错误底层类型是*PathError。 func (f *File) Sync() error 文件的当前内容进行稳定的存储。一般来说,这表示将文件系统的最近写入的数据在内存中的拷贝刷新到硬盘中稳定保存。 func (f *File) Truncate(size int64) error 文件的大小,它不会改变I/O的当前位置。 如果截断文件,多出的部分就会被丢弃。如果出错,错误底层类型是*PathError。 func (f *File) Write(b []) (n ,err error) 文件中写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误 func (f *File) WriteAt(b [],err error) 文件,从字节偏移开始。它返回写入的字节数和错误,写的时候返回一个错误,当n != len(b) func (f *File) WriteString(s ) (n ,err error)

读写参数@H_403_171@

文件打开模式:

= syscall.O_RDONLY 文件 O_WRONLY = syscall.O_WRONLY 文件 O_RDWR = syscall.O_RDWR 文件 O_APPEND = syscall.O_APPEND 文件尾部 O_CREATE = syscall.O_CREAT 文件 O_EXCL = syscall.O_EXCL 文件必须不存在 O_SYNC = syscall.O_SYNC 文件用于同步I/O O_TRUNC = syscall.O_TRUNC 文件 )

文件权限:

  • r :可读,对应的004

  • w:可写,对应002

  • x:可执行,对应001

文件读取@H_403_171@

Read

import (
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">os<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">io<span style="color: #800000;">"<span style="color: #000000;">
)

func main() {
file,err := os.Open(<span style="color: #800000;">"<span style="color: #800000;">/home/test.txt<span style="color: #800000;">") <span style="color: #008000;">//只读打开
<span style="color: #0000ff;">if err !=<span style="color: #000000;"> nil {
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">open file error: <span style="color: #800000;">"<span style="color: #000000;">,err)
<span style="color: #0000ff;">return<span style="color: #000000;">
}
defer file.Close() <span style="color: #008000;">//<span style="color: #008000;">关闭文件
context := make([]<span style="color: #0000ff;">byte,<span style="color: #800080;">100<span style="color: #000000;">)
<span style="color: #0000ff;">for<span style="color: #000000;"> {
readNum,err :=<span style="color: #000000;"> file.Read(context)
<span style="color: #0000ff;">if err != nil && err !=<span style="color: #000000;"> io.EOF {
<span style="color: #008000;">//<span style="color: #008000;">panic(err) <span style="color: #008000;">//<span style="color: #008000;">有错误抛出异常
<span style="color: #000000;"> }
<span style="color: #0000ff;">if <span style="color: #800080;">0 ==<span style="color: #000000;"> readNum {
<span style="color: #0000ff;">break <span style="color: #008000;">//<span style="color: #008000;">当读取完毕时候退出循环
<span style="color: #000000;"> }
}
<span style="color: #0000ff;">for k,v :=<span style="color: #000000;"> range context{
println(k,v)
}

}

Seek

文件不存在则创建文件,以append方式打开 file,err := os.OpenFile(,os.O_CREATE|os.O_APPEND, err !=关闭文件 file.WriteString() 文件 buf := make([], str ,os.SEEK_SET) 文件指针 文件 = ferr != nil && ferr != n == += (buf[

按行读取ReadLine

import (
<span style="color: #800000;">"<span style="color: #800000;">bufio<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">io<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">os<span style="color: #800000;">"<span style="color: #000000;">
)

func main() {
file,err := os.Open(<span style="color: #800000;">"<span style="color: #800000;">/home/test.txt<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #0000ff;">if err !=<span style="color: #000000;"> nil {
fmt.Println(err)
<span style="color: #0000ff;">return<span style="color: #000000;">
}
defer file.Close()
reader :=<span style="color: #000000;"> bufio.NewReader(file)
<span style="color: #0000ff;">var line []<span style="color: #0000ff;">byte
<span style="color: #0000ff;">for<span style="color: #000000;"> {
data,prefix,err :=<span style="color: #000000;"> reader.ReadLine()
<span style="color: #0000ff;">if err ==<span style="color: #000000;"> io.EOF {
<span style="color: #0000ff;">break<span style="color: #000000;">
}

    line </span>=<span style="color: #000000;"&gt; append(line,data...)
    </span><span style="color: #0000ff;"&gt;if</span> !<span style="color: #000000;"&gt;prefix {
        fmt.Printf(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;data:%s\n</span><span style="color: #800000;"&gt;"</span>,<span style="color: #0000ff;"&gt;string</span><span style="color: #000000;"&gt;(line))
        line </span>=<span style="color: #000000;"&gt; line[:]
    }

}

}

读取整个文件ReadAll

import (
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">os<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">io/IoUtil<span style="color: #800000;">"<span style="color: #000000;">
)

func main() {
fileName := <span style="color: #800000;">"<span style="color: #800000;">/home/test.txt<span style="color: #800000;">"<span style="color: #000000;">

file,err :</span>= os.OpenFile(fileName,os.O_CREATE|os.O_RDWR,<span style="color: #800080;"&gt;0666</span><span style="color: #000000;"&gt;)
</span><span style="color: #0000ff;"&gt;if</span> err !=<span style="color: #000000;"&gt; nil {
    fmt.Println(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;Open file error: </span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;,err)
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt;
}
defer file.Close()

buf,err :</span>=<span style="color: #000000;"&gt; <a href="/tag/IoU/" target="_blank" class="keywords">IoU</a>til.ReadAll(file)
</span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;buf,err := <a href="/tag/IoU/" target="_blank" class="keywords">IoU</a>til.ReadFile(fileName)</span>
<span style="color: #0000ff;"&gt;if</span> err !=<span style="color: #000000;"&gt; nil {
    fmt.Fprintf(os.Stderr,</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;File Error: %s\n</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;,err)
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt;
}
fmt.Printf(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;%s\n</span><span style="color: #800000;"&gt;"</span>,<span style="color: #0000ff;"&gt;string</span><span style="color: #000000;"&gt;(buf))

}

四、带缓冲区的读写(bufio)

带缓冲的读写操作作用是为了减少磁盘io次数,通过包bufio实现,这里做简单示例说明,bufio包后续再介绍.

标准输入读示例:

import (
<span style="color: #800000;">"<span style="color: #800000;">bufio<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">os<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">
)

func main() {
reader := bufio.NewReader(os.Stdin) <span style="color: #008000;">//<span style="color: #008000;"> 创建从标准输入中读取数据对象
str,err := reader.ReadString(<span style="color: #800000;">'<span style="color: #800000;">\n<span style="color: #800000;">') <span style="color: #008000;">//<span style="color: #008000;">读数据,bytes类型是单引号
<span style="color: #0000ff;">if err !=<span style="color: #000000;"> nil {
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">read fail<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #0000ff;">return<span style="color: #000000;">
}
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">input string: <span style="color: #800000;">"<span style="color: #000000;">,str)

}
<span style="color: #008000;">//<span style="color: #008000;">adad
<span style="color: #008000;">//<span style="color: #008000;">input string: adad

文件读取示例

import (
<span style="color: #800000;">"<span style="color: #800000;">bufio<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">os<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">io<span style="color: #800000;">"<span style="color: #000000;">
)

func main() {
file,err := os.Open(<span style="color: #800000;">"<span style="color: #800000;">test.txt<span style="color: #800000;">") <span style="color: #008000;">//<span style="color: #008000;">以只读方式打开文件
<span style="color: #0000ff;">if err !=<span style="color: #000000;"> nil {
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">open file fail err:<span style="color: #800000;">"<span style="color: #000000;">,err)
<span style="color: #0000ff;">return<span style="color: #000000;">
}
reader := bufio.NewReader(file) <span style="color: #008000;">//<span style="color: #008000;"> 创建读取数据对象
<span style="color: #000000;"> defer file.Close()
<span style="color: #0000ff;">for<span style="color: #000000;">{
str,err := reader.ReadString(<span style="color: #800000;">'<span style="color: #800000;">\n<span style="color: #800000;">') <span style="color: #008000;">//<span style="color: #008000;">读数据,bytes类型是单引号,回车结束。
<span style="color: #0000ff;">if err ==<span style="color: #000000;"> io.EOF {
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">read over<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #0000ff;">break<span style="color: #000000;">
}
<span style="color: #0000ff;">if err !=<span style="color: #000000;"> nil{
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">error :<span style="color: #800000;">"<span style="color: #000000;">,err)
<span style="color: #0000ff;">break<span style="color: #000000;">
}
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">STRING: <span style="color: #800000;">"<span style="color: #000000;">,str)

}

}

文件示例:

注意事项:写入文件需要 Flush缓冲区的内容文件中。

import (
<span style="color: #800000;">"<span style="color: #800000;">bufio<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">os<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">
)

func main() {
file,err := os.OpenFile(<span style="color: #800000;">"<span style="color: #800000;">test.txt<span style="color: #800000;">",os.O_WRONLY,<span style="color: #800080;">0644) <span style="color: #008000;">//<span style="color: #008000;">以写方式打开文件
<span style="color: #0000ff;">if err !=<span style="color: #000000;"> nil {
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">open file fail err:<span style="color: #800000;">"<span style="color: #000000;">,err)
<span style="color: #0000ff;">return<span style="color: #000000;">
}
writer := bufio.NewWriter(file) <span style="color: #008000;">//<span style="color: #008000;"> 创建写对象
<span style="color: #000000;"> defer file.Close()
<span style="color: #0000ff;">var str <span style="color: #0000ff;">string<span style="color: #000000;">
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">请输入内容:<span style="color: #800000;">"<span style="color: #000000;">)
fmt.Scanf(<span style="color: #800000;">"<span style="color: #800000;">%s<span style="color: #800000;">",&<span style="color: #000000;">str)
writer.WriteString(str)
writer.Flush() <span style="color: #008000;">//<span style="color: #008000;"> 将缓冲区内容写入文件,默认写入到文件开头
<span style="color: #000000;">
}

五、命令行参数

命令行参数:程序启动或者停止时候,在命令行中给定的参数就是命令行参数。例如start.sh -p 8080  

go语言中提供了两种处理命令行参数的包os.Agrs和flag包。

优缺点:

  • os.Agrs提供了简单的命令行参数,以命令行参数个数作为标识,参数列表是一个切片,索引0代表程序本身,1代表第一个参数,以此类推,没有更细粒度的参数区分,使用起来简单
  • flag提供了更为科学的命令行参数处理办法,提供更细粒度的和更全的参数解析,推荐使用

os.Agrs@H_403_171@

os.Args 提供原始命令行参数访问功能。注意,切片中的第一个参数是该程序的路径,并且 os.Args[1:]保存所有程序的的参数。

示例:

import (
<span style="color: #800000;">"<span style="color: #800000;">os<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">
)
func main() {
<span style="color: #0000ff;">if len(os.Args) < <span style="color: #800080;">2<span style="color: #000000;"> {
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">no args<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #0000ff;">return<span style="color: #000000;">
}
println(<span style="color: #800000;">"<span style="color: #800000;">script name: <span style="color: #800000;">",os.Args[<span style="color: #800080;">0<span style="color: #000000;">])
<span style="color: #0000ff;">for i :=<span style="color: #000000;"> range os.Args {
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">this is %d arg : %s\n<span style="color: #800000;">"<span style="color: #000000;">,i,os.Args[i])

}

}
<span style="color: #008000;">//<span style="color: #008000;"> 执行./eg1 name age body
<span style="color: #008000;">//<span style="color: #008000;">结果:
<span style="color: #008000;">//<span style="color: #008000;">script name: ./eg1
<span style="color: #008000;">//<span style="color: #008000;">this is 0 arg : ./eg1
<span style="color: #008000;">//<span style="color: #008000;">this is 1 arg : name
<span style="color: #008000;">//<span style="color: #008000;">this is 2 arg : age
<span style="color: #008000;">//<span style="color: #008000;">this is 3 arg : body

flag包@H_403_171@

Flag类型是一个结构体,其定义如下:

type Flag Usage Value Value DefValue }

flag包提供了一系列解析命令行参数的功能接口,其定义的命令行参数方式有以下几种:

-flag 支持bool类型 -flag=-flag x 支持非bool类型 特别说明一个-和 -- 效果是一样的

定义flag参数

方式一:通过flag.String(),Bool(),Int() 等flag.Xxx()方法,该种方式返回一个相应的指针

示例:

import (
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">flag<span style="color: #800000;">"<span style="color: #000000;">
)
func main() {
ip := flag.String(<span style="color: #800000;">"<span style="color: #800000;">ip<span style="color: #800000;">",<span style="color: #800000;">"<span style="color: #800000;">10.0.0.230<span style="color: #800000;">",<span style="color: #800000;">"<span style="color: #800000;">server listen ip<span style="color: #800000;">") <span style="color: #008000;">//<span style="color: #008000;">参数一为命令行接受的参数名称,参数二为默认值,参数三为描述信息
port := flag.Int(<span style="color: #800000;">"<span style="color: #800000;">port<span style="color: #800000;">",<span style="color: #800080;">80,<span style="color: #800000;">"<span style="color: #800000;">server port<span style="color: #800000;">"<span style="color: #000000;">)
flag.Parse()
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">ip<span style="color: #800000;">",<span style="color: #000000;">ip)
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">port<span style="color: #800000;">",
<span style="color: #000000;">port)
}
<span style="color: #008000;">//<span style="color: #008000;">使用go build 编译 执行./eg1 --port 8080 -ip 10.0.0.241
<span style="color: #008000;">//<span style="color: #008000;">结果
<span style="color: #008000;">//<span style="color: #008000;">ip 10.0.0.241
<span style="color: #008000;">//<span style="color: #008000;">port 8080

方式二:

通过flag.XxxVar()方法将flag绑定到一个变量,该种方式返回值类型,我们将上述示例改为flag.xxxVar()

import (
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">flag<span style="color: #800000;">"<span style="color: #000000;">
)
func main() {
<span style="color: #0000ff;">var ip <span style="color: #0000ff;">string
<span style="color: #0000ff;">var port <span style="color: #0000ff;">int<span style="color: #000000;">
flag.StringVar(&ip,<span style="color: #800000;">"<span style="color: #800000;">ip<span style="color: #800000;">",<span style="color: #800000;">"<span style="color: #800000;">server listen ip<span style="color: #800000;">") <span style="color: #008000;">//<span style="color: #008000;">参数一是变量,后面与flag.String一样
flag.IntVar(&port,<span style="color: #800000;">"<span style="color: #800000;">port<span style="color: #800000;">",<span style="color: #800000;">"<span style="color: #800000;">server port<span style="color: #800000;">"<span style="color: #000000;">)
flag.Parse()
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">ip<span style="color: #800000;">"<span style="color: #000000;">,ip)
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">port<span style="color: #800000;">"<span style="color: #000000;">,port)
}
<span style="color: #008000;">//<span style="color: #008000;"> 同样编译完成运行./eg1 --port 8080 -ip 10.0.0.241
<span style="color: #008000;">//<span style="color: #008000;">结果
<span style="color: #008000;">//<span style="color: #008000;">ip 10.0.0.241
<span style="color: #008000;">//<span style="color: #008000;">port 8080

六、序列化、反序列化

应用程序交互,即数据的交互,数据交互永远离不开序列化,常见的数据库交互格式如json、xml,在go语言中提供了诸多的序列化格式:

性能高不支持不确定大小类型 int、slice、string支持多种类型性能低于 binary 和 protobuf支持多种类型,性能高生成 .pb.go 文件支持多种类型性能低 @H_403_171@

json@H_403_171@

json格式数据是现在数据交互用的最多的数据格式,go一般通过json.Marshal()进行序列化,通过json.Marshal()反序列化。

示例一:序列化struct

import (
<span style="color: #800000;">"<span style="color: #800000;">encoding/json<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">
)

type Student <span style="color: #0000ff;">struct<span style="color: #000000;"> {
Name <span style="color: #0000ff;">string json:<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;name</span><span style="color: #800000;"&gt;"</span> <span style="color: #008000;">//<span style="color: #008000;">序列化时将字段变为小写
Age <span style="color: #0000ff;">int json:<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;age</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;
score <span style="color: #0000ff;">int json:<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;<a href="/tag/score/" target="_blank" class="keywords">score</a></span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;
}

func main() {
stu1 :=&Student{Name:<span style="color: #800000;">"<span style="color: #800000;">wd<span style="color: #800000;">",Age:<span style="color: #800080;">22,score:<span style="color: #800080;">100<span style="color: #000000;">}
res,err :=<span style="color: #000000;"> json.Marshal(stu1)
<span style="color: #0000ff;">if err !=<span style="color: #000000;"> nil {
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">json encode error<span style="color: #800000;">"<span style="color: #000000;">)
<span style="color: #0000ff;">return<span style="color: #000000;">
}
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">json string: %s<span style="color: #800000;">"<span style="color: #000000;">,res)
}<span style="color: #008000;">//<span style="color: #008000;"> 结果
<span style="color: #008000;">//<span style="color: #008000;">json string :{"name":"wd","age":22,"score":100}

示例二:序列化map

import (
<span style="color: #800000;">"<span style="color: #800000;">encoding/json<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">
)

type Dictmap map[<span style="color: #0000ff;">int]<span style="color: #0000ff;">string<span style="color: #000000;">

func main() {

 map1 :</span>= &amp;Dictmap{<span style="color: #800080;"&gt;1</span>:<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;wd</span><span style="color: #800000;"&gt;"</span>,<span style="color: #800080;"&gt;2</span>:<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;name</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;}
res,err :</span>=<span style="color: #000000;"&gt; json.Marshal(map1)
</span><span style="color: #0000ff;"&gt;if</span> err !=<span style="color: #000000;"&gt; nil {
    fmt.Println(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;json encode error</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;)
    </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt;
}
fmt.Printf(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;json string: %s</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;,res)
}

<span style="color: #008000;">//<span style="color: #008000;"> 结果:json string: {"1":"wd","2":"name"}

反序列化

反序列化过程中需要注意,数据格式是byte切片

func Unmarshal(data [],v {}) error

反序列化struct示例:

import (
<span style="color: #800000;">"<span style="color: #800000;">encoding/json<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">
)

type Student <span style="color: #0000ff;">struct<span style="color: #000000;"> {
Name <span style="color: #0000ff;">string json:<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;name</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;
Age <span style="color: #0000ff;">int json:<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;age</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;
score <span style="color: #0000ff;">int json:<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;<a href="/tag/score/" target="_blank" class="keywords">score</a></span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;
}

func main() {
data := {<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;name</span><span style="color: #800000;"&gt;"</span>:<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;wd</span><span style="color: #800000;"&gt;"</span>,<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;age</span><span style="color: #800000;"&gt;"</span>:<span style="color: #800080;"&gt;22</span>,<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;<a href="/tag/score/" target="_blank" class="keywords">score</a></span><span style="color: #800000;"&gt;"</span>:<span style="color: #800080;"&gt;100</span><span style="color: #000000;"&gt;}
<span style="color: #0000ff;">var<span style="color: #000000;"> stu1 Student
err := json.Unmarshal([]<span style="color: #0000ff;">byte(data),&<span style="color: #000000;">stu1)
<span style="color: #0000ff;">if err !=<span style="color: #000000;"> nil {
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">json decode error: <span style="color: #800000;">"<span style="color: #000000;">,err)
<span style="color: #0000ff;">return<span style="color: #000000;">
}
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">struct obj is : %s<span style="color: #800000;">"<span style="color: #000000;">,stu1.Name)
}
<span style="color: #008000;">//<span style="color: #008000;">结果
<span style="color: #008000;">//<span style="color: #008000;">struct obj is : wd

gob@H_403_171@

Gob(Go binary 的缩写) 是 Go 自己的以二进制形式序列化和反序列化程序数据的格式,其方法在encoding中,类似于 Python 的 "pickle" ,这样的数据格式只能在go程序之间进行数据交互。

序列化和反序列化示例:

import (
<span style="color: #800000;">"<span style="color: #800000;">bytes<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">encoding/gob<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">
)

type Student <span style="color: #0000ff;">struct<span style="color: #000000;"> {
Name <span style="color: #0000ff;">string json:<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;name</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;
Age <span style="color: #0000ff;">int json:<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;age</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;
score <span style="color: #0000ff;">int json:<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;<a href="/tag/score/" target="_blank" class="keywords">score</a></span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;
}

func main() {
stu1 := Student{<span style="color: #800000;">"<span style="color: #800000;">wd<span style="color: #800000;">",<span style="color: #800080;">22,<span style="color: #800080;">100<span style="color: #000000;">}
<span style="color: #0000ff;">var<span style="color: #000000;"> buf bytes.Buffer

enc :</span>= gob.NewEncoder(&amp;<span style="color: #000000;"&gt;buf)
dec :</span>= gob.NewDecoder(&amp;<span style="color: #000000;"&gt;buf)

</span><span style="color: #0000ff;"&gt;if</span> err := enc.Encode(stu1); err !=<span style="color: #000000;"&gt; nil {
    fmt.Println(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;encode error:</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;,err)
}
fmt.Printf(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;gob res %s: \n</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;,enc)
</span><span style="color: #0000ff;"&gt;var</span><span style="color: #000000;"&gt; stu2 Student
</span><span style="color: #0000ff;"&gt;if</span> err := dec.Decode(&amp;stu2); err !=<span style="color: #000000;"&gt; nil {
    fmt.Println(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;decode error:</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;,err)
}
fmt.Println(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;decode res:</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;,stu2)
} </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;decode res: wd</span></pre>

403_171@

endoding包中的binnary主要用于二进制数据序列化,但是局限性较高。

 注意: 如果字段中有不确定大小的类型,如 int,slice,string 等,则会报错。使用binary.Write进行序列化时候,数据类型必须是固定大小如:int只能使用int64、int32,切片需要有固定长度。

import (
<span style="color: #800000;">"<span style="color: #800000;">bytes<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">encoding/binary<span style="color: #800000;">"
<span style="color: #800000;">"<span style="color: #800000;">fmt<span style="color: #800000;">"<span style="color: #000000;">
)

type Message <span style="color: #0000ff;">struct<span style="color: #000000;"> {
Id uint64
Size uint64
}

func main() {
m1 := Message{<span style="color: #800080;">1,<span style="color: #800080;">22<span style="color: #000000;">}
buf := <span style="color: #0000ff;">new<span style="color: #000000;">(bytes.Buffer)
err := binary.Write(buf,binary.LittleEndian,m1) <span style="color: #008000;">//<span style="color: #008000;"> 序列化
<span style="color: #0000ff;">if err !=<span style="color: #000000;"> nil {
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">binary write error:<span style="color: #800000;">"<span style="color: #000000;">,err)
}
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">binary res: %s \n <span style="color: #800000;">",m1) <span style="color: #008000;">//<span style="color: #008000;">binary res: {%!s(uint64=1) %!s(uint64=22)}
<span style="color: #0000ff;">var<span style="color: #000000;"> m2 Message
err1 := binary.Read(buf,&m2); <span style="color: #008000;">//<span style="color: #008000;">反序列化
<span style="color: #0000ff;">if err1 !=<span style="color: #000000;"> nil {
fmt.Println(<span style="color: #800000;">"<span style="color: #800000;">binary read error:<span style="color: #800000;">"<span style="color: #000000;">,err)
}
fmt.Printf(<span style="color: #800000;">"<span style="color: #800000;">decode res: %s<span style="color: #800000;">",m2) <span style="color: #008000;">//<span style="color: #008000;">decode res: {%!s(uint64=1) %!s(uint64=22)}
}

ProtoBuf@H_403_171@

对于ProtoBuf并不是go语言中包自带的,需要自行安装你需要安装protoc编译器,以及protoc库以及生成相关的类

安装方法(linux或者mac):

go get -u github.com/golang/protobuf/proto go get -u github.com/golang/protobuf/proto-gen-go go install github.com/golang/protobuf/proto go install github.com/golang/protobuf/protoc-gen-go

使用:

创建一个test.proto文件

Syntax = <span style="color: #008000;">//<span style="color: #008000;">包名,通过protoc生成时go文件
<span style="color: #000000;">package test;

<span style="color: #008000;">//<span style="color: #008000;">手机类型
<span style="color: #008000;">//<span style="color: #008000;">枚举类型第一个字段必须为0
<span style="color: #0000ff;">enum<span style="color: #000000;"> PhoneType {
HOME = <span style="color: #800080;">0<span style="color: #000000;">;
WORK = <span style="color: #800080;">1<span style="color: #000000;">;
}

<span style="color: #008000;">//<span style="color: #008000;">手机
<span style="color: #000000;">message Phone {
PhoneType type = <span style="color: #800080;">1<span style="color: #000000;">;
<span style="color: #0000ff;">string number = <span style="color: #800080;">2<span style="color: #000000;">;
}

<span style="color: #008000;">//<span style="color: #008000;">人
<span style="color: #000000;">message Person {
<span style="color: #008000;">//<span style="color: #008000;">后面的数字表示标识号
int32 id = <span style="color: #800080;">1<span style="color: #000000;">;
<span style="color: #0000ff;">string name = <span style="color: #800080;">2<span style="color: #000000;">;
<span style="color: #008000;">//<span style="color: #008000;">repeated表示可重复
<span style="color: #008000;">//<span style="color: #008000;">可以有多个手机
repeated Phone phones = <span style="color: #800080;">3<span style="color: #000000;">;
}

<span style="color: #008000;">//<span style="color: #008000;">联系簿
<span style="color: #000000;">message ContactBook {
repeated Person persons = <span style="color: #800080;">1<span style="color: #000000;">;
}

运行命令:protoc --go_out=. *.proto,生成test.pb.go文件

使用protobuf

猜你在找的Go相关文章