问题描述
我想在我的 for loop 上发送每次迭代的并发调用。
当前代码
这个程序主要是尝试在服务器上找到一个有效的目录
package main
import (
"bufio"
"fmt"
"net/http"
"os"
)
func main() {
var site string
if len(os.Args) > 1 {
site = os.Args[1]
} else {
fmt.Println("Need the host. Example > http://www.google.com/")
fmt.Println("wfuzz http://www.google.com/ wordlist.txt")
site = "http://www.google.com"
os.Exit(1)
}
f, err := os.Open(os.Args[2])
if err != nil {
fmt.Println("error opening file!", err)
}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
a := site + scanner.Text()
get_page(a)
}
if err := scanner.Err(); err != nil {
fmt.Println("error", err)
}
var input string
fmt.Scanln(&input)
fmt.Println("done")
}
func get_page(site string) string {
a := "\n"
res, err := http.Get(site)
if err != nil {
fmt.Println("error:", err)
}
if res.StatusCode != 404 {
fmt.Println("Page Found!! +::", site, " ::+", res.StatusCode)
}
return a
}
实现目标
我想要实现的主要是发送我的for循环并发调用,这样我会加快进程,并且将成为当前程序的最终目标。
答案 0 :(得分:1)
您可以使用
sync.WaitGroup
唯一的问题是你要进行多少次并发通话。
示例
如果wordlist.txt包含此内容
admin.php
admin
administrator
administrator
你知道你将进行4次并发呼叫
如果内容是
admin.php
admin/
administrator/
administrator/
administrator/
administrator/
你知道你将进行6次并发呼叫。
以下代码是使用3个字的文件
package main
import (
"fmt"
"sync"
"bufio"
"net/http"
"os"
)
func main(){
var site string
var wg sync.WaitGroup
if len(os.Args) > 1 {
site = os.Args[1]
} else {
fmt.Println("Need the host. Example > http://www.google.com/")
fmt.Println("wfuzz http://www.google.com/ wordlist.txt")
site = "http://www.google.com"
os.Exit(1)
}
f, err := os.Open(os.Args[2])
if err != nil {
fmt.Println("error opening file!", err)
}
wg.Add(3) // TODO check the number of words in the file
scanner := bufio.NewScanner(f)
for scanner.Scan() {
a := site + scanner.Text()
go get_page(a,&wg)
}
if err := scanner.Err(); err != nil {
fmt.Println("error", err)
}
wg.Wait()
fmt.Println("done")
}
func get_page(site string,wg *sync.WaitGroup) string{
a := "\n"
defer wg.Done()
res, err := http.Get(site)
if err != nil {
fmt.Println("error:", err)
}
if res.StatusCode != 404 {
fmt.Println("Page Found!! +::", site, " ::+", res.StatusCode)
}
return a
}
答案 1 :(得分:1)
使用Go标准库sync.WaitGroup
和频道的组合,您可以完成此操作,而无需明确跟踪您希望从中读取的文件中的字数。
修改你的get_page
(旁注:这不是惯用的去func名称中的用户下划线 - > https://golang.org/doc/effective_go.html#names)func接受额外的频道和等待组,你可以做类似的事情以下内容:
package main
import (
"bufio"
"fmt"
"net/http"
"os"
"sync"
)
func main() {
//your previous code for getting the command line arguments from os.Args, then...
//create a WaitGroup
wg := new(sync.WaitGroup)
//create a channel that you can write your results too
resultChan := make(chan string)
scanner := bufio.NewScanner(f)
for scanner.Scan() {
//increment the waitgroup
wg.Add(1)
a := site + scanner.Text()
//call the getPage with the http target, with the result chan, and the waitgroup
go getPage(a, resultChan, wg)
}
if err := scanner.Err(); err != nil {
fmt.Println("error", err)
//if there is an error, close the result chan so progam can exit (for more robust cancellation of potential currently running go routines, take a look at https://blog.golang.org/pipelines)
close(resultChan)
}
//start another go routine to wait for all concurrent calls to get_page to complete, then close the result channel
go func() {
wg.Wait()
close(resultChan)
}()
for result := range resultChan {
//deal with the result in some way
fmt.Println(result)
}
fmt.Println("done")
}
//side note - it is not idiomatic go to use underscores in func name
func getPage(site string, ch chan<- string, wg *sync.WaitGroup) {
//decrement waitgroup when operation completes
defer wg.Done()
res, err := http.Get(site)
if err != nil {
ch <- fmt.Sprintf("error: %s", err)
return
}
if res.StatusCode != 404 {
ch <- fmt.Sprintf("Page Found!! +:: %s ::+ %d", site, res.StatusCode)
}
}
答案 2 :(得分:0)
您可以使用go get_page(a)
为wordlist上的每个单词启动goroutine,以设置使用工作池的最大并发调用。 (https://gobyexample.com/worker-pools)