?🎁個人主頁:星云愛編程
?🔍所屬專欄:【Go】?
🎉歡迎大家點贊👍評論📝收藏?文章
?長風破浪會有時,直掛云帆濟滄海
目錄
1.文件操作
1.1文件介紹
1.2.文件流
1.3.打開和關閉文件
1.4.讀文件操作
1.5.寫文件操作
1.6判斷文件是否存在
1.7拷貝文件
2.flag解析命令行參數
2.1.命令行參數基本使用
2.2flag包解析命令行參數
?2.3flag包處理命令行參數
3.json處理
3.1JSON介紹
3.2Json數據格式說明
3.3JSON序列化
3.4JSON反序列化
結語
1.文件操作
1.1文件介紹
文件是保存數據的地方,例如word文檔、txt文本文件,excel文件等都是文件。文件能保存圖片,視屏,音頻等。
1.2.文件流
文件在程序中是以流的形式來操作的:
流:數據在數據源(文件)和程序(內存)之間經歷的路程。
輸入流:數據從數據源(文件)到程序(內存)的路徑。
輸出流:數據從程序(內存)到數據源(文件)的路徑。?
1.3.打開和關閉文件
打開文件用到的方法:
(1)默認文件模式:
(2) 可指定文件模式:
?其flag可為的常量:
const (O_RDONLY int = syscall.O_RDONLY // 只讀模式打開文件O_WRONLY int = syscall.O_WRONLY // 只寫模式打開文件O_RDWR int = syscall.O_RDWR // 讀寫模式打開文件O_APPEND int = syscall.O_APPEND // 寫操作時將數據附加到文件尾部O_CREATE int = syscall.O_CREAT // 如果不存在將創建一個新文件O_EXCL int = syscall.O_EXCL // 和O_CREATE配合使用,文件必須不存在O_SYNC int = syscall.O_SYNC // 打開文件用于同步I/OO_TRUNC int = syscall.O_TRUNC // 如果可能,打開時清空文件
)
?關閉文件用到的方法:
使用案例:
package main
import ("fmt""os"
)func main(){//文件路徑path:="D:/goProject/src/basic/io/main/text/a.txt"//打開文件file ,err:=os.Open(path)if err!=nil{//打開失敗fmt.Printf("open err:%v\n",err)}//輸出文件,看看會輸出什么?fmt.Printf("%v",file)//&{0xc00008c6c8}err=file.Close()if err!=nil{//關閉失敗fmt.Printf("close err:%v\n",err)}
}
說明:
- Open方法和Close方法都在os包下,使用時要導入os包
- file就是個指針
1.4.讀文件操作
(1)帶緩沖讀文件
package main
import ("fmt""os""bufio""io"
)func main(){path:="D:/goProject/src/basic/io/main/text/a.txt"file ,err:=os.Open(path)if err!=nil{//打開失敗fmt.Printf("open err:%v\n",err)}defer file.Close()// 創建一個 *Reader,是帶緩沖的/*const(defaultBufsize= 4096 //默認的緩沖區為4096)*/readr:=bufio.NewReader(file)//循環的讀取文件的內容for{str,err:=readr.ReadString('\n')//讀取到\n就結束,即一行一行的讀if err==io.EOF{//io.EOF表示文件的末尾break}//輸出內容fmt.Print(str)}fmt.Println("\n文件讀取結束")
}
(2)一次性讀文件
案例:
package main
import("fmt""io/ioutil"
)func main(){//文件路徑path:="D:/goProject/src/basic/io/main/text/a.txt"//一次性讀取文件content,err:=ioutil.ReadFile(path)if err!=nil{fmt.Println("read err:",err)}// fmt.Println(content) 此時輸出的是byte[],得用string轉化才能輸出原內容 fmt.Println(string(content))//我們沒有顯式的open文件,因此也不需要顯式的close文件//因為,文件的open和close被封裝到 ReadFile 函數內部
}
1.5.寫文件操作
(1)創建新文件并寫入數據
package main
import ("fmt""os""bufio"
)func main(){//文件路徑path:="D:/goProject/src/basic/io/main/text/b.txt"//打開文件file,err:=os.OpenFile(path,os.O_WRONLY | os.O_CREATE,0666)if err!=nil{fmt.Println("open err:",err)return}//最后關閉file文件defer file.Close()//寫入內容str:="好好學習,天天向上"//用帶緩存的*writer寫入writer:=bufio.NewWriter(file)for i:=0;i<5;i++{writer.WriteString(str)writer.WriteString("\n") // 添加換行}//因為writer是帶緩存的,因此在調用WriteString時//是先將內容寫入到緩存中,所以需要用Flush方法//將緩存的數據真正的寫入到文件中,否則文件中會沒有數據writer.Flush()fmt.Println("寫入完成")
}
(2)打開原有文件,將原內容覆蓋寫入
package main
import ("fmt""os""bufio"
)func main(){//文件路徑path:="D:/goProject/src/basic/io/main/text/b.txt"//打開原有文件file,err:=os.OpenFile(path,os.O_WRONLY | os.O_TRUNC,0666)if err!=nil{fmt.Println("open err:",err)return}//最后關閉file文件defer file.Close()//寫入內容str:="溫故而知新,可以為師矣"//用帶緩存的*writer寫入writer:=bufio.NewWriter(file)for i:=0;i<5;i++{writer.WriteString(str) writer.WriteString("\n") // 添加換行}//因為writer是帶緩存的,因此在調用WriteString時//是先將內容寫入到緩存中,所以需要用Flush方法//將緩存的數據真正的寫入到文件中,否則文件中會沒有數據writer.Flush()fmt.Println("寫入完成")
}
?(3)打開原有文件,在原文件上追加寫入
package main
import ("fmt""os""bufio"
)func main(){//文件路徑path:="D:/goProject/src/basic/io/main/text/b.txt"//打開原有文件file,err:=os.OpenFile(path,os.O_WRONLY | os.O_APPEND,0666)if err!=nil{fmt.Println("open err:",err)return}//最后關閉file文件defer file.Close()//寫入內容str:="實迷途其未遠,覺今是而昨非"//用帶緩存的*writer寫入writer:=bufio.NewWriter(file)for i:=0;i<5;i++{writer.WriteString(str) writer.WriteString("\n") // 添加換行}//因為writer是帶緩存的,因此在調用WriteString時//是先將內容寫入到緩存中,所以需要用Flush方法//將緩存的數據真正的寫入到文件中,否則文件中會沒有數據writer.Flush()fmt.Println("寫入完成")
}
?(4)打開原有文件,并進行讀和寫操作
package main
import ("fmt""os""bufio""io"
)func main(){//文件路徑path:="D:/goProject/src/basic/io/main/text/b.txt"//打開原有文件file,err:=os.OpenFile(path,os.O_RDWR | os.O_APPEND,0666)if err!=nil{fmt.Println("open err:",err)return}//最后關閉file文件defer file.Close()//讀操作reader:=bufio.NewReader(file)for{str1,err:=reader.ReadString('\n')if err==io.EOF{break}fmt.Print(str1)}//寫操作//寫入內容str:="故有之以為用,無之以為利"//用帶緩存的*writer寫入writer:=bufio.NewWriter(file)for i:=0;i<5;i++{writer.WriteString(str) writer.WriteString("\n") // 添加換行}//因為writer是帶緩存的,因此在調用WriteString時//是先將內容寫入到緩存中,所以需要用Flush方法//將緩存的數據真正的寫入到文件中,否則文件中會沒有數據writer.Flush()fmt.Println("寫入完成")
}
1.6判斷文件是否存在
golang判斷文件或文件夾是否存在的方法為使用os.Stat()函數返回的錯誤值進行判斷:
- 如果返回的錯誤為nil,說明文件或文件夾存在
- 如果返回的錯誤類型使用os.IsNotExist()判斷為true,說明文件或文件夾不存在
- 如果返回的錯誤為其它類型,則不確定是否在存在
package main
import ("fmt""os""bufio"
)func main(){//文件路徑path:="D:/goProject/src/basic/io/main/text/b.txt"// 檢查文件是否存在if _, err := os.Stat(path); os.IsNotExist(err) {fmt.Println("文件不存在,將創建新文件")} else if err != nil {fmt.Println("檢查文件出錯:", err)return} else {fmt.Println("文件已存在,將追加內容")}
}
1.7拷貝文件
package main
import ("fmt""os""io"
)func CopyFile(srcPath, destPath string)(written int64, err error){// 打開源文件src, err := os.Open(srcPath)if err != nil{return 0, fmt.Errorf("打開源文件錯誤: %v", err)}defer src.Close()// 創建目標文件dest, err := os.Create(destPath)if err != nil{return 0, fmt.Errorf("創建目標文件錯誤: %v", err)}defer dest.Close()// 復制文件內容return io.Copy(dest, src)
}func main(){srcPath := "D:\\goProject\\src\\basic\\io\\main\\c.jpg"destPath := "D:\\goProject\\src\\basic\\io\\main\\text\\copy.jpg"written, err := CopyFile(srcPath, destPath)if err != nil {fmt.Println("復制失敗:", err)return}fmt.Printf("成功復制 %d 字節\n", written)
}
2.flag解析命令行參數
2.1.命令行參數基本使用
package main
import ("fmt""os"
)func main(){fmt.Println("命令行參數有",len(os.Args))//遍歷命令行參數for i,v:=range os.Args{fmt.Printf("args[%v]=%v\n",i,v)}}
2.2flag包解析命令行參數
前面的方式是比較原生的方式,對解析參數不是特別的方便,特別是帶有指定參數形式的命令行;
Go提供了flag包,可以方便的解析命令行參數,并且參數順序可以隨意
package main
import("fmt""flag"
)func main(){//定義幾個變量,用于接受命令行的參數值var user stringvar pwd stringvar host stringvar port int//此例子用于mysql的連接/*func (f *FlagSet) StringVar(p *string, name string, value string, usage string)String用指定的名稱、默認值、使用信息注冊一個string類型flag。返回一個保存了該flag的值的指針。*/// u就是-u指定參數// ""為-u指定參數的默認值//"用戶名,默認為空" -說明flag.StringVar(&user,"u","","用戶名,默認為空")flag.StringVar(&pwd,"pwd","","密碼,默認為空")flag.StringVar(&host,"h","localhost","主機名,默認為localhost")flag.IntVar(&port,"port",3306,"端口號,默認為3306")//這里有一個非常重要的操作,轉換,必須調用該方法flag.Parse()//輸出結果fmt.Printf(" user=%v\n pwd=%v\n host=%v\n port=%v\n",user,pwd,host,port)
}
?2.3flag包處理命令行參數
package mainimport ("flag""fmt"
)func main() {// 定義命令行參數name := flag.String("name", "Guest", "用戶姓名")age := flag.Int("age", 18, "用戶年齡")verbose := flag.Bool("v", false, "是否顯示詳細信息")// 解析命令行參數flag.Parse()// 使用解析后的參數fmt.Printf("姓名: %s\n", *name)fmt.Printf("年齡: %d\n", *age)if *verbose {fmt.Println("顯示詳細信息")}
}
說明:
(1)定義參數:
- ?flag.String() :定義字符串類型參數
- flag.Int() :定義整數類型參數
- flag.Bool() :定義布爾類型參數
(2)參數解析
- flag.Parse() :解析命令行參數
(3)使用參數
- 通過 * 解引用獲取參數值
3.json處理
3.1JSON介紹
JSON(JavaScript Object Notation)是一種輕量級的數據交換格式,易于人閱讀和編寫,同時也易于機器解析和生成
JSON是在2001年開始推廣使用的數據格式,目前已經成為主流的數據格式。
JSON易于機器解析和生成,并有效地提升網絡傳輸效率,通常程序在網絡傳輸時會先將數據(結構體、map等)序列化成json字符串,到接收方得到json字符串時,在反序列化恢復成原來的數據類型(結構體、map等)。這種方式已然成為各個語言的標準。
3.2Json數據格式說明
在JS語言中,一切都是對象,因此任何的數據類型都可以通過JSON來表示
JSON鍵值對是用來保存數據的一種方式,鍵值對組合中的鍵名寫在前面并用雙引號""包裹,使用冒號:分隔,然后緊接著值
基本結構:
(1)對象:用 {} 表示,包含鍵值對
{"name": "Alice","age": 25
}
(2)數組:用 [] 表示,包含多個值?
["apple", "banana", "orange"]
(3)值 :可以是字符串、數字、布爾值、null、對象或數組
?JSON在線解析:?JSON在線解析
3.3JSON序列化
JSON序列化是將對應的數據結構(例如struct,map,slice)轉換為JSON格式字符串的過程。
案例:
package main
import("fmt""encoding/json"
)type Stu struct{Name stringAge intGender stringScore float64Phone string
}
//將結構體序列化
func testStruct(){stu:=Stu{Name:"jack",Age: 12,Gender: "男",Score:85.6,Phone:"1581689988",}//將stu序列化data,err:=json.Marshal(&stu)if err!=nil{panic(err)}//輸出序列化后的結果fmt.Println(string(data))//{"Name":"jack","Age":12,"Gender":"男","Score":85.6,"Phone":"1581689988"}
}//將map序列化
func testMap(){//定義一個mapvar a map[string]interface{}//使用map前,需要makea = make(map[string]interface{})a["name"]="李星云"a["age"]=21a["skill"]="九幽玄天神功"a["lover"]="姬如雪"a["address"]="長安"//將a序列化data,err:=json.Marshal(a)if err!=nil{panic(err)}//輸出序列化的結果fmt.Println(string(data))//{"address":"長安","age":21,"lover":"姬如雪","name":"李星云","skill":"九幽玄天神功"}}//對切片序列化
func testSlice(){var slice []map[string]interface{}var a map[string]interface{}//使用map前,需要makea = make(map[string]interface{})a["name"]="李星云"a["age"]=21a["skill"]="九幽玄天神功"a["lover"]="姬如雪"a["address"]="長安"var b map[string]interface{}//使用map前,需要makeb = make(map[string]interface{})b["name"]="姬如雪"b["age"]=19b["skill"]="幻音訣"b["lover"]="李星云"b["address"]="幻音坊"//將a,b添加到slice中slice=append(slice,a)slice=append(slice,b)//將切片進行序列化操作data,err:=json.Marshal(slice)if err!=nil{panic(err)}//輸出序列化結果fmt.Println(string(data))//[{"address":"長安","age":21,"lover":"姬如雪","name":"李星云","skill":"九幽玄天神功"},{"address":"幻音坊","age":19,"lover":"李星云","name":"姬如雪","skill":"幻音訣"}]
}//對基本數據類型進行序列化
//對基本數據類型進行序列化意義不大
func testFloat64(){var num float64=3.1415926535//對num進行序列化data,err:=json.Marshal(num)if err!=nil{panic(err)}//輸出序列化后的結果fmt.Println(string(data))
}func main(){testStruct()testMap()testSlice()testFloat64()
}
注意事項:
- 結構體字段首字母必須大寫,否則無法被序列化
- 若想讓序列化后的結構體字段首字母小寫,可以使用tag標簽
- 可以使用 json:",omitempty" 標簽來忽略空值字段
- 可以使用 json:"-" 標簽來忽略某個字段
3.4JSON反序列化
JSON反序列化是將JSON格式字符串轉換為對應的數據結構(例如struct,map,slice)的過程
package main
import("fmt""encoding/json"
)type Stu struct{Name stringAge intGender stringScore float64Phone string
}//演示將json字符串,反序列化為struct
func unmarshalStruct(){str:="{\"Name\":\"jack\",\"Age\":12,\"Gender\":\"男\",\"Score\":85.6,\"Phone\":\"1581689988\"}"//定義一個Stu實例var stu Stuerr:=json.Unmarshal([]byte(str),&stu)if err!=nil{panic(err)}//輸出反序列化后的strfmt.Println(stu)
}//演示將json字符串,反序列化為map
func unmarshalMap(){str:=`{"address":"長安","age":21,"lover":"姬如雪","name":"李星云","skill":"九幽玄天神功"}`//定義一個map實例var a map[string]interface{}err:=json.Unmarshal([]byte(str),&a)if err!=nil{panic(err)}//輸出反序列化后的strfmt.Println(a)
}//演示將json字符串,反序列化為slice
func unmarshalSlice(){str:=`[{"address":"長安","age":21,"lover":"姬如雪","name":"李星云","skill":"九幽玄天神功"},{"address":"幻音坊","age":19,"lover":"李星云","name":"姬如雪","skill":"幻音訣"}]`//定義一個slice實例var slice []map[string]interface{}//進行反序列化err:=json.Unmarshal([]byte(str),&slice)if err!=nil{panic(err)}//輸出反序列化后的結果fmt.Println(slice)
}func main(){unmarshalStruct()unmarshalMap()unmarshalSlice()
}
說明:
(1)在反序列化一個json字符串時,要確保反序列化后的數據類型和原來序列化前的數據類型一致。
(2)如果json字符串是通過程序獲取到的,則不需要再對"進行轉義處理
結語
感謝您的耐心閱讀,希望這篇博客能夠為您帶來新的視角和啟發。如果您覺得內容有價值,不妨動動手指,給個贊👍,讓更多的朋友看到。同時,點擊關注🔔,不錯過我們的每一次精彩分享。若想隨時回顧這些知識點,別忘了收藏?,讓知識觸手可及。您的支持是我們前進的動力,期待與您在下一次分享中相遇!