ir sistema de linguagem - a partir do teste de unidade de operação de arquivo


Operações de arquivo

Arquivo é uma fonte de dados (onde o salvamento de dados), como documento utilizado com frequência palavra, txt documento, arquivo excel ... é um arquivo. O papel principal é salvar o arquivo de dados, ou seja, ele pode salvar uma imagem, você também pode guardar o vídeo, som ...

Os fluxos de entrada e de saída

Forma de um arquivo de fluxo é operado no programa

stream: caminho de dados entre uma fonte de dados (arquivos) e do programa (memória) experimentaram

fluxo de entrada: o caminho de dados a partir de uma fonte de dados (arquivos) para o programa (de memória)

fluxos de saída: um caminho de dados do programa (memória) para a fonte de dados (arquivo)

todos os arquivos relacionados operações de embalagem os.File, a estrutura do arquivo é um

operação de volta arquivo, muitas vezes usado para estruturar os.File

Abra o arquivo e feche o arquivo

Funções e métodos de utilização


apresentação do caso

import (
   "fmt"
   "os"
)

func main()  {
   //打开文件
   //概念说明:file的叫法
   //1. file 叫 file对象
   //2. file 叫 file指针
   //3. file 叫 file文件句柄
   file, err := os.Open("e:/test.txt")
   if err != nil {
      fmt.Println("Open file err = ", err)
   }
   //输出文件,看看文件是什么,看出file就是一个指针 *Filr
   fmt.Printf("file = %v", file)   //file = &{0xc000070780}
   //关闭
   err = file.Close()
   if err != nil {
      fmt.Println("Close file err = ", err)
   }
}

Leia Applications operação de arquivo

  1. Lendo o conteúdo do ficheiro e exibido no (modo tampão banda) do terminal, utilizando os.Open, File.Close, bufio.NewReader (), reader.ReadString funções e métodos
import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main()  {
	//打开文件
	//概念说明:file的叫法
	//1. file 叫 file对象
	//2. file 叫 file指针
	//3. file 叫 file文件句柄
	file, err := os.Open("E:/gostudent/src/2020-04-02/utils/utils.go")
	if err != nil {
		fmt.Println("Open file err = ", err)
	}
	//当函数退出时,要及时的关闭file
	defer file.Close() //要及时关闭file句柄,否则会有内存泄漏
	//创建一个*Reader , 是带缓冲的
	/*
	   const (
	      defaultBufSize = 4096  //默认的缓冲区为4096
	   )
	*/
	reader := bufio.NewReader(file)
	//循环读取文件的内容
	for {
		str, err := reader.ReadString('\n')  //读到一个换行就结束
		if err == io.EOF {      //io.EOF 表示文件的末尾
			break
		}
		//输出内容
		fmt.Print(str)
	}
	fmt.Println("文件读取结束...")
}
  1. Lendo o conteúdo do arquivo e exibida no terminal (usando ioutil uma vez todo o arquivo é lido na memória), este método é aplicável ao caso de pequenos arquivos. métodos e funções relacionadas ioutil.ReadFile
import (
	"fmt"
	"io/ioutil"
)

func main()  {
	//使用ioutil.ReadFile一次性将文件读取到位
	file := "E:/gostudent/src/2020-04-02/utils/utils.go"
	content, err := ioutil.ReadFile(file)
	if err != nil {
		fmt.Printf("read file err = %v", err)
	}
	//把读取到的内容显示到终端
	//fmt.Printf("%v", content) //[]byte
	fmt.Printf("%v", string(content)) // []byte
	//这里没有显示的Open文件,因此也不需要显示的Close文件
	//因为,文件的Open和Close被封装到ReadFile函数内部
}

Aplicações operação de arquivo de gravação

função os.OpenFile

  1. Criar um novo arquivo, escreva para: 5 "Olá, zisefeizhu"
import (
	"bufio"
	"fmt"
	"os"
)

func main()  {
	filePath := "E:/gostudent/src/2020-04-05/abc.txt"
	file, err := os.OpenFile(filePath, os.O_CREATE | os.O_WRONLY, 0666)
	if err != nil {
		fmt.Printf("open file err = %v \n", err)
		return
	}
	//及时关闭file句柄
	defer file.Close()
	//准备写入5句: "hello,zisefeizhu"
	str := "hello,zisefeizhu\n" // \n表示换行
	//写入时,使用带缓存的*Writer
	writer := bufio.NewWriter(file)
	for i := 0; i< 5; i++ {
		writer.WriteString(str)
	}
	//因为write是带缓存的,因此在调用WriterString方法时
	//其实内容是先写入到缓存的,所以需要调用Flush方法,将缓冲的数据
	//真正写入到文件中,否则文件中会没有数据!!!
	writer.Flush()
}
  1. Abra um arquivo existente, o conteúdo original cobrindo o novo conteúdo em 10 "Olá, roxo Flying Pig"
import (
   "bufio"
   "fmt"
   "os"
)

func main()  {
   //2)打开一个存在的文件,将原来的内容覆盖成新的内容10句“你好,紫色飞猪”
   //1. 打开已经存在的文件E:/gostudent/src/2020-04-05/abc.txt
   filePath := "E:/gostudent/src/2020-04-05/abc.txt"
   file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_TRUNC, 0666)
   if err != nil {
      fmt.Printf("open file err = %v \n", err)
      return
   }
   //及时关闭file句柄
   defer file.Close()
   //准备写入10句: "hello,zisefeizhu"
   str := "你好,紫色飞猪!\n" // \n表示换行
   //写入时,使用带缓存的*Writer
   writer := bufio.NewWriter(file)
   for i := 0; i< 10; i++ {
      writer.WriteString(str)
   }
   //因为write是带缓存的,因此在调用WriterString方法时
   //其实内容是先写入到缓存的,所以需要调用Flush方法,将缓冲的数据
   //真正写入到文件中,否则文件中会没有数据!!!
   writer.Flush()

}
  1. Abra um arquivo existente, anexar o conteúdo do original "Olá, jingxing"
import (
   "bufio"
   "fmt"
   "os"
)

func main()  {
   //1. 打开已经存在的文件E:/gostudent/src/2020-04-05/abc.txt
   filePath := "E:/gostudent/src/2020-04-05/abc.txt"
   file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_APPEND, 0666)
   if err != nil {
      fmt.Printf("open file err = %v \n", err)
      return
   }
   //及时关闭file句柄
   defer file.Close()
   //追加内容
   str := "你好,jingxing\n" // \n表示换行
   //写入时,使用带缓存的*Writer
   writer := bufio.NewWriter(file)
   for i := 0; i< 10; i++ {
      writer.WriteString(str)
   }
   //因为write是带缓存的,因此在调用WriterString方法时
   //其实内容是先写入到缓存的,所以需要调用Flush方法,将缓冲的数据
   //真正写入到文件中,否则文件中会没有数据!!!
   writer.Flush()
}
  1. Abra um arquivo existente, leia o conteúdo original exibida no terminal, e um adicional de 5 "Olá, Shenzhen"
import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main()  {
	//1. 打开已经存在的文件E:/gostudent/src/2020-04-05/abc.txt
	filePath := "E:/gostudent/src/2020-04-05/abc.txt"
	file, err := os.OpenFile(filePath, os.O_RDWR | os.O_APPEND, 0666)
	if err != nil {
		fmt.Printf("open file err = %v \n", err)
		return
	}
	//及时关闭file句柄
	defer file.Close()
	//先读取原来文件的内容,并显示在终端
	reader := bufio.NewReader(file)
	for {
		str, err := reader.ReadString('\n')
		if err == io.EOF {   //如果读取到文件的末尾
			break
		}
		//显示到终端
		fmt.Print(str)
	}
	//追加内容
	str := "你好,深圳\n" // \n表示换行
	//写入时,使用带缓存的*Writer
	writer := bufio.NewWriter(file)
	for i := 0; i< 5; i++ {
		writer.WriteString(str)
	}
	//因为write是带缓存的,因此在调用WriterString方法时
	//其实内容是先写入到缓存的,所以需要调用Flush方法,将缓冲的数据
	//真正写入到文件中,否则文件中会没有数据!!!
	writer.Flush()
}

5) Escreva um programa, o conteúdo de um arquivo, escreva para outro arquivo. Nota: Estes dois documentos têm existido

Nota: Use ioutil.ReadFile / ioutil.WriteFile completar a tarefa de escrever arquivos

import (
   "fmt"
   "io/ioutil"
)
func main()  {
   //将e:/abc.txt 文件内容导入到e:/abc.txt
   //1. 首先将 e:/abc.txt 内容读取到内存
   //2. 将读取到的内容写入d:/abc.txt
   file1Path := "E:/gostudent/src/2020-04-05/abc.txt"
   file2Path := "D:/abc.txt"
   data, err := ioutil.ReadFile(file1Path)
   if err != nil {
      //说明读取文件有错误
      fmt.Printf("read file err = %v\n", err)
      return
   }
   err = ioutil.WriteFile(file2Path, data, 0666)
   if err != nil {
      fmt.Printf("write file error = %v \n", err)
   }
}

Determinar se existe um arquivo

arquivo Go ou pasta é determinado se existe ou não é uma função método usando os.stat () retorna um valor de erro é determinada:

  1. Se um erro é retornado a zero, documentação ou pasta existe

  2. Se o tipo errado de retorno usado os.IsNotExist () determina verdade, descreveu o arquivo ou pasta não existe

  3. Se o retorno é um outro tipo de erro, é incerto se há

Exemplos de programação de aplicação de arquivo

Copiar arquivos

Descrição: A imagem / filmes / mp3 copiado para outro arquivo e: /abc.jpg

func Copy (dst Escritor, src Reader) (int64 escrita, erro err)

Nota: A função Copy é io pacote fornece

import (
   "bufio"
   "fmt"
   "io"
   "os"
)
//编写一个函数,接收两个文件路径 srcFileName dstFileName
func CopyFile(srcFileName string, dstFileName string) (written int64, err error) {
   srcFile, err := os.Open(srcFileName)
   if err != nil {
      fmt.Printf("open file err = %v\n", err)
   }
   defer  srcFile.Close()
   //通过srcfile,获取到Reader
   reader := bufio.NewReader(srcFile)
   //打开dstFileName
   dstFile,err := os.OpenFile(dstFileName, os.O_WRONLY | os.O_CREATE, 0666)
   if err != nil {
      fmt.Printf("open file err = %v\n", err)
      return
   }
   //通过dstFile,获取到Writer
   writer := bufio.NewWriter(dstFile)
   defer  dstFile.Close()
   return io.Copy(writer, reader)
}
func main()  {
   //将d:/abc.jpg 文件拷贝到e:/abc.jpg
   //调用CopyFile 完成文件拷贝
   srcFile := "d:/abc.jpeg"
   dstFile := "e:/abc.jpg"
   _, err := CopyFile(srcFile, dstFile)
   if err == nil {
      fmt.Printf("拷贝完成\n")
   } else {
      fmt.Printf("拷贝错误 err = %v\n", err)
   }
}

estatísticas inglesas, números, espaços e outro número de caracteres

import (
   "bufio"
   "fmt"
   "io"
   "os"
)
//定义一个结构体,用于保存统计结果
type CharCount struct {
   ChCount int //记录英文个数
   NumCount int //记录数字的个数
   SpaceCount int //记录空格的个数
   OtherCount int //记录其它字符的个数
}

func main()  {
   //思路:打开一个文件,创一个Reader
   //每读取一行,就去统计该行有多少个英文、数字、空格和其它字符
   //然后将结果保存到一个结构体
   fileName := "E:/gostudent/src/2020-04-05/abc.txt"
   file,err := os.Open(fileName)
   if err != nil {
      fmt.Printf("open file err = %v \n", err)
      return
   }
   defer  file.Close()
   //定义个CharCount实例
   var count CharCount
   //创建一个Reader
   reader := bufio.NewReader(file)
   //开始循环读取fleName的内容
   for {
      str, err := reader.ReadString('\n')
      if err == io.EOF { //读到文件末尾就退出
         break
      }
      //为了兼容中文字符,可以将str转成[]rune
      strChange := []rune(str)
      //遍历str,进行统计
      for _,v := range strChange {
         switch  {
         case v >= 'a' && v <= 'z' :
            fallthrough //穿透
         case v >= 'A' && v <= 'Z' :
            count.ChCount++
         case v == ' ' || v == '\t' :
            count.SpaceCount++
         case v >= '0' && v <= '9' :
            count.NumCount++
         default:
            count.OtherCount++
         }
      }
   }
   //输出统计的结果看看是否正确
   fmt.Printf("字符的个数为 = %v 数字的个数为 = %v 空格的个数为 = %v 其它字符个数 = %v",
      count.ChCount, count.NumCount, count.SpaceCount, count.OtherCount)
}

parâmetros de linha de comando

Nós estamos esperando para chegar aos vários parâmetros de linha de comando, como lidar com?

fatia os.Args é uma string, para armazenar todos os parâmetros de linha de comando

ilustração

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)
	}
}
//E:\gostudent\src\2020-04-05>go run main.go 999
//命令行的参数有: 2
//args[0] = C:\Users\lxxxxn\AppData\Local\Temp\go-build133979866\b001\exe\main.
//exe
//args[1] = 999

pacote bandeira para linha de comando parâmetros de análise

Explicação: A forma de realização anterior é muito mais nativo, não é particularmente conveniente para os parâmetros de resolução, em especial sob a forma de um parâmetro de linha de comando com o especificado

Por exemplo: cmd> main.exe fc: /aaa.txtx -p 200 forma de raiz u de tal linha de comando um, para fornecer os designers Go saco bandeira, pode parâmetros de linha de comando analisar facilmente, ea ordem dos parâmetros podem ser livremente

import (
	"flag"
	"fmt"
)

func main()  {
	//定义几个变量,用于接收命令行的参数值
	var user string
	var pwd string
	var host string
	var port int
	//&user就是接收用户命令行中输入的 -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 pwd = %v host = %v port = %v",
		user, pwd, host, port)
}
//E:\gostudent\src\2020-04-05>go run main.go -u root -pwd zisefeizhu -h 20.0.0.201 -port 3306
//user = root pwd = zisefeizhu host = 20.0.0.201 port = 3306

Json

Básico introdução Json

JSON (JavaScript Object Notation) é um formato de intercâmbio de dados leve. Fácil de ler e escrever. É fácil para máquinas para analisar e gerar. chave - val

Json em 2001 para promover o uso de formatos de dados, dados tornou-se o formato dominante

Quando a máquina é fácil de analisar e gerar JSON, e efetivamente melhorar a eficiência de transmissão da rede, geralmente o programa vai primeira rede de transmissão de dados (estrutura, mapa, etc.) em uma string seqüência json, para a string json destinatário get durante a desserialização de retorno para o tipo de dados original (estrutura, mapa, etc.). Isto tornou-se a forma padrão de cada idioma

cenários

Json Dados Format Descrição

Na linguagem JS, tudo é um objeto. Assim, qualquer tipo de dados pode ser representado pela JSON, tais como cordas, números, objetos, matriz, mapa, estruturas e similares

JSON par de chaves de valor é utilizada para armazenar dados de uma maneira

pares de chave / valor combinação de teclas editorial e aspas duplas "" pacote, cólon: separado, e logo em seguida Encontrado:

[{"key1":val1,"key2":val2,"key3":val3,"key4":[val4,val5]},
{"key1":val1,"key2":val2,"key3":val3,"key4":[val4,val5]}]
比如
{"firstName":"Json"}

{"name":"tom","age":18,"address":["北京","上海"]}

[{"name":"zisefeizhu","age":18,"address":["北京","上海"]},
{"name":"jingxing","age":18,"address":["北京","上海"]}]

Jsnon dados analítico online

https://www.json.cn/ site pode validar um formato JSON dados estão corretos. Especialmente na preparação de dados de formato json mais complexo, útil

Serialização JSON de

json meios de serialização, haverá chave - o tipo de dados da estrutura de valor (tal estrutura, o mapa, que corta) uma série de módulos em json

aplicações

Demonstram que a estrutura, o mapa e a sequência da fatia, de uma sequência de dados semelhante outros tipos

import (
   "encoding/json"
   "fmt"
)
//定义一个结构体
type Monster struct {
   Name string
   Age int
   Bithday string
   Sal float64
   Skill string
}

func testStruct()  {
   //演示
   monster := Monster{
      Name : "牛魔王",
      Age : 500,
      Bithday : "2001-11-11",
      Sal : 8000.0,
      Skill : "牛头拳",
   }
   //将monster 序列化
   data, err := json.Marshal(&monster)
   if err != nil {
      fmt.Printf("序列号错误 err = %v \n", err)
   }
   //输出序列化后的结果
   fmt.Printf("monster 序列化后 = %v \n", string(data))
}
//将map进行序列化
func testMap()  {
   //定义一个map
   var a map[string]interface{}
   //使用map,需要先make
   a = make(map[string]interface{})
   a["name"] = "红孩儿"
   a["age"] = 30
   a["address"] = "洪崖洞"
   //将a这个map进行序列化
   data, err := json.Marshal(a)
   if err != nil {
      fmt.Printf("序列号错误 err = %v \n", err)
   }
   //输出序列化后的结果
   fmt.Printf("monster 序列化后 = %v \n", string(data))
}
//演示对切片进行序列化,这个切片[]map[string]interface{}
func testSlice()  {
   var slice []map[string]interface{}
   var m1 map[string]interface{}
   //使用map前,需要先make
   m1 = make(map[string]interface{})
   m1["name"] = "jack"
   m1["age"] = "7"
   m1["address"] = "北京"
   slice = append(slice, m1)

   var m2 map[string]interface{}
   //使用map前,需要先make
   m2 = make(map[string]interface{})
   m2["name"] = "tom"
   m2["age"] = "20"
   m2["address"] = [2]string{"墨西哥","夏威夷"}
   slice = append(slice, m2)
   //将切片进行序列化操作
   data, err := json.Marshal(slice)
   if err != nil {
      fmt.Printf("序列号错误 err = %v \n", err)
   }
   //输出序列化后的结果
   fmt.Printf("monster 序列化后 = %v \n", string(data))
}
//对基本数据类型序列化,意义不大
func testFloat64()  {
   var num1 float64 = 2345.67
   //对num1进行序列化
   data, err := json.Marshal(num1)
   if err != nil {
      fmt.Printf("序列号错误 err = %v \n", err)
   }
   //输出序列化后的结果
   fmt.Printf("monster 序列化后 = %v \n", string(data))
}
func main()  {
   //演示将结构体、map、切片进行序列化
   testStruct()
   testMap()
   testSlice()
   testFloat64()
}
//输出
// monster 序列化后 = {"Name":"牛魔王","Age":500,"Bithday":"2001-11-11","Sal":8000,"Skill":"牛头拳"} 
//monster 序列化后 = {"address":"洪崖洞","age":30,"name":"红孩儿"} 
//monster 序列化后 = [{"address":"北京","age":"7","name":"jack"},{"address":["墨西哥","夏威夷"],"age":"20","name":"tom"}] 
//monster 序列化后 = 2345.67 

precauções

Para a estrutura de serialização, o nome da chave, se você quiser ser serializado após a re-promulgação, você pode desenvolver uma tag para o tag struct

import (
   "encoding/json"
   "fmt"
)
//定义一个结构体
type Monster struct {
   Name string  `json:"monster_name"` //反射机制 //:两边不要分开
   Age int `json:"monster_age"`
   Bithday string
   Sal float64
   Skill string
}

func testStruct()  {
   //演示
   monster := Monster{
      Name : "牛魔王",
      Age : 500,
      Bithday : "2001-11-11",
      Sal : 8000.0,
      Skill : "牛头拳",
   }
   //将monster 序列化
   data, err := json.Marshal(&monster)
   if err != nil {
      fmt.Printf("序列号错误 err = %v \n", err)
   }
   //输出序列化后的结果
   fmt.Printf("monster 序列化后 = %v \n", string(data))
}
func main()  {
   //演示将结构体、map、切片进行序列化
   testStruct()
}
//输出
// monster 序列化后 = {"monster_name":"牛魔王","monster_age":500,"Bithday":"2001-11-11","Sal":8000,"Skill":"牛头拳"} 

JSON desserialização

json deserializing meios, o desserializadas em cadeia json correspondente ao tipo de dados (tais como o, o mapa, que corta a estrutura) operação

aplicações

Mostrar-lhe a string JSON desserializado em estruturas, mapa e cortado

import (
   "encoding/json"
   "fmt"
)
//定义一个结构体
type Monster struct {
   Name string
   Age int
   Birthday string
   Sal float64
   Skill string
}
//演示将json字符串,反序列化成struct
func unmarshalStruct()  {
   //说明str在项目开发中,是通过网络传输获取到.. 或者是读取文件获取到
   str := "{\"Name\":\"牛魔王\",\"Age\":500,\"Birthday\":\"2001-11-11\",\"Sal\":8000,\"Skill\":\"牛头拳\"}"
   //定义一个Monster 实例
   var monster Monster
   err := json.Unmarshal([]byte(str), &monster)
   if err != nil {
      fmt.Printf("unmarshal err = %v\n", err)
   }
   fmt.Printf("反序列化后 monster = %v monster.Name = %v \n", monster, monster.Name)
}
//演示将json字符串,反序列化成map
func unmarshalMap()  {
   str := "{\"address\":\"洪崖洞\",\"age\":30,\"name\":\"红孩儿\"}"
   //定义一个map
   var a map[string]interface{}
   //反序列化
   //注意:反序列化map,不需要make,因为make操作被封装到Unmarshal函数
   err := json.Unmarshal([]byte(str), &a)
   if err != nil {
      fmt.Printf("unmarshal err = %v\n", err)
   }
   fmt.Printf("反序列化后 a = %v\n",a)
}
//演示将json字符串,反序列化成切片1
func unmarshalSlice()  {
   str := "[{\"address\":\"北京\",\"age\":\"7\",\"name\":\"jack\"},"+
      "{\"address\":[\"墨西哥\",\"夏威夷\"],\"age\":\"20\",\"name\":\"tom\"}]"
   //定义一个slice
   var slice []map[string]interface{}
   //反序列化,不需要make,因为make操作被封装到Unmarshal函数
   err := json.Unmarshal([]byte(str), &slice)
   if err != nil {
      fmt.Printf("unmarshal err = %v\n", err)
   }
   fmt.Printf("反序列化后 slice = %v\n", slice)
}

func main()  {
   unmarshalStruct()
   unmarshalMap()
   unmarshalSlice()
}
//输出
//反序列化后 monster = {牛魔王 500 2001-11-11 8000 牛头拳} monster.Name = 牛魔王 
//反序列化后 a = map[address:洪崖洞 age:30 name:红孩儿]
//反序列化后 slice = [map[address:北京 age:7 name:jack] map[address:[墨西哥 夏威夷] age:20 name:tom]]

precauções

1) Quando uma cadeia json deserialização, para garantir a consistência do tipo de dados que o tipo de dados e deserialização da sequência original

2) Se a string JSON é adquirido pelo programa, então não há necessidade de "" escapar

O teste de unidade

Um olhar sobre a demanda

No trabalho, encontrou tal situação um, é para confirmar uma função, ou um módulo dos resultados estão corretos

Tais como:

func addUpper(n int) int {
   res := 0
   for i := 1; i <= n; i++ {
      res += i
   }
   return res
}

O método tradicional

Na função principal, chamar addUpper função, olhar para os resultados da produção real e resultados esperados são consistentes, se consistente, então funcionar corretamente, caso contrário, a função tem um erro, e em seguida, modificar o erro

//一个被测试函数
func addUpper(n int) int {
   res := 0
   for i := 1; i <= n - 1; i++ {
      res += i
   }
   return res
}
func main()  {
   //传统的测试方法,就是在main函数中使用看看结果是否正确
   res := addUpper(10)
   if res != 55 {
      fmt.Printf("addUpper错误 返回值 = %v 期望值 = %v\n ", res, 55)
   } else {
      fmt.Printf("addUpper正确 返回值 = %v 期望值 = %v\n", res, 55)
   }
}
//addUpper错误 返回值 = 45 期望值 = 55

Análise das deficiências dos métodos tradicionais

  1. não é conveniente, você precisa chamar na função principal, por isso, é necessário modificar a função principal agora se o projeto está sendo executado, é possível parar o projeto

  2. não é propício para a gestão, porque quando nós testamos mais de uma função ou mais módulos, você precisa escrever a função principal, não é propício para a nossa administração e nosso pensamento claro

  3. Extracção teste de unidade. -> testar framework de testes pode resolver o problema

O teste de unidade

introdução básica

linguagem Go vem com um framework de teste leve para testar e vem com um comando para ir testes de implementação de teste de unidade e testes de desempenho, estruturas de teste e outro framework de testes linguagem semelhante, você pode escrever um teste para a função correspondente com base nesse quadro caso de uso, ela pode ser escrita a uma pressão correspondente sobre o suporte de ensaio. Por testes de unidade, pode abordar as seguintes questões:

  1. Certifique-se de que cada função está em execução e os resultados operacionais estão corretas

  2. Escrever código para garantir o desempenho é bom

  3. Unidade testando descoberta oportuna de erros ou lógica implementada a programação, a exposição precoce problema para localizar a solução para o problema, e testes de desempenho está focada em alguns dos problemas encontrados na programação, para que o programa também pode, no caso de alta concorrência estável

Introdução

Use Go testes unitários, testes de função eo sub addUpper

Nota especial: Ao testar, pode ser necessário para sair temporariamente 360 ​​(porque 360 ​​poderia pensar que o programa é para gerar casos de teste Trojans)

Demonstra como executar testes de unidade

unidade de executar testes princípio esquemático

início rápido resumo de testes de unidade

  1. Teste nome do arquivo caso deve terminar com _test.go. Por exemplo cal_test.go, cal não é fixo

  2. função de teste deve começar com o teste, teste + é o nome genérico da função a ser testado, tal como TestAddUpper

  3. TestAddUpper (t * testing.T) tipos de parâmetros deve ser * testing.T

  4. Um arquivo de caso de teste, pode haver vários casos de teste coreano, como TestAddUpper, TestSub

  5. Execute as instruções de caso de teste

(1) cmd> teste go [se executado corretamente, há registros, logs de erro será emitido]

(2) cmd> ir -v teste [certo prazo ou errado, são de log de saída]

  1. Quando ocorre um erro, você pode usar t.Fatalf a saída de formato de uma mensagem de erro e sair do programa

  2. t.Logf saída método de Maio de um registo correspondendo

  3. função de teste, e não sobre a função principal pode ser realizada, este é um caso de teste de lugar conveniente

  4. PASS representa um teste bem sucedido, queda representam casos de teste falhar

  5. Testar um único arquivo, os arquivos de origem deve ser colocado em teste

ir teste -v cal_test.go cal.go

  1. Testando um único método

teste go -v -test.run TestAddUpper

Caso integrada

Abrangentes requisitos de casos de teste de unidade:

  1. Escrever estrutura Monstro, campo Nome, Idade, uma habilidade

  2. método de ligação de loja, monstro pode ser uma variável (objecto), a sequência do guardado num ficheiro

  3. abordagem vinculativa para restaurar monstro, pode ser uma sequência de monstro, lido a partir do arquivo e desserializar objetos monstro, verificação do nome desserialização corretamente

  4. Programação store_test.go arquivo de caso de teste, escrever casos de teste para testar a teststore função e testrestore

código de área

monstro / monster.go

package monster

import (
   "encoding/json"
   "io/ioutil"
   "fmt"
)

type Monster struct {
   Name string
   Age int
   Skill string
}
//给Monster绑定方法Store,可以将一个Monster变量(对象),序列化后保存到文件中
func (this *Monster) Store() bool {
   //先序列化
   data, err := json.Marshal(this)
   if err != nil {
      fmt.Println("marshal err =", err)
      return false
   }
   //保存到文件
   filePath := "e:/monster.ser"
   err = ioutil.WriteFile(filePath, data, 0666)
   if err != nil {
      fmt.Println("write file err =",err)
      return false
   }
   return true
}
//给Monster绑定方法ReStore,可以将一个序列化的Monster从文件中读取,
//并反序列化为Monster对象,检查反序列化,名字正确
func (this *Monster) ReStore() bool {
   //1. 先从文件中,读取序列化的字符串
   filePath := "e:/monster.ser"
   data, err := ioutil.ReadFile(filePath)
   if err != nil {
      fmt.Println("ReadFile err =", err)
      return false
   }
   //2. 使用读取到data []byte,对反序列化
   err = json.Unmarshal(data, this)
   if err != nil {
      fmt.Println("UnMarshal err = ", err)
      return false
   }
   return true
}

monstro / monster_test.go

package monster

import "testing"
//测试用例,测试Store方法
func TestStore(t *testing.T)  {
   //先创建一个Monster实例
   monster := &Monster{
      Name: "红孩儿",
      Age: 10,
      Skill: "吐火",
   }
   res := monster.Store()
   if !res {
      t.Fatalf("monster.Store() 错误,希望为 = %v 实例为 = %v",true,res)
   }
   t.Logf("monster.Store() 测试成功!")
}
func TestReStore(t *testing.T)  {
   //测试数据是很多,测试很多次,才确定函数,模块..
   //先创建一个Monster实例,不需要制定字段的值
   var monster = &Monster{}
   res := monster.ReStore()
   if !res {
      t.Fatalf("monster.ReStore() 错误,希望为 = %v 实例为 = %v",true,res)
   }
   //进一步判断
   if monster.Name != "红孩儿" {
      t.Fatalf("monster.ReStore() 错误,希望为 = %v 实例为 = %v","红孩儿",monster.Name)
   }
   t.Logf("monster.ReStore() 测试成功!")
}


Acho que você gosta

Origin www.cnblogs.com/zisefeizhu/p/12638713.html
Recomendado
Clasificación