- Operações de arquivo
- parâmetros de linha de comando
- Json
- O teste de unidade
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
- 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("文件读取结束...")
}
- 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
- 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()
}
- 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()
}
- 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()
}
- 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:
-
Se um erro é retornado a zero, documentação ou pasta existe
-
Se o tipo errado de retorno usado os.IsNotExist () determina verdade, descreveu o arquivo ou pasta não existe
-
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
-
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
-
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
-
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:
-
Certifique-se de que cada função está em execução e os resultados operacionais estão corretas
-
Escrever código para garantir o desempenho é bom
-
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
-
Teste nome do arquivo caso deve terminar com _test.go. Por exemplo cal_test.go, cal não é fixo
-
função de teste deve começar com o teste, teste + é o nome genérico da função a ser testado, tal como TestAddUpper
-
TestAddUpper (t * testing.T) tipos de parâmetros deve ser * testing.T
-
Um arquivo de caso de teste, pode haver vários casos de teste coreano, como TestAddUpper, TestSub
-
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]
-
Quando ocorre um erro, você pode usar t.Fatalf a saída de formato de uma mensagem de erro e sair do programa
-
t.Logf saída método de Maio de um registo correspondendo
-
função de teste, e não sobre a função principal pode ser realizada, este é um caso de teste de lugar conveniente
-
PASS representa um teste bem sucedido, queda representam casos de teste falhar
-
Testar um único arquivo, os arquivos de origem deve ser colocado em teste
ir teste -v cal_test.go cal.go
- Testando um único método
teste go -v -test.run TestAddUpper
Caso integrada
Abrangentes requisitos de casos de teste de unidade:
-
Escrever estrutura Monstro, campo Nome, Idade, uma habilidade
-
método de ligação de loja, monstro pode ser uma variável (objecto), a sequência do guardado num ficheiro
-
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
-
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() 测试成功!")
}