Go long話述

這也是一篇關於面試中的問題,這門語言也是很火,所以抽時間學了很簡單的入門。
並且我可以在面試當中加入這門語言的簡單話述。

爲什麼要學習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)]
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章