Golang中如何生成tar格式的覆盖率检测二进制文件

Golang中如何生成tar格式的覆盖率检测二进制文件 我正在尝试创建一个支持覆盖率检测的二进制文件。 参考 - 集成测试的覆盖率分析支持 - Go 编程语言

这里使用的示例命令如下,它会创建一个 exe 文件:

go build -cover -o myprogram.exe myprogram.go

我想知道是否也可以使用 -cover 标志来创建 tar/tgz 格式的检测二进制文件。尽管我尝试更改文件扩展名并运行命令,但最终得到了损坏的文件。

我的最终目标是创建二进制文件,并替换应用程序中的 Kubernetes Pods,以便进一步运行自动化测试。

Go 版本 - 1.21.4


更多关于Golang中如何生成tar格式的覆盖率检测二进制文件的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

你能详细说明一下为什么需要tar格式吗?

难道你不能直接用 go build 生成二进制文件,然后创建一个包含该插桩二进制文件的Docker镜像,让它在启动时执行该二进制文件,并让K8s pod使用这个镜像吗?

// 代码示例:使用go build生成二进制文件
func main() {
    fmt.Println("构建并运行")
}

更多关于Golang中如何生成tar格式的覆盖率检测二进制文件的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中,-cover标志只能用于生成可执行的二进制文件,不能直接生成tar格式的覆盖率检测文件。覆盖率检测需要将运行时数据收集功能编译到可执行文件中,这与归档格式不兼容。

不过,你可以通过以下步骤实现你的需求:

1. 先构建覆盖率检测的二进制文件

go build -cover -covermode=atomic -coverpkg=./... -o myapp ./cmd/myapp

2. 将二进制文件打包到tar中

package main

import (
    "archive/tar"
    "compress/gzip"
    "io"
    "os"
    "path/filepath"
)

func createTarWithBinary() error {
    // 创建tar.gz文件
    tarFile, err := os.Create("myapp-cover.tar.gz")
    if err != nil {
        return err
    }
    defer tarFile.Close()

    // 创建gzip写入器
    gzWriter := gzip.NewWriter(tarFile)
    defer gzWriter.Close()

    // 创建tar写入器
    tarWriter := tar.NewWriter(gzWriter)
    defer tarWriter.Close()

    // 打开覆盖率检测的二进制文件
    binaryFile, err := os.Open("myapp")
    if err != nil {
        return err
    }
    defer binaryFile.Close()

    // 获取文件信息
    fileInfo, err := binaryFile.Stat()
    if err != nil {
        return err
    }

    // 创建tar头部
    header := &tar.Header{
        Name:    "myapp",
        Mode:    0755,
        Size:    fileInfo.Size(),
        ModTime: fileInfo.ModTime(),
    }

    // 写入头部
    if err := tarWriter.WriteHeader(header); err != nil {
        return err
    }

    // 复制文件内容到tar
    if _, err := io.Copy(tarWriter, binaryFile); err != nil {
        return err
    }

    return nil
}

3. 在Kubernetes中使用的完整示例

// build_cover_tar.go
package main

import (
    "archive/tar"
    "compress/gzip"
    "fmt"
    "io"
    "os"
    "os/exec"
    "path/filepath"
)

func main() {
    // 构建覆盖率检测的二进制文件
    cmd := exec.Command("go", "build", 
        "-cover", 
        "-covermode=atomic",
        "-coverpkg=./...",
        "-o", "app-cover",
        "./cmd/app")
    
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    
    if err := cmd.Run(); err != nil {
        panic(fmt.Sprintf("构建失败: %v", err))
    }

    // 创建tar包
    if err := createCoverageTar("app-cover", "app-coverage.tar.gz"); err != nil {
        panic(fmt.Sprintf("创建tar失败: %v", err))
    }
    
    fmt.Println("覆盖率检测tar包创建成功: app-coverage.tar.gz")
}

func createCoverageTar(binaryPath, outputPath string) error {
    // 打开二进制文件
    binaryFile, err := os.Open(binaryPath)
    if err != nil {
        return err
    }
    defer binaryFile.Close()
    defer os.Remove(binaryPath) // 清理临时文件

    // 创建输出文件
    outFile, err := os.Create(outputPath)
    if err != nil {
        return err
    }
    defer outFile.Close()

    // 创建gzip和tar写入器
    gzWriter := gzip.NewWriter(outFile)
    defer gzWriter.Close()
    
    tarWriter := tar.NewWriter(gzWriter)
    defer tarWriter.Close()

    // 获取文件信息
    fileInfo, err := binaryFile.Stat()
    if err != nil {
        return err
    }

    // 创建tar头部
    header := &tar.Header{
        Name:    filepath.Base(binaryPath),
        Mode:    0755, // 可执行权限
        Size:    fileInfo.Size(),
        ModTime: fileInfo.ModTime(),
    }

    // 写入头部和文件内容
    if err := tarWriter.WriteHeader(header); err != nil {
        return err
    }
    
    if _, err := io.Copy(tarWriter, binaryFile); err != nil {
        return err
    }

    return nil
}

4. 在Kubernetes中使用的Dockerfile示例

FROM alpine:latest

# 复制tar包并解压
COPY app-coverage.tar.gz /tmp/
RUN tar -xzf /tmp/app-coverage.tar.gz -C /usr/local/bin/ && \
    chmod +x /usr/local/bin/app-cover && \
    rm /tmp/app-coverage.tar.gz

# 设置覆盖率环境变量
ENV GOCOVERDIR=/tmp/coverage

# 创建覆盖率目录
RUN mkdir -p /tmp/coverage

ENTRYPOINT ["/usr/local/bin/app-cover"]

5. 运行测试并收集覆盖率数据

// 在测试容器中运行
// 设置覆盖率输出目录
export GOCOVERDIR=/tmp/coverage

// 运行应用程序
./app-cover

// 从容器中提取覆盖率数据
kubectl cp <pod-name>:/tmp/coverage ./coverage-data

// 转换为HTML报告
go tool covdata textfmt -i=./coverage-data -o coverage.txt
go tool cover -html=coverage.txt -o coverage.html

这种方法可以让你:

  1. 构建包含覆盖率检测的二进制文件
  2. 打包成tar格式便于分发
  3. 在Kubernetes Pods中替换使用
  4. 收集运行时覆盖率数据
  5. 生成覆盖率报告

注意:覆盖率数据需要在程序正常退出时才会写入GOCOVERDIR指定的目录。

回到顶部