天天看點

go入門篇 (4)一、檔案的操作二、指令行參數三、json四、單元測試

go入門篇4

  • 一、檔案的操作
    • 1.1 流
    • 1.2 打開關閉檔案
    • 1.3 使用緩沖區讀取檔案
    • 1.4 一次性讀取檔案
    • 1.5 寫入檔案
    • 1.6 寫的模式
    • 1.7 判斷檔案是否存在
    • 1.8複制檔案
    • 1.9 複制圖檔
    • 1.10 統計檔案中的字母和數字
  • 二、指令行參數
    • 2.1 os.Args
    • 2.2 舉例
    • 2.3 flag包解析指令行參數
  • 三、json
    • 3.1結構體序列化
    • 3.2 map序列化
    • 3.3 json.Marshal(para)
    • 3.4 切片的序列化
    • 3.4 基本類型的序列化
    • 3.5 改變json序列化後的key
    • 3.6 結構體反序列化
    • 3.7 map反序列化
  • 四、單元測試
    • 4.1 簡單的案例
    • 4.2 單元測試注意的點

一、檔案的操作

1.1 流

  • 輸入流

    資料從資料源(檔案)到程式(記憶體)的路徑

  • 輸出流

    資料從程式(記憶體)到資料源(檔案)的路徑

1.2 打開關閉檔案

func main(){
	file, err := os.Open("F:\\a.txt")
	if err != nil{
		fmt.Println("打開檔案出錯")
	}else {
		fmt.Printf("file=%v", file)
	}
	//關閉檔案
	err1 :=file.Close()
	if err != nil{
		fmt.Println("關閉檔案出錯",err1)
	}
}

           

1.3 使用緩沖區讀取檔案

func main(){
	file, err := os.Open("F:\\a.txt")
	if err != nil{
		fmt.Println("打開檔案出錯")
	}
    //defer:函數要退出時,會調用後面的内容
	defer file.Close()
	reader := bufio.NewReader(file)
	for{
		//讀到換行符就截至,每行都有換行符
		str, err := reader.ReadString('\n')
        if err == io.EOF{
			fmt.Println("已經讀到檔案的末尾了")
			break
		}
		fmt.Println(str)
	}
}

           

1.4 一次性讀取檔案

  • open和close都被封裝到ReadFile中了
func main(){
	file := "f://a.txt"
	content, err := ioutil.ReadFile(file)
	if err != nil{
		fmt.Println("讀取的檔案出錯",err)
	}
	//content是位元組類型的數組
	fmt.Println(string(content))
}
           

1.5 寫入檔案

func main(){
	filename := "f://a.txt"
	file, err := os.OpenFile(filename, os.O_WRONLY | os.O_CREATE, 0666 )
    if err != nil{
		fmt.Println("打開檔案出錯")
		return
	}
	defer file.Close()
	str := "hello, my daday"
	writer :=bufio.NewWriter(file)
	writer.WriteString(str)
	//write是寫入緩存中的,flush是寫入到檔案中
	writer.Flush()
	fmt.Println("寫入成功")
}
           

1.6 寫的模式

  • 删除源檔案的美容
os.O_WRONLY | os.O_TRUNC
           
  • 在源檔案内容基礎上追加
os.O_WRONLY | os.O_APPEND
           

1.7 判斷檔案是否存在

func judgaFile(filePath string){
	_,err := os.Stat(filePath)
	if err == nil{
		fmt.Println("檔案存在")
		return
	}
	if os.IsNotExist(err) {
		fmt.Println("檔案不存在")
		return
	}
	fmt.Println("不确定檔案存在不存在")

}
func main(){
	pathName := "f://a1.txt"
	judgaFile(pathName)
}
           

1.8複制檔案

func main(){
	sourceFille := "f://a.txt"
	goalFile := "f://c.txt"
	data, err := ioutil.ReadFile(sourceFille)
    if err != nil{
		fmt.Println("讀取檔案出錯")
		return
	}
	err1 := ioutil.WriteFile(goalFile, data, 0666)
	if err1 != nil{
		fmt.Println("讀取檔案出錯")
	}
}
           

1.9 複制圖檔

func copyFile(resFile string, desFile string)(written64 int64, err error){
	newSrcFile, err := os.Open(resFile)
	if err != nil{
		fmt.Println("打開源檔案錯誤")
		return
	}
	newDesFile, err :=os.OpenFile(desFile, os.O_WRONLY | os.O_CREATE, 0666)
	if err != nil{
		fmt.Println("打開目标檔案錯誤")
		return
	}
	defer newSrcFile.Close()
	defer newDesFile.Close()
	reader := bufio.NewReader(newSrcFile)
	writer := bufio.NewWriter(newDesFile)
	return io.Copy(writer, reader)


}
func main(){
	srcFille := "f://a.jpg"
	desFille := "f://a1.jpg"
	copyFile(srcFille, desFille)

}
           

1.10 統計檔案中的字母和數字

func main() {
	srcFille := "f://test.doc"
	var numCount int
	var wordCount int
	file, err := os.Open(srcFille)
	if err != nil {
		fmt.Println("打開檔案錯誤")
	}
	reader := bufio.NewReader(file)
	for {
		//讀到\n停止
		str, err := reader.ReadString('\n')
		if err == io.EOF {
			fmt.Println("結束")
			break
		}
		//周遊每一行的内容
		for _, value := range str {
			switch {
			case value >= 'a' && value <= 'z':
				fallthrough
			case value >= 'A' && value <= 'Z':
				wordCount++
			case value >= '0' && value <= '9':
				numCount++
			}
		}
	}
	fmt.Println(wordCount, numCount)
}
           

二、指令行參數

2.1 os.Args

存儲指令行參數

2.2 舉例

func main(){
	length := len(os.Args)
	fmt.Println(length)
	for k, v := range os.Args{
		fmt.Println(k , v)
	}
}
           
go入門篇 (4)一、檔案的操作二、指令行參數三、json四、單元測試
結果:
2
0 C:\Users\Administrator\AppData\Local\Temp\GoLand\___2go_build_file_go.exe
1 wqeqw:2323,sadas:2324.adas:2343
           

2.3 flag包解析指令行參數

func main(){
	var port int
	var name string
	flag.StringVar(&name,"u","","使用者名")
	flag.IntVar(&port,"p",3306,"端口号")
	flag.Parse()
	fmt.Println(name, port)
}
           
go入門篇 (4)一、檔案的操作二、指令行參數三、json四、單元測試
結果:
ybx 2344

           

三、json

3.1結構體序列化

  • 結構體屬性名如果第一個字母小寫,則不會被序列化,大寫才會被序列化
type Student struct {
	//注意:如果屬性小寫,則序列化不了,序列化的結果就是空
	name string
	Age int
	Address string
	Hobby []string
}
func main(){
	var stu Student = Student{
		name:"jack",
		Age:23,
		Address:"西安",
		Hobby:[]string{
			"basketball","football","ping-pong","eat",
		},
	}
	res, err := json.Marshal(&stu)
	if err != nil{
		fmt.Println("序列化失敗")
		return
	}
	fmt.Println(string(res))
}
           

3.2 map序列化

type Student struct {
	//注意:如果屬性小寫,則序列化不了,序列化的結果就是空
	name string
	Age int
	Address string
	Hobby []string
}
func main(){
	var stu Student = Student{
		name:"jack",
		Age:23,
		Address:"西安",
		Hobby:[]string{
			"basketball","football","ping-pong","eat",
		},
	}
	var mymap map[string]interface{} = make(map[string]interface{})
	mymap["name"] = "jack"
	mymap["age"] = 36
	mymap["stu"] = stu
	res, err := json.Marshal(mymap)
	if err != nil{
		fmt.Println("序列化失敗")
		return
	}
	fmt.Println(string(res))
}
           

3.3 json.Marshal(para)

注意para是引用類型

3.4 切片的序列化

type Student struct {
	//注意:如果屬性小寫,則序列化不了,序列化的結果就是空
	name string
	Age int
	Address string
	Hobby []string
}
func main(){
	var stu Student = Student{
		name:"jack",
		Age:23,
		Address:"西安",
		Hobby:[]string{
			"basketball","football","ping-pong","eat",
		},
	}
	var mymap []map[string]interface{}
	var mymap1 map[string]interface{} = make(map[string]interface{})
	var mymap2 map[string]interface{} = make(map[string]interface{})
	mymap1["name"] = "jack"
	mymap1["age"] = 36
	mymap1["stu"] = stu
	mymap2["name"] = "jack"
	mymap2["age"] = 36
	mymap2["stu"] = stu
	mymap = append(mymap, mymap2)
	mymap = append(mymap,mymap1)
	res, err := json.Marshal(mymap)
	if err != nil{
		fmt.Println("序列化失敗")
		return
	}
	fmt.Println(string(res))
}
           

3.4 基本類型的序列化

  • 基本類型的序列化沒有什麼意義
func main() {
	var num int = 23
	res, err := json.Marshal(num)
	if err != nil{
		fmt.Println("序列化出錯")
	}
	fmt.Println(string(res))
}

           

3.5 改變json序列化後的key

type Student struct {
	//注意:如果屬性小寫,則序列化不了,序列化的結果就是空
	name string`json:"stu_name"`
	Age int	`json:"stu_age"`
	Address string`json:"stu_address"`
	Hobby []string
}
           

3.6 結構體反序列化

func main(){
    str := "{\"stu_age\":23,\"stu_address\":\"西安\",\"Hobby\":[\"basketball\",\"football\",\"ping-pong\",\"eat\"]}"
	var stu1 Student
	err1 := json.Unmarshal([]byte(str), &stu1)
	if err1!= nil{
		fmt.Println("反序列化出錯")
	}
	fmt.Println(stu1.name,stu1.Age, stu1.Hobby,stu1.Address)
}
           

3.7 map反序列化

  • map反序列化會自動make,不需要自己make
func main(){
	var stu Student = Student{
		name:"jack",
		Age:23,
		Address:"西安",
		Hobby:[]string{
			"basketball","football","ping-pong","eat",
		},
	}
	var mymap map[string]interface{} = make(map[string]interface{})
	mymap["name"] = "ybx"
	mymap["age"] = 12
	mymap["stu"] = stu
	res, err := json.Marshal(mymap)
	if err != nil{
		fmt.Println("序列化失敗")
		return
	}
	var mymap2 map[string]interface{}
	err1 := json.Unmarshal(res, &mymap2)
	if err1!= nil{
		fmt.Println("反序列化出錯")
	}
	fmt.Println(mymap2)
}
           

四、單元測試

4.1 簡單的案例

package test

import "testing"

//注意測試函數嚴格符合一定的命名規範
func TestCal(t *testing.T){
	//調用被測試的函數
	res := cal()
	if res != 45{
		t.Fatal("測試結果與期望結果不符")
	}
	t.Logf("執行結果正确")
}
           
結果:
=== RUN   TestCal
45
    cal_test.go:12: 執行結果正确
--- PASS: TestCal (0.00s)
PASS

           

4.2 單元測試注意的點

  • 測試函數的命名時:Test+函數名大寫,也可以是其他的名稱,但是名稱首字母必須大寫
  • 測試檔案的命名是:被測試的檔案名+_test