前言
emm这里会记录下我学Go
的一些小基础吧,毕竟之后肯定会接触Go
,用一些简单的例子来解释一些内容,这里大家可以尝试以写端口扫描工具来感受下并发
并发机制
不并发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package main
import ( "fmt" "net" )
func porter() { for port := 0; port < 65535; port++ {
address := fmt.Sprintf("192.168.0.128:%d", port) connect, connect_error := net.Dial("tcp", address)
if connect_error != nil { fmt.Printf("[-] %d --> close\n", port) continue } else { connect.Close() fmt.Printf("[+] %d -->opening \n", port) } fmt.Println(address) } }
func main() { porter() }
|
可以说是龟速
goroutine并发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package main
import ( "fmt" "net" "sync" "time" )
func porter() { var wait_group sync.WaitGroup time_start := time.Now() for port := 0; port < 65535; port++ { wait_group.Add(1) go func(f_port int) { defer wait_group.Done() address := fmt.Sprintf("192.168.0.128:%d", f_port) connect, connect_error := net.Dial("tcp", address) if connect_error != nil { return } connect.Close() fmt.Printf("[+] %d -->opening \n", f_port) }(port) } wait_group.Wait() time_stop := time.Now() time_def := time_stop.Sub(time_start) fmt.Printf("[*] 1-65535端口扫描完毕,共用时:%v。\n", time_def) }
func main() { porter() }
|
对上述代码进行理解,其实就是在循环当中每次循环计数器加一来起一个Goroutines
去执行我的匿名函数,相当于主线程在循环的当中多了很多独立的协程去跑我们函数体
如图 —> 还能开无数个 然后每个协程的任务完成后就计数器减一,(因为循环肯定比扫描快,所以肯定是先计数器完才到函数执行完)
计数器的流程
Goroutines是什么
Goroutines 可以看作是轻量级线程。创建一个 goroutine 非常简单,只需要把 go
关键字放在函数调用语句前
channel是什么
他是一个用来实现多个goroutine之间数据共享的东西 比如goroutine1和goroutine2 这两个都是独立的 使用channel 通过管道连接在一起 达到数据共享,可以把goroutine1得到的内容给goroutine2