Golang程序运行报错问题排查指南

Golang程序运行报错问题排查指南 大家好,我正在尝试使用 net/http、os、bufio 和 fmt 包在 Go 语言中编写一个目录枚举器。我是 Go 语言的新手,因为学习这门语言的时间还不长。代码如下:

package main

import (
    "fmt"
    "net/http"
    "os"
    "bufio"
)

func main() {
    // 代码内容...
}
2 回复
$ go vet main.go
./main.go:23:22: Sprint call has possible formatting directive %s
$ 

Sprint

req,err1:=http.Get(fmt.Sprint("%s/%s",os.Args[1],scanner.Text()))

应该使用 Sprintf

req,err1:=http.Get(fmt.Sprintf("%s/%s",os.Args[1],scanner.Text()))

另外,请处理错误。例如:

req,err1:=http.Get(fmt.Sprintf("%s/%s",os.Args[1],scanner.Text()))
if err1 != nil {
    // 处理错误
    continue
}

更多关于Golang程序运行报错问题排查指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


以下是一个完整的目录枚举器示例,包含错误处理和常见问题排查方法:

package main

import (
    "bufio"
    "fmt"
    "net/http"
    "os"
    "strings"
    "sync"
    "time"
)

func main() {
    // 1. 检查命令行参数
    if len(os.Args) < 3 {
        fmt.Println("用法: go run main.go <目标URL> <字典文件>")
        fmt.Println("示例: go run main.go http://example.com wordlist.txt")
        os.Exit(1)
    }

    targetURL := os.Args[1]
    wordlistPath := os.Args[2]

    // 2. 验证URL格式
    if !strings.HasPrefix(targetURL, "http://") && !strings.HasPrefix(targetURL, "https://") {
        fmt.Printf("错误: URL必须以http://或https://开头\n")
        os.Exit(1)
    }

    // 3. 打开字典文件
    file, err := os.Open(wordlistPath)
    if err != nil {
        fmt.Printf("打开文件错误: %v\n", err)
        os.Exit(1)
    }
    defer file.Close()

    // 4. 创建HTTP客户端(设置超时避免阻塞)
    client := &http.Client{
        Timeout: 10 * time.Second,
    }

    // 5. 使用WaitGroup控制并发
    var wg sync.WaitGroup
    scanner := bufio.NewScanner(file)
    semaphore := make(chan struct{}, 10) // 限制并发数为10

    fmt.Printf("开始枚举: %s\n", targetURL)
    fmt.Println("=" * 50)

    for scanner.Scan() {
        path := strings.TrimSpace(scanner.Text())
        if path == "" {
            continue
        }

        wg.Add(1)
        semaphore <- struct{}{}

        go func(p string) {
            defer wg.Done()
            defer func() { <-semaphore }()

            url := fmt.Sprintf("%s/%s", targetURL, p)
            checkURL(client, url)
        }(path)
    }

    wg.Wait()
    fmt.Println("=" * 50)
    fmt.Println("枚举完成")
}

func checkURL(client *http.Client, url string) {
    resp, err := client.Get(url)
    if err != nil {
        // 网络错误处理
        fmt.Printf("请求失败 %s: %v\n", url, err)
        return
    }
    defer resp.Body.Close()

    // 只显示成功响应的URL
    if resp.StatusCode >= 200 && resp.StatusCode < 400 {
        fmt.Printf("[%d] %s\n", resp.StatusCode, url)
    }
}

常见错误排查指南:

  1. 网络连接错误
resp, err := http.Get(url)
if err != nil {
    // 检查具体错误类型
    if os.IsTimeout(err) {
        fmt.Println("连接超时")
    } else if strings.Contains(err.Error(), "connection refused") {
        fmt.Println("连接被拒绝")
    } else if strings.Contains(err.Error(), "no such host") {
        fmt.Println("域名解析失败")
    }
    return
}
  1. 文件读取错误
file, err := os.Open("wordlist.txt")
if err != nil {
    if os.IsNotExist(err) {
        fmt.Println("字典文件不存在")
    } else if os.IsPermission(err) {
        fmt.Println("没有文件读取权限")
    }
    os.Exit(1)
}
  1. 并发控制问题
// 使用带缓冲的channel控制并发数
maxConcurrent := 20
sem := make(chan struct{}, maxConcurrent)

for _, task := range tasks {
    sem <- struct{}{}
    go func(t string) {
        defer func() { <-sem }()
        // 执行任务
    }(task)
}
  1. 内存泄漏排查
// 确保response body被关闭
resp, err := http.Get(url)
if err != nil {
    return
}
defer resp.Body.Close() // 必须关闭

// 读取body内容
body, err := io.ReadAll(resp.Body)
if err != nil {
    return
}
  1. 超时设置
client := &http.Client{
    Timeout: 30 * time.Second,
    Transport: &http.Transport{
        MaxIdleConns:        100,
        MaxIdleConnsPerHost: 10,
        IdleConnTimeout:     90 * time.Second,
    },
}

运行程序时可能遇到的错误:

# 1. 缺少参数
$ go run main.go
用法: go run main.go <目标URL> <字典文件>

# 2. 文件不存在
$ go run main.go http://example.com notexist.txt
打开文件错误: open notexist.txt: no such file or directory

# 3. 网络超时
请求失败 http://example.com/timeout: Get "http://example.com/timeout": context deadline exceeded

# 4. 连接被拒绝
请求失败 http://localhost:9999: Get "http://localhost:9999": dial tcp 127.0.0.1:9999: connect: connection refused

使用示例:

# 编译程序
go build -o dir_enum main.go

# 运行程序
./dir_enum http://example.com wordlist.txt
回到顶部