惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
T
Threat Research - Cisco Blogs
美团技术团队
IT之家
IT之家
Apple Machine Learning Research
Apple Machine Learning Research
Microsoft Azure Blog
Microsoft Azure Blog
小众软件
小众软件
Engineering at Meta
Engineering at Meta
U
Unit 42
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
MongoDB | Blog
MongoDB | Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The Cloudflare Blog
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
G
Google Developers Blog
博客园 - 三生石上(FineUI控件)
Vercel News
Vercel News
The Register - Security
The Register - Security
Cyberwarzone
Cyberwarzone
F
Fortinet All Blogs
L
LINUX DO - 热门话题
C
Check Point Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Know Your Adversary
Know Your Adversary
S
Security Affairs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Webroot Blog
Webroot Blog
V2EX - 技术
V2EX - 技术
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Martin Fowler
Martin Fowler
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
I
InfoQ
Cisco Talos Blog
Cisco Talos Blog
博客园 - 司徒正美
aimingoo的专栏
aimingoo的专栏
T
The Exploit Database - CXSecurity.com
博客园 - 【当耐特】
C
CERT Recently Published Vulnerability Notes
酷 壳 – CoolShell
酷 壳 – CoolShell
云风的 BLOG
云风的 BLOG
L
Lohrmann on Cybersecurity
T
Threatpost
腾讯CDC
Security Latest
Security Latest
K
Kaspersky official blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Stack Overflow Blog
Stack Overflow Blog
Help Net Security
Help Net Security
Forbes - Security
Forbes - Security

博客园 - 悉野

ssh连结vmware中ubuntu的共享文件夹 spring加载冲突问题 spring一个错误修正 抓安卓日记到文件 注册表删除桌面顽固图标 github买的账号无法拉取代码的解决方法 apk常用命令 java服务器异常处理 ES6 学习难度分层 promise原理 材质, 纹理, shader之间的关系 TCP与UDP区别 javascript中=>与function的区别 javascript中函数解析过程 cocos使用fgui 几种服务注册与发现的区别 mybatis测试 向量点乘与叉乘 unity画布3种渲染模式 go学习笔记10(HTTP) go学习笔记9(TCP) go学习笔记8(反射) c++简单的线程池 operator new 是 C++ 动态内存分配的核心函数,负责分配原始内存,不调用构造函数 C++的定位放置new(Placement new) go学习笔记6(协程与channel,select使用,线程安全,异常处理) go学习笔记5(函数,结构体,自定义类型和类别名,接口) go学习笔记4(数组与切片,map,if,switch,for循环) go学习笔记3(变量定义,输入输出,基本数据类型) go学习笔记2 laya打包的apk版本更新脚本 laya列表滚动问题 laya踩坑记 laya列表时计算具体体子项是列表中第几个 子弹射击 laya给自己画边框 查看laya已经加载的资源 laya spine事件
go学习笔记7(泛型,文件读写,测试)
悉野 · 2026-04-05 · via 博客园 - 悉野

16.泛型

package main

import (
    "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]K

func 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 main

import (
    "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_test

func Add(a, b int) int {
    return a + b
}

unit_test\calc_test.go

package unit_test

import (
    "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           string
        A, 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_test

import (
    "fmt"
    "os"
    "testing"
)

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