Local-first LAN scanning via Go and
The biggest gotcha with Go networking is managing timeouts and goroutines without leaking resources. If you let the AI wing it, it often forgets to close connections or uses time.Sleep instead of proper context cancellation.
To get this right, I created a patterns.md file in my project root and added it to Cursor's context. In that file, I explicitly defined that all network I/O must use context.WithTimeout. When I prompted the AI to implement the ARP/ICMP scanning logic, I simply referenced that file.
Here is the core logic I landed on for the concurrent scanner. I used a worker pool pattern to avoid hitting OS file descriptor limits when scanning a /24 subnet:
package main
import (
"context"
"fmt"
"net"
"sync"
"time"
)
func scanHost(ctx context.Context, ip string, results chan<- string, wg *sync.WaitGroup) {
defer wg.Done()
d := net.Dialer{Timeout: 500 * time.Millisecond}
conn, err := d.DialContext(ctx, "tcp", ip+":80") // Scanning port 80 as a proxy for "alive"
if err == nil {
conn.Close()
results <- ip
}
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
ips := []string{"192.168.1.1", "192.168.1.2", "192.168.1.3"} // Simplified for example
results := make(chan string, len(ips))
var wg sync.WaitGroup
for _, ip := range ips {
wg.Add(1)
go scanHost(ctx, ip, results, &wg)
}
go func() {
wg.Wait()
close(results)
}()
for res := range results {
fmt.Printf("Host found: %s\n", res)
}
}Config and Workflow Tips:
Use .cursorrules for Go specifics: I added a rule to my project that tells the AI: "Prefer slog over fmt for logging and always implement context propagation in function signatures." This stopped the AI from suggesting outdated log.Printf calls.
The "Iterative Refinement" loop: I didn't get the worker pool right in one go. First, I asked for a basic loop. Then, I highlighted the slow section and used the "Chat" (Cmd+L) to ask: "This is blocking. Rewrite this using a worker pool of 50 goroutines to speed up the /24 scan." The AI correctly identified that the bottleneck was the synchronous Dial call.
Performance Gain: Moving from a sequential scan to a controlled goroutine pool dropped the scan time for my local subnet from ~40 seconds to under 3 seconds.
One annoying thing about Claude 3.5 Sonnet in Cursor is that it sometimes tries to use third-party libraries like github.com/mdlayher/arp without telling me to go get them. I've found that adding "Stick to the standard library unless performance requires otherwise" to the prompt keeps the dependency tree clean.
All Replies (0)
No replies yet — be the first!
