python和go語(yǔ)言的區(qū)別是什么
背景
工作中的主力語(yǔ)言是Python,今年要搞性能測(cè)試的工具,由于GIL鎖的原因,Python的性能實(shí)在是慘淡,需要學(xué)一門(mén)性能高的語(yǔ)言來(lái)生成性能測(cè)試的壓力端。因此我把目光放在了現(xiàn)在的新秀Go。經(jīng)過(guò)一段時(shí)間的學(xué)習(xí),也寫(xiě)了一個(gè)小工具,記一下這兩個(gè)語(yǔ)言的區(qū)別。
需求
工具是一個(gè)小爬蟲(chóng),用來(lái)爬某網(wǎng)站的某個(gè)產(chǎn)品的迭代記錄,實(shí)現(xiàn)邏輯就是運(yùn)行腳本后,使用者從命令行輸入某些元素(產(chǎn)品ID等)后,腳本導(dǎo)出一個(gè)Excel文件出來(lái)。
最初的版本是用Python寫(xiě)的,30行代碼不到就搞定了。這次用Go重寫(xiě),代碼量在110行左右。
接受輸入
第一步就是接受命令行的輸入內(nèi)容,工具要給非技術(shù)人員用的,弄一個(gè)CLI不太合適,要的效果就是一行一行的輸入內(nèi)容,用Python實(shí)現(xiàn)起來(lái)非常容易,像這樣:
app_id = raw_input('請(qǐng)輸入app_id: ') app_analysis = raw_input('請(qǐng)輸入analysis: ')
執(zhí)行后就是一行一行的往下走,但是用Go就有點(diǎn)蛋疼了,完整的代碼如下:
func getPara() (string, string) { var i = 0 var appId, analysis string fmt.Print("請(qǐng)輸入appId:") scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { text := scanner.Text() if i == 0 { appId = text fmt.Print("請(qǐng)輸入analysis:") } else if i == 1 { analysis = text fmt.Print("程序初始化數(shù)據(jù)完畢。。。。請(qǐng)按任意鍵繼續(xù)") } else { break } i++ } return appId, analysis }
Go要實(shí)現(xiàn)CLI很方便,但是涉及到這種一行一行的輸入,要一直監(jiān)聽(tīng)Scan(),所以就有了上面蛋疼的循環(huán)處理,而且在必須要先打印信息,再來(lái)監(jiān)聽(tīng)內(nèi)容,總體的寫(xiě)的過(guò)程很惡心,也許是沒(méi)有找到更好的方法吧,實(shí)在是太逆天了。
發(fā)送請(qǐng)求
在發(fā)送請(qǐng)求方便,兩種語(yǔ)言倒是差別不太大,至少我寫(xiě)的Get請(qǐng)求是這樣的。
Python params = { "analysis": app_analysis, "appid": app_id, "country": 'cn' } r = requests.get(url, params)
Go q := req.URL.Query() q.Add("appid", appId) q.Add("analysis", analysis) q.Add("country", "cn") req.URL.RawQuery = q.Encode() var resp *http.Response resp, _ = http.DefaultClient.Do(req)
返回結(jié)果處理
在返回結(jié)果的處理上,Python的處理方式簡(jiǎn)直是太友好了,直接調(diào)用json就處理了。
result = r.json()
但是Go就有點(diǎn)蛋疼了,由于是靜態(tài)語(yǔ)言,所以解包數(shù)據(jù)的時(shí)候需要先定義數(shù)據(jù)格式,比如返回的內(nèi)容必須要先做如下的結(jié)構(gòu)定義:
type ResultInfo struct { Code int Msg string Version []VersionInfo } type VersionInfo struct { Version string `json:"version"` ReleaseTime string `json:"release_time"` ReleaseNote string `json:"release_note"` AppName string `json:"app_name"` SubTitle string `json:"subtitle"` }
第一個(gè)ResultInfo是返回的數(shù)據(jù),其中的Version也是一個(gè)數(shù)組對(duì)象,所以還要再定義一個(gè)數(shù)組對(duì)象,這樣才能調(diào)用方法來(lái)解包處理。
body, _ := ioutil.ReadAll(resp.Body) var rst = ResultInfo{} if err := json.Unmarshal(body, &rst); err != nil { fmt.Println(err) }
寫(xiě)數(shù)據(jù)到Excel
這部分調(diào)用的都是第三方庫(kù),所以沒(méi)什么可比性,代碼的實(shí)現(xiàn)完全依賴(lài)于第三方包。
無(wú)所不在的err != nil
Go的異常捕獲機(jī)制跟Python或者Java都不一樣,Python的異常捕獲使用的是try,except來(lái)包裹代碼塊,而Go用的是一個(gè)error對(duì)象,所以所有的Go代碼都會(huì)充斥著大量的
if err != nil { return nil, err }
這種鬼東西,這種異常機(jī)制在閱讀代碼的時(shí)候,非常惡心,極大的影響了閱讀體驗(yàn)。
吐槽完后
基本上從書(shū)寫(xiě)代碼的過(guò)程來(lái)看,Python的編碼效率比Go高出了很多很多,Go號(hào)稱(chēng)語(yǔ)法靈活,可以極大的提高編碼效率,實(shí)際上并沒(méi)有,受限于靜態(tài)語(yǔ)言,相比于Python這種動(dòng)態(tài)語(yǔ)言來(lái)說(shuō),編碼效率的差距還是非常大的。只能說(shuō)比其他靜態(tài)語(yǔ)言編碼效率高。
但是?。?!
Go的效率比Python高了太多。舉個(gè)例子,有一個(gè)計(jì)算斐波那契數(shù)的算法,Go的實(shí)現(xiàn)如下: func main() { const n = 40 starttime := time.Now() fibN := fib(n) endtime := time.Now() cost_time := endtime.Sub(starttime) fmt.Println(cost_time) fmt.Printf("\rFibonacci(%d) = %d\n", n, fibN) } func fib(x int) int { if x < 2 { return x } return fib(x-1) + fib(x-2) }
很簡(jiǎn)單的一個(gè)遞歸,當(dāng)N為40的時(shí)候,Go花了大概1秒左右的時(shí)間,執(zhí)行結(jié)果如下:
876.838ms(消耗時(shí)間) Fibonacci(40) = 102334155
我們換成Python
def fib(x): if x<2: return x return fib(x-1)+fib(x-2) if __name__ == '__main__': import time begin = time.time() print fib(40) end = time.time() print end-begin
一樣的執(zhí)行邏輯,執(zhí)行的結(jié)果卻是:
102334155 52.8657081127(消耗時(shí)間)
WTF!!! 用Go來(lái)處理效率是Python的50倍以上。
還沒(méi)完,工具寫(xiě)完了總是要給人用的吧,Python寫(xiě)完之后,如果給一個(gè)非技術(shù)人員使用,那么。。。
使用者:要怎么用? 我:你裝一下Python,然后配好環(huán)境變量,順便把requests庫(kù)和xlwt庫(kù)也裝一下。 我:要裝這兩個(gè)庫(kù)你要先裝一下pip。 使用者:黑人問(wèn)號(hào)臉!?。。?!
如果你用Go來(lái)寫(xiě),打包完發(fā)過(guò)去就行了
使用者:要怎么用? 我:你雙擊一下,讓你輸入什么就輸入什么
如果使用者是用Windows系統(tǒng),那也沒(méi)問(wèn)題,
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build xxx.go
直接打包成exe文件
知識(shí)點(diǎn)擴(kuò)展:
什么是Python?
Python是一種功能強(qiáng)大的高級(jí)編程語(yǔ)言,主要用于科學(xué)和工程計(jì)算。它是一種高效的語(yǔ)言,優(yōu)雅務(wù)實(shí),簡(jiǎn)單而強(qiáng)大,適合新手和專(zhuān)業(yè)人士的編程。
Python支持多種編程范例,并提出了一個(gè)大型標(biāo)準(zhǔn)庫(kù),包括面向?qū)ο?,命令式,功能性和程序性?/p>
Go是什么?
Go是一種通用編程語(yǔ)言,由Google設(shè)計(jì);它借鑒了許多其他許多好主意語(yǔ)言,同時(shí)避免導(dǎo)致復(fù)雜性和不可靠代碼的功能。
Go支持多范式,如程序,功能和并發(fā)。它的語(yǔ)法傳統(tǒng)上來(lái)自C語(yǔ)言,但它已經(jīng)做了很多修改,以改進(jìn)簡(jiǎn)單性和安全性等功能。
到此這篇關(guān)于python和go語(yǔ)言的區(qū)別是什么的文章就介紹到這了,更多相關(guān)go語(yǔ)言和python有什么區(qū)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python+Tableau廣東省人口普查可視化的實(shí)現(xiàn)
本文將結(jié)合實(shí)例代碼,介紹Python+Tableau廣東省人口普查可視化,第七次人口普查數(shù)據(jù)分析,繪制歷次人口普查人口數(shù)量變化圖,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06python3.6連接mysql數(shù)據(jù)庫(kù)及增刪改查操作詳解
這篇文章主要介紹了python3.6 連接mysql數(shù)據(jù)庫(kù)及增刪改查操作詳解,需要的朋友可以參考下2020-02-02Python學(xué)習(xí)之.iloc與.loc的區(qū)別、聯(lián)系和用法
loc和iloc都是pandas工具中定位某一行的函數(shù),下面這篇文章主要給大家介紹了關(guān)于Python學(xué)習(xí)之.iloc與.loc的區(qū)別、聯(lián)系和用法的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05Python進(jìn)階學(xué)習(xí)修改閉包內(nèi)使用的外部變量
這篇文章主要為大家介紹了Python進(jìn)階學(xué)習(xí)修改閉包內(nèi)使用的外部變量實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06python?查看cpu的核數(shù)實(shí)現(xiàn)
這篇文章主要介紹了python?查看cpu的核數(shù)的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05使用PyV8在Python爬蟲(chóng)中執(zhí)行js代碼
PyV8是chrome用來(lái)執(zhí)行javascript的引擎,據(jù)說(shuō)是最快的js引擎,通過(guò)pyv8的封裝,可以在python中使用。下面這篇文章主要介紹了使用PyV8在Python爬蟲(chóng)中執(zhí)行js代碼的相關(guān)資料,需要的朋友可以參考下。2017-02-02OpenCV圖像修復(fù)cv2.inpaint()的使用
這篇博客將介紹如何通過(guò)OpenCV中圖像修復(fù)的技術(shù)——cv2.inpaint() 去除舊照片中的小噪音、筆劃等。并提供一個(gè)可交互式的程序,感興趣的可以了解一下2021-08-08