这种恐慌的原因是什么?
What is the reason for this panic?
为了练习一些基本概念,我正在编写一个简单的端口扫描器。然而,当尝试实现 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()
}
谁能帮我看看我做错了什么?
net.DialTimeout()
return是一个连接和一个错误,你正确检查错误是否不是nil
,但即使有错误,你也只是打印它并继续。
如果出现非 nil
错误,您不应该(不得)使用 returned 连接,因为这可能是 nil
或无效值。如果有错误,请检查/打印它并 return,不要尝试使用 conn
.
如此简单 return:
if err != nil {
result.State = "Closed"
fmt.Printf("%+v\n", result)
return
}
此外,如果没有错误,您可以“安排”立即关闭连接,延迟。如果您在函数中最后关闭连接,则使用 defer
毫无意义。
所以它应该是这样的:
conn, err := net.DialTimeout(protocol, socket, 2*time.Second)
if err != nil {
result.State = "Closed"
fmt.Printf("%+v\n", result)
return
}
defer conn.Close()
result.State = "Open"
fmt.Printf("%+v\n", result)
为了练习一些基本概念,我正在编写一个简单的端口扫描器。然而,当尝试实现 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()
}
谁能帮我看看我做错了什么?
net.DialTimeout()
return是一个连接和一个错误,你正确检查错误是否不是nil
,但即使有错误,你也只是打印它并继续。
如果出现非 nil
错误,您不应该(不得)使用 returned 连接,因为这可能是 nil
或无效值。如果有错误,请检查/打印它并 return,不要尝试使用 conn
.
如此简单 return:
if err != nil {
result.State = "Closed"
fmt.Printf("%+v\n", result)
return
}
此外,如果没有错误,您可以“安排”立即关闭连接,延迟。如果您在函数中最后关闭连接,则使用 defer
毫无意义。
所以它应该是这样的:
conn, err := net.DialTimeout(protocol, socket, 2*time.Second)
if err != nil {
result.State = "Closed"
fmt.Printf("%+v\n", result)
return
}
defer conn.Close()
result.State = "Open"
fmt.Printf("%+v\n", result)