1.1、打开一个文件
基本介绍:打开一个文件用于读取,如果操作成功,返回的文件对象的方法可用于读取文件数据。如果出错,错误底层类型是"*.PathError"
func Open(name string) (*File, error)
name string:打开的文件路径
*File:返回值1,文件对象
error:返回值2,错误err
1.2、关闭一个文件
基本介绍:语法如下
func (f *File) Close() error
(f *File) Close():文件对象的Close方法
error:返回值1,错误err
打开文件,关闭文件,快速入门案例:
package main import ( "fmt" "os" ) func main() { // 打开一个文件(默认有2个返回值:文件对象,错误) file, err:=os.Open("sudada.log") // 如果err有值,则输出错误 if err != nil { fmt.Println("打开文件失败,错误:",err) } // 通过文件对象file的值 fmt.Println(file) // 返回值:&{0xc000100a00} fmt.Println(file.Name()) // 返回值:sudada.log // 关闭文件(默认有1个返回值:错误) close_err := file.Close() if close_err != nil { fmt.Println("打开文件失败,错误:",close_err) } }
1.3、读文件内容
1.读取文件内容并显示在终端(带缓冲区的方式):使用bufio.NewReader(),reader.ReadString函数和方法。
步骤:先打开文件,然后读文件,最后关闭文件
package main import ( "bufio" "fmt" "io" "os" ) func main() { // 打开一个文件(有2个返回值:文件对象,错误) file, err:=os.Open("sudada.log") // 如果err有值,则输出错误 if err != nil { fmt.Println("打开文件失败,错误:",err) } // 在函数要退出时,关闭文件 defer file.Close() // 创建一个 *Reader,是带缓冲的(默认4096字节) reader := bufio.NewReader(file) // 循环读取文件的内容: reader.ReadString (有2个返回值:文件内容,错误) for { str,err := reader.ReadString('\n') // 读到"换行"就结束 // 读到文件结尾时,就break if err == io.EOF { break } // 打印读取到的文件内容 fmt.Print(str) // 返回值:hello world // 返回值:sudada // 返回值:beijing } }
2.读取文件内容并显示在终端(使用ioutil一次将整个文件读入到内存中),这种方式适合小文件:使用ioutil.ReadFile函数
步骤:一次将文件读取到位
package main import ( "fmt" "io/ioutil" ) func main() { // 使用ioutil.ReadFile一次性将文件读取到位 file := "sudada.log" content,err := ioutil.ReadFile(file) if err != nil { fmt.Println(err) } // 显示读取的内容 fmt.Printf("%v",string(content)) // hello world // sudada // beijing // shanghai }
1.4、常用的4种写文件方式
基本介绍:语法如下
func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
name string:打开的文件
flag int:文件打开的模式
os.O_WRONLY 只写模式
os.O_RDWR 读写模式
os.O_RDONLY 只读模式
os.O_CREATE 如果文件不存在则创建
os.O_EXCL 和os.O_CREATE配合使用,文件必须不存在
os.O_SYNC 打开文件用于同步IO
os.O_TRUNC 如果可能,打开是清空文件os.O_APPEND 追加内容
perm FileMode:文件的权限控制(linux)
file *File:返回值1,文件对象
err error:返回值2,错误err
快速入门案例:
1.创建一个新文件,写入内容:hello world(模式 os.O_WRONLY | os.O_CREATE )
package main import ( "bufio" "fmt" "os" ) func main() { // 创建一个新文件,写入内容:hello world // 1.文件名"test.log" filename := "test.log" // 打开文件"test.log" file,err :=os.OpenFile(filename, os.O_WRONLY | os.O_CREATE, 0666) if err != nil { fmt.Println(err) return } // 2.写入到文件的内容(\r\n表示换行) str:="hello world sudada \r\n" // 写入文件时,使用带缓存的 *Writer writer:=bufio.NewWriter(file) writer.WriteString(str) // writer带缓存,在调用WriteString方法写入时,需要flush到磁盘。 writer.Flush() // 3.关闭文件句柄 defer file.Close() }
2.打开一个存在的文件,覆盖文件的内容(模式 os.O_WRONLY | os.O_TRUNC )
package main import ( "bufio" "fmt" "os" ) func main() { // 1.文件名"test.log" filename := "test.log" // 打开文件"test.log" file,err :=os.OpenFile(filename, os.O_WRONLY | os.O_TRUNC, 0666) if err != nil { fmt.Println(err) return } // 2.写入到文件的内容(\r\n表示换行) str:="hello world sudada \r\n" // 写入文件时,使用带缓存的 *Writer writer:=bufio.NewWriter(file) writer.WriteString(str) // writer带缓存,在调用WriteString方法写入时,需要flush到磁盘。 writer.Flush() // 3.关闭文件句柄 defer file.Close() }
3.打开一个存在的文件,追加内容(模式 os.O_WRONLY | os.O_APPEND )
package main import ( "bufio" "fmt" "os" ) func main() { // 1.文件名"test.log" filename := "test.log" // 打开文件"test.log" file,err :=os.OpenFile(filename, os.O_WRONLY | os.O_APPEND, 0666) if err != nil { fmt.Println(err) return } // 2.写入到文件的内容(\r\n表示换行) str:="hello world new \r\n" // 写入文件时,使用带缓存的 *Writer writer:=bufio.NewWriter(file) writer.WriteString(str) // writer带缓存,在调用WriteString方法写入时,需要flush到磁盘。 writer.Flush() // 3.关闭文件句柄 defer file.Close() }
4.打开一个存在的文件,读取原来的内容,然后在追加内容(模式 os.O_RDWR | os.O_APPEND )
package main import ( "bufio" "fmt" "io" "os" ) func main() { // 1.文件名"test.log" filename := "test.log" // 打开文件"test.log" file,err :=os.OpenFile(filename, os.O_RDWR | os.O_APPEND, 0666) if err != nil { fmt.Println(err) return } // 2.先读文件 reader:=bufio.NewReader(file) for{ str,err := reader.ReadString('\n') // 如果读取到文件的末尾,就break if err == io.EOF { break } // 显示文件已有的内容 fmt.Print(str) } // 3.然后再追加文件内容 str:="hello shanghai \r\n" // 写入文件时,使用带缓存的 *Writer writer:=bufio.NewWriter(file) writer.WriteString(str) // writer带缓存,在调用WriteString方法写入时,需要flush到磁盘。 writer.Flush() // 4.关闭文件句柄 defer file.Close() }
5.将文件a复制到文件b(使用ioutil.ReadFile() 和 ioutil.WriteFile()方法)
package main import ( "fmt" "io/ioutil" ) func main() { file_test := "test.log" file_new_test := "new_test.log" // 1.读文件"test.log"的内容 data, read_err := ioutil.ReadFile(file_test) if read_err != nil { fmt.Println("read file test.log error: ",read_err) return } // 2.将"test.log"的文件内容写到"new_test.log" write_err := ioutil.WriteFile(file_new_test, data, 0666) if write_err != nil { fmt.Println("writer file new_test.log error: ",write_err) return } }
1.5、判断文件或目录是否存在
os.Stat(file_path) 方法的返回值说明:
1.返回的错误为nil,说明文件或文件夹存在
2.返回的错误使用os.IsNotExist()为true,说明文件或文件夹不存在
3.返回的错误为其他类型,则不确定是否存在package main import ( "fmt" "os" ) func main() { file_path := "test.log" _, err := os.Stat(file_path) // os.Stat(file_test) 的用法: // 1.返回的错误为nil,说明文件或文件夹存在 // 2.返回的错误使用os.IsNotExist()为true,说明文件或文件夹不存在 // 3.返回的错误为其他类型,则不确定是否存在 // err == nil 时,文件存在 if err == nil { fmt.Printf("file %v exist !", file_path) } // os.IsNotExist()为true时,文件不存在 if os.IsNotExist(err) { fmt.Printf("file %v is not exist !", file_path) } } // 封装的一个函数判断文件是否存在 func PathExist(path string) (bool, error) { _, err := os.Stat(path) // os.Stat(file_test) 的用法 // 1.返回的错误为nil,说明文件或文件夹存在 // 2.返回的错误使用os.IsNotExist()为true,说明文件或文件夹不存在 // 3.返回的错误为其他类型,则不确定是否存在 // err == nil 时,文件存在 if err == nil { return true, nil } // os.IsNotExist()为true时,文件不存在 if os.IsNotExist(err) { return false, err } return false, err } func main() { file_path := "1test.log" flg, msg:=PathExist(file_path) if flg { fmt.Printf("file %v exist !", file_path) } else { fmt.Printf("file %v is not exist, msg: %v\n", file_path, msg) } }
1.6、文件拷贝
Copy函数是io包提供的
package main import ( "bufio" "fmt" "io" "os" ) func CopyFile(dstFileName string, srcFileName string)(written int64, err error) { // 获取源文件 srcFile,err := os.Open(srcFileName) if err != nil { fmt.Println("open file error: ",err) } // 关闭文件句柄 defer srcFile.Close() // 通过srcFile,获取到Reader reader := bufio.NewReader(srcFile) // 打开目标文件 dstFile, err := os.OpenFile(dstFileName,os.O_WRONLY | os.O_CREATE,0666) if err != nil { fmt.Println("open file error: ",err) return } writer := bufio.NewWriter(dstFile) // 关闭文件句柄 defer dstFile.Close() // 通过io.Copy将源文件copy到目标文件 return io.Copy(writer, reader) } func main() { // 将文件funingla.png, copy到fufu.png srcFileName := "funingla.png" dstFileName := "fufu.png" _,err := CopyFile(dstFileName, srcFileName) if err == nil { fmt.Println("copy success") } else { fmt.Println("error: ",err) } }
2.1、获取命令行参数
方法1:os.Args是一个string切片,用来存储所有的命令行参数。
package main import ( "fmt" "os" ) func main() { fmt.Println("命令行的参数有",len(os.Args)) // 编译os.Args切片就拿到所有的命令行参数 for i,v := range os.Args { fmt.Printf("args[%v]=%v\n",i,v) } // 执行命令(空格分隔):go run main.go test aa abc // 第1个参数(文件名):main.exe // 第2个参数(实际的参数1):test // 第3个参数(实际的参数2):aa // 第4个参数(实际的参数3):abc }
方法2:flag包解析命令行参数
package main import ( "flag" "fmt" ) func main() { var user string var port int var pwd string var host string // &user:接收输入的"-u"的值,默认值为"",参数解释:"用户名" flag.StringVar(&user,"u","","用户名") // &port:接收输入的"-port"的值,默认值为3306,参数解释:"端口,默认为3306" flag.IntVar(&port,"port",3306,"端口,默认为3306") // &pwd:接收输入的"-p"的值,默认值为"",参数解释:"端口,默认为空" flag.StringVar(&pwd,"p","","密码,默认为空") // &host:接收输入的"-h"的值,默认值为"localhost",参数解释:"主机地址,默认为localhost" flag.StringVar(&host,"h","localhost","主机地址,默认为localhost") // 必须转换 flag.Parse() // 输出结果 fmt.Printf("user=%v,port=%v,pwd=%v,host=%v\n",user,port,pwd,host) // 执行命令(必须以空格分隔):go run main.go -u root -p asd!@#%^&( -port 3306 -h 127.0.0.1 // 返回结果:user=root,port=3306,pwd=asd!@#%&(,host=127.0.0.1 }
序列化快速入门:data, err := json.Marshal(monster)
data == 拿到序列化后的json格式数据
monster == 被序列化的格式(结构体,map,切片)
3.1、结构体-序列化
package main import ( "encoding/json" "fmt" ) type Monster struct { Name string Age int Birthday string Skill string } // 结构体Json序列化 func testStruct() { var monster = Monster{ Name:"sudada", Age:18, Birthday:"2000-06-11", Skill:"牛牛冲击", } data, err := json.Marshal(monster) if err != nil { fmt.Println("序列化失败:",err) } // struct序列化结果 fmt.Println(string(data)) // 返回值(key的值被大写了,因为结构体的字段是大写的):{"Name":"sudada","Age":18,"Birthday":"2000-06-11","Skill":"牛牛冲击"} } func main() { testStruct() }
结构体json序列化时tag的使用(可以将结构体的字段小写)
package main import ( "encoding/json" "fmt" ) type Monster struct { name string `json:"name"` // 反射机制 Age int `json:"age"` // 反射机制 Birthday string `json:"birthday"` // 反射机制 Skill string `json:"skill"` // 反射机制 } // 结构体Json序列化 func testStruct() { var monster = Monster{ name: "sudada", Age:18, Birthday:"2000-06-11", Skill:"牛牛冲击", } // 结构体字段不能小写,因为在json包内无法识别小写的"结构体的字段名" // 如果"结构体字段小写"且进行序列化,那么"序列化后的数据"不包含这个"小写字段"的值 // 这里小写name字段为例,序列化后得到的值:{"age":18,"birthday":"2000-06-11","skill":"牛牛冲击"} data, err := json.Marshal(monster) if err != nil { fmt.Println("序列化失败:",err) } // struct序列化结果 fmt.Println(string(data)) // 返回值(字段小写):{"name":"sudada","age":18,"birthday":"2000-06-11","skill":"牛牛冲击"} } func main() { testStruct() }
3.2、map-序列化
package main import ( "encoding/json" "fmt" ) // map序列化 func mapTest() { var a map[string]interface{} a = make(map[string]interface{}) a["name"]="sudada" a["age"]="18" a["skill"]="丢丢" // map序列化 data, err := json.Marshal(a) if err != nil { fmt.Println("序列化失败:",err) } fmt.Println(string(data)) // 返回值:{"age":"18","name":"sudada","skill":"丢丢"} } func main() { mapTest() }
3.3、切片-序列化
package main import ( "encoding/json" "fmt" ) // 切片序列化 func testSlice() { // 切片内有多个map var slice []map[string]interface{} var m1 map[string]interface{} m1 = make(map[string]interface{}) m1["name"]="sudada" m1["age"]="18" m1["skill"]="丢丢" slice = append(slice, m1) fmt.Println(slice) // 返回值:[map[age:18 name:sudada skill:丢丢]] // 切片序列化 data, err := json.Marshal(slice) if err != nil { fmt.Println("序列化失败:",err) } fmt.Println(string(data)) // 返回值:[{"age":"18","name":"sudada","skill":"丢丢"}] } func main() { testSlice() }
3.4、反序列化(将json格式的数据,转换为"结构体,map,切片")
在反序列化一个json数据时,要确保反序列化后的数据类型和原来序列化前的数据类型一致。
反序列化快速入门:err := json.Unmarshal([]byte(str),&slice)
str == json格式的数据
slice == 被反序列化的格式(结构体,map,切片)
3.4.1、结构体-反序列化
json数据的key,需要和结构体字段保持完全一致
package main import ( "encoding/json" "fmt" ) type Monster struct { Name string Age int Birthday string Skill string } func test() { // 结构体变量 var monster Monster // 将json格式的数据,反序列化为struct str := "{\"name\":\"sudada\",\"age\":18,\"birthday\":\"2000-06-11\",\"skill\":\"牛牛冲击\"}" // 反序列化 err := json.Unmarshal([]byte(str), &monster) if err != nil { fmt.Println("反序列化失败",err) } fmt.Println(monster) // 返回值:{sudada 18 2000-06-11 牛牛冲击} } func main() { test() }
3.4.2、map-反序列化
package main import ( "encoding/json" "fmt" ) func main() { // 将json格式的数据,反序列化为map str := "{\"age\":\"18\",\"name\":\"sudada\",\"skill\":\"丢丢\"}" // 定义map var a map[string]interface{} // 反序列化map时,不需要make,因为make操作在Unmarshal函数内已经自动执行了 err := json.Unmarshal([]byte(str),&a) if err != nil { fmt.Println("反序列化失败",err) } fmt.Println(a) // 返回值:map[age:18 name:sudada skill:丢丢] }
3.4.2、切片-反序列化
package main import ( "encoding/json" "fmt" ) func main() { // 将json格式的数据,反序列化为切片 str := "[{\"age\":\"18\",\"name\":\"sudada\",\"skill\":\"丢丢\"}]" // 定义切片 var slice []map[string]interface{} // 反序列化切片 err := json.Unmarshal([]byte(str),&slice) if err != nil { fmt.Println("反序列化失败",err) } fmt.Println(slice) // 返回值:[map[age:18 name:sudada skill:丢丢]] }
1.反射可以在运行时,动态获取变量的各种信息,比如变量的类型,类别。