当前位置: 首页 > news >正文

go学习笔记7(泛型,文件读写,测试)

go学习笔记7(泛型,文件读写,测试)

16.泛型

package mainimport ("encoding/json""fmt"
)func plus(a int, b int) int {return a + b
}
func plusUint(a uint, b uint) uint {return a + b
}// 泛型约束 不带波号只能匹配原生, 带波浪号的可以匹配别名(如下面的Age不带波号时, 不匹配, 带波浪号就可以匹配了), 实测, 两种都行, 不过推荐使用~
// ~也只有泛型约束能用, 其它没用
type Number interface {//int | uint | int8 | int16 | int32 | int64 //旧版本这样没问题, 新版本也没报错,~int | ~uint | ~int8 | ~int16 | ~int32 | ~int64
}type Number2 interface {~int | ~uint | ~int8 | ~int16 | ~int32 | ~int64
}type Age int32// 泛型, 限制为int与uint
func mul[T int | uint](a T, b T) T {return a * b
}// 1.泛型函数
func div[T Number](a T, b T) T {return a / b
}
func div2[T Number2](a T, b T) T {return a / b
}func myPrint[T int, K string | int](a T, b K) {fmt.Println(a, b)
}// 2.泛型结构体
type Response[T any] struct {Code int    `json:"code"`Msg  string `json:"msg"`Data T      `json:"data"`
}
type UserName struct {Name string `json:"name"`
}type UserInfo struct {Name string `json:"name"`Age  int    `json:"age"`
}func test16() {var a, b = uint(8), uint(3)var c = plus(int(a), int(b))var d = plusUint(a, b)var e = mul(a, b)fmt.Println(c, d, e)var age1 Age = Age(10)var age2 Age = Age(2)var data = div(age1, age2)fmt.Println(data)
}// 3.泛型切片
type MySlice[T int | string] []T// 4.泛型map
type MyMap[T ~int | string, K int | ~string] map[T]Kfunc main() {//泛型结构体必须显式指定类型res1 := Response[UserName]{1, "hello1", UserName{"Tom"}}res2 := Response[UserInfo]{2, "hello2", UserInfo{"Tom", 3}}byteStr1, _ := json.Marshal(res1)byteStr2, _ := json.Marshal(res2)fmt.Println(string(byteStr1), string(byteStr2))var user1 Response[UserName]err := json.Unmarshal(byteStr1, &user1)if err != nil {return}var user2 Response[UserInfo]str2 := string(byteStr2)err = json.Unmarshal([]byte(str2), &user2)if err != nil {return}mySlice := MySlice[int]{1, 2, 3}fmt.Println(mySlice)
}

 


17.文件读写

package mainimport ("bufio""fmt""io""os""strconv"
)func readAllText(fileName string) {var txt, err = os.ReadFile(fileName)if err != nil {panic(err)}fmt.Println(string(txt))
}func readTextByLine(fileName string) {file, err := os.Open(fileName)if err != nil {panic(err)}defer func(file *os.File) {err := file.Close()if err != nil {panic(err)}}(file)buf := bufio.NewReader(file)for {line, isPrefix, err := buf.ReadLine()if err == io.EOF {break}if isPrefix {fmt.Println("有isPrefix", string(line))} else {fmt.Println(string(line))}}
}func writeFile(fileName string) {file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE, 0666)if err != nil {panic(err)}defer func(file *os.File) {err := file.Close()if err != nil {}}(file)for i := 0; i < 100; i++ {_, err = file.Write([]byte("hello world" + strconv.Itoa(i) + "\r\n"))}
}// 100M以下文件复制
func copySmallFile(src string, dst string) error {data, err := os.ReadFile(src)if err != nil {return err}//return os.WriteFile(dst, data, 0666)// 保留原文件权限info, _ := os.Stat(src)perm := os.FileMode(0644)if info != nil {perm = info.Mode()}return os.WriteFile(dst, data, perm)
}// 大于100M文件复制
func copyBigFile(src, dst string) error {// 打开源文件source, err := os.Open(src)if err != nil {return fmt.Errorf("打开源文件失败: %w", err)}defer source.Close()// 创建目标文件(0644 = rw-r--r--)destination, err := os.Create(dst)if err != nil {return fmt.Errorf("创建目标文件失败: %w", err)}defer destination.Close()// 复制内容bytesWritten, err := io.Copy(destination, source)if err != nil {return fmt.Errorf("复制失败: %w", err)}// 同步到磁盘(确保数据落盘,可选)if err := destination.Sync(); err != nil {return fmt.Errorf("同步失败: %w", err)}fmt.Printf("成功复制 %d 字节\n", bytesWritten)return nil
}// 遍历目录
func showDir(dir string) {var files, err = os.ReadDir(dir)if err != nil {panic(err)}for _, file := range files {if file.IsDir() {newDir := dir + "/" + file.Name()showDir(newDir)}fmt.Println(dir + "/" + file.Name())}
}func main() {showDir(".")fileName := "config/cfg.txt"writeFile(fileName)//readAllText(fileName)
    readTextByLine(fileName)}

 


18.测试
unit_test\calc.go

package unit_testfunc Add(a, b int) int {return a + b
}

unit_test\calc_test.go

package unit_testimport ("testing"
)// 执行 go test .\unit_test\calc.go .\unit_test\calc_test.go
// 或者右击左边的unit_test文件夹
func TestAdd(t *testing.T) {/*//普通单元测试res := Add(1, 2)if res != 3 {t.Errorf("测试失败")return}t.Logf("测试成功")*//*// 子测试t.Run("add1", func(t *testing.T) {if Add(1, 2) != 3 {t.Errorf("测试失败1")return}})t.Run("add2", func(t *testing.T) {if Add(1, -1) != 0 {t.Errorf("测试失败2")return}})*/cases := []struct {Name           stringA, B, Expected int}{{"a1", 1, 2, 3},{"a2", 2, 3, 3},{"a3", 3, 4, 7},{"a4", 4, 5, 9},}for _, c := range cases {t.Run(c.Name, func(t *testing.T) {if Add(c.A, c.B) != c.Expected {t.Errorf("%s测试失败", c.Name)return}})}
}

 

unit_test\main_test.go

package unit_testimport ("fmt""os""testing"
)// TestMain优先执行
func TestMain(t *testing.M) {fmt.Println("TestMain begin")code := t.Run()fmt.Println("TestMain end", code)os.Exit(code)
}