这种恐慌的原因是什么?

为了练习一些基本概念,我正在编写一个简单的端口扫描器。然而,当尝试实现 goroutines 时,程序会出现恐慌,并且出现分段错误:


Scanning ports

{Port:139 State:Open}

{Port:135 State:Open}

{Port:136 State:Closed}

{Port:131 State:Closed}

{Port:131 State:Open}

{Port:134 State:Closed}

{Port:134 State:Open}

panic: runtime error: invalid memory address or nil pointer dereference

[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4eb26a]


goroutine 20 [running]:

main.scanPort(0x52033b, 0x3, 0x52203e, 0xf, 0x83)

        /home/athos/Projects/go-tutorial/scanner.go:33 +0x1ea

created by main.main

        /home/athos/Projects/go-tutorial/scanner.go:41 +0xf1

panic: runtime error: invalid memory address or nil pointer dereference

[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4eb26a]


goroutine 23 [running]:

main.scanPort(0x52033b, 0x3, 0x52203e, 0xf, 0x86)

        /home/athos/Projects/go-tutorial/scanner.go:33 +0x1ea

created by main.main

        /home/athos/Projects/go-tutorial/scanner.go:41 +0xf1

exit status 2

这是我的代码:


package main


import (

    "fmt"

    "net"

    "strconv"

    "sync"

    "time"

)


var wg sync.WaitGroup


type scanResult struct {

    Port  int

    State string

}


func scanPort(protocol, hostname string, port int) {

    defer wg.Done()

    result := scanResult{Port: port}

    socket := hostname + ":" + strconv.Itoa(port)

    conn, err := net.DialTimeout(protocol, socket, 2*time.Second)


    if err != nil {

        result.State = "Closed"

        fmt.Printf("%+v\n", result)

    }


    result.State = "Open"

    fmt.Printf("%+v\n", result)


    // Defers: FILO data structure

    defer conn.Close()

}


func main() {

    fmt.Println("Scanning ports")

    for i := 130; i <= 145; i++ {

        wg.Add(1)

        go scanPort("tcp", "192.168.200.103", i)

    }

    // Wait for goroutines to complete

    wg.Wait()

}

谁能帮我看看我做错了什么?


青春有我
浏览 118回答 1
1回答

开心每一天1111

net.DialTimeout()返回连接和错误,您正确检查错误是否不是nil,但即使有错误,您只需打印并继续。如果存在非nil错误,则不应(绝不能)使用返回的连接,因为它可能是nil无效值。如果有错误,检查/打印并返回,不要尝试使用conn.所以简单地返回:if err != nil {&nbsp; &nbsp; result.State = "Closed"&nbsp; &nbsp; fmt.Printf("%+v\n", result)&nbsp; &nbsp; return}此外,如果没有错误,您可以“安排”立即关闭连接,延迟。defer如果您在函数中关闭连接的最后一件事,则使用毫无意义。所以它应该是这样的:conn, err := net.DialTimeout(protocol, socket, 2*time.Second)if err != nil {&nbsp; &nbsp; result.State = "Closed"&nbsp; &nbsp; fmt.Printf("%+v\n", result)&nbsp; &nbsp; return}defer conn.Close()result.State = "Open"fmt.Printf("%+v\n", result)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go