這也是一篇關於面試中的問題,這門語言也是很火,所以抽時間學了很簡單的入門。
並且我可以在面試當中加入這門語言的簡單話述。
爲什麼要學習Go語言?
Go語言是現在非常火爆🔥的一門編程語言,極大地提高了後端編程的效率,同時有着極高的性能。
藉助Go語言我們可以用同步的方式寫出高併發的服務端軟件,同時,Go語言也是雲原生第一語言,Docker,Kubernetes等等著名的項目都是使用Go語言實現的。
Go語言之所以如此火爆,是因爲Go語言既有動態語言的開發效率,又能有靜態語言的編譯期檢驗,編譯通過之後基本上不會遇到崩潰,再加上Go語言簡單而又剛好足夠的語法,以及統一的內置工具和編碼風格,使得用戶能夠輕鬆的和團隊裏的其他人協作。
爲什麼要用go來改造爬蟲?
主要還是因爲python的性能瓶頸,而go除了本身的高性能以外,其內置的bufio模塊可以提高http請求速率以及文件操作的性能,與此同時還可以很輕鬆的應用併發下載及其斷點續傳功能,所以有的時候需要爲了高性能而犧牲一部分的開發效率
代碼如下:
package main
import (
"net/http"
"log"
"time"
"net/url"
"path"
"os"
"io"
"bufio"
"math"
"strconv"
)
//定義下載地址
var durl = "https://video.pearvideo.com/mp4/adshort/20190515/cont-1554493-13908887_adpkg-ad_hd.mp4";
func main() {
uri, err := url.ParseRequestURI(durl)
if err != nil {
panic("網址錯誤")
}
filename := path.Base(uri.Path)
log.Println("[*] Filename " + filename)
client := http.DefaultClient;
client.Timeout = time.Second * 60 //設置超時時間
resp, err := client.Get(durl)
if err != nil {
panic(err)
}
if resp.ContentLength <= 0 {
log.Println("[*] Destination server does not support breakpoint download.")
}
raw := resp.Body
defer raw.Close()
reader := bufio.NewReaderSize(raw, 1024*32);
file, err := os.Create(filename)
if err != nil {
panic(err)
}
writer := bufio.NewWriter(file)
buff := make([]byte, 32*1024)
written := 0
go func() {
for {
nr, er := reader.Read(buff)
if nr > 0 {
nw, ew := writer.Write(buff[0:nr])
if nw > 0 {
written += nw
}
if ew != nil {
err = ew
break
}
if nr != nw {
err = io.ErrShortWrite
break
}
}
if er != nil {
if er != io.EOF {
err = er
}
break
}
}
if err != nil {
panic(err)
}
}()
spaceTime := time.Second * 1
ticker := time.NewTicker(spaceTime)
lastWtn := 0
stop := false
for {
select {
case <-ticker.C:
speed := written - lastWtn
log.Printf("[*] Speed %s / %s \n", bytesToSize(speed), spaceTime.String())
if written-lastWtn == 0 {
ticker.Stop()
stop = true
break
}
lastWtn = written
}
if stop {
break
}
}
}
func bytesToSize(length int) string {
var k = 1024 // or 1024
var sizes = []string{"Bytes", "KB", "MB", "GB", "TB"}
if length == 0 {
return "0 Bytes"
}
i := math.Floor(math.Log(float64(length)) / math.Log(float64(k)))
r := float64(length) / math.Pow(float64(k), i)
return strconv.FormatFloat(r, 'f', 3, 64) + " " + sizes[int(i)]
}