在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Go語言的設(shè)計(jì)上存在四大“硬傷”

DPVg_AI_era ? 來源:lp ? 2019-03-29 08:50 ? 次閱讀

Go語言為何不受待見?事實(shí)上,Go仍然是一種相當(dāng)不錯(cuò)的語言,并且逐漸取代Python成為很多人的首選語言。但是其卻有一些問題,使得開發(fā)速度大受影響。本文就跟隨作者一起解讀下Go中那些“硬傷”設(shè)計(jì)。

Go作為一種編程語言來說是相當(dāng)體面的,然而,我在公司Slack(譯者注:一種團(tuán)隊(duì)協(xié)作工具)的編程頻道上對(duì)它的抱怨卻越來越多(猜到我是做啥了的吧?)。我想我還是把這些抱怨寫下來放在這里,這樣當(dāng)人們問我到底抱怨什么時(shí),我就可以給他們一個(gè)鏈接,讓他們直接到這里來看。

過去一年左右的時(shí)間我都一直在大量地使用Go語言來編程,寫一些命令行應(yīng)用程序、scc(https://github.com/boyter/scc/)、lc(https://github.com/boyter/lc/)和一些API等等。

其中包括一個(gè)供客戶端調(diào)用代碼高亮插件(https://github.com/boyter/searchcode-server-highlighter)的大規(guī)模API,這個(gè)代碼高亮插件很快將會(huì)在https://searchcode.com/網(wǎng)站中使用。

我在這里的批評(píng)是專門針對(duì)Go編程語言的。然而,我對(duì)我使用的每種編程語言都有抱怨。這里我引用一下C++編程語言之父Bjarne Stroustrup說過的一句話:

“世界上只有兩種編程語言:一種是人們抱怨的語言,另一種是沒人使用的語言。”

——Bjarne Stroustrup

缺乏函數(shù)式編程

我不是一個(gè)函數(shù)式編程的狂熱分子。Lisp語言讓我首先想到的是語言障礙,這可能是我使用Go語言編程時(shí)最痛苦的地方。

和大多數(shù)開發(fā)者不一樣,我不想要泛型,我認(rèn)為這只會(huì)給大多數(shù)Go項(xiàng)目增加不必要的復(fù)雜性。我想要的是一些可以應(yīng)用于內(nèi)置的Slice(切片)和Map類型之上的函數(shù)方法。Slice和Map這兩種類型都可以容納任何類型,而且是泛型的,這種在某種意義上很神奇。然而Go的泛型不使用接口的話,就無法實(shí)現(xiàn)自己,這樣就損失了所有的安全性和性能。

舉個(gè)例子,考慮下面的需求。

給定兩個(gè)字符串片斷,找出這兩段字符串片斷中都包含的相同的子字符串,并將其放入一個(gè)新的字符串片斷中,以便我們稍后處理它。

existsBoth:=[]string{}for_,first:=rangefirstSlice{for_,second:=rangesecondSlice{iffirst==second{existsBoth=append(existsBoth,proxy)break}}}

上面的Go語言的解決方法很簡(jiǎn)單。但我們還有其他方法,如使用Map來解決這個(gè)問題,使用Map可以減少運(yùn)行時(shí)間,但是如果我們的內(nèi)存容量有限,或者我們沒有很大的片斷需要處理,那么額外的運(yùn)行時(shí)間并不足以抵消它帶來的復(fù)雜性。

讓我們將其與Java中使用Stream和函數(shù)編程來實(shí)現(xiàn)相同邏輯的代碼比較一下。

varexistsBoth=firstList.stream().filter(x->secondList.contains(x)).collect(Collectors.toList());

上面的代碼確實(shí)將算法的復(fù)雜性隱藏起來,從代碼上看清楚要實(shí)現(xiàn)的邏輯容易得多。

與實(shí)現(xiàn)同樣功能的Go代碼相比,上面的代碼的意圖是顯而易見的,真正的簡(jiǎn)潔之處是添加額外的過濾器也變得非常簡(jiǎn)單。而如果用Go語言實(shí)現(xiàn)像下面的示例一樣添加額外的過濾器,我們就必須在已經(jīng)嵌套的for循環(huán)中再添加兩個(gè)if條件。

varexistsBoth=firstList.stream().filter(x->secondList.contains(x)).filter(x->x.startsWith(needle)).filter(x->x.length()>=5).collect(Collectors.toList());

有一些使用Go Generate的項(xiàng)目可以為你做到上面所說的,但是如果沒有好的IDE支持的話,將上面的循環(huán)提取到它自己的方法中會(huì)非常笨重,而且會(huì)帶來更多的麻煩。

通道(channel)/并行切片(Slice)處理

Go的通道(channel)通常非常簡(jiǎn)潔。雖然它們存在一些問題會(huì)導(dǎo)致它永久阻塞,但它們并不打算提供安全的并發(fā)性,因?yàn)橥ㄟ^競(jìng)爭(zhēng)檢測(cè)機(jī)制可以很容易地?cái)[脫這些問題。對(duì)于一個(gè)不知道有多少個(gè)值或何時(shí)結(jié)束的流,或者如果處理這些值的方法不受CPU的制約,那么通道是一個(gè)很好的選擇。

通道不太擅長(zhǎng)的是處理那些預(yù)先知道大小并希望并行處理的切片(Slice)。

并行處理在幾乎所有其他語言中都很常見,通常發(fā)生在你有一個(gè)大的列表或切片,使用并行流、并行LINQ(語言集成查詢)、Rayon(一種數(shù)據(jù)并行庫)、多進(jìn)程或其他一些語法,使用所有可用的CPU,對(duì)該列表/切片進(jìn)行迭代處理時(shí)。你將它們應(yīng)用到你的列表上,然后返回處理好的元素列表。如果你的列表有太多的元素,或者你正在使用的函數(shù)太復(fù)雜,使用一個(gè)多核系統(tǒng)應(yīng)該也可以更快地完成。

然而,在Go語言中,你需要怎么實(shí)現(xiàn)它并不明確。

一種可能的解決方法是為切片中的每個(gè)元素生成一個(gè)goroutine。因?yàn)間oroutine的開銷很低,所以在某種程度上,這是一個(gè)有效的策略。

toProcess:=[]int{1,2,3,4,5,6,7,8,9}varwgsync.WaitGroupfori,_:=rangetoProcess{wg.Add(1)gofunc(jint){toProcess[j]=someSlowCalculation(toProcess[j])wg.Done()}(i)}wg.Wait()fmt.Println(toProcess)

上面的代碼會(huì)保持切片中元素的順序,但是我們的例子并不要求實(shí)現(xiàn)這點(diǎn)。

上面的問題首先是添加一個(gè)waitgroup,并且必須記住遞增并調(diào)用它。這對(duì)開發(fā)人員開說是額外負(fù)擔(dān)。如果弄錯(cuò)了,這個(gè)程序?qū)⒉粫?huì)產(chǎn)生正確的輸出,可能是不確定的結(jié)果,也可能永遠(yuǎn)不會(huì)執(zhí)行完成。

另外,如果你的列表很長(zhǎng),你要為列表中每個(gè)單獨(dú)的元素生成一個(gè)goroutine。正如我之前所說,這本身不是一個(gè)問題,因?yàn)镚o語言能毫無問題地做到這一點(diǎn)。但問題是,每一個(gè)goroutine都要為使用CPU的時(shí)間片而競(jìng)爭(zhēng)。因此這不是執(zhí)行此任務(wù)的最有效方法。

你可能想做的是為每個(gè)CPU生成一個(gè)goroutine,并讓它們依次挑選處理它的列表。增加一個(gè)goroutine的開銷很小,但是對(duì)于一個(gè)迭代次數(shù)很多的循環(huán)來說,這個(gè)開銷并不算小。當(dāng)我在為scc項(xiàng)目工作時(shí),我遇到了這個(gè)問題,它在每個(gè)CPU的內(nèi)核上創(chuàng)建了一個(gè)goroutine。如果要完全用Go語言的方式來解決這個(gè)問題,你就需要?jiǎng)?chuàng)建一個(gè)通道,然后循環(huán)你的每個(gè)切片元素,讓你的函數(shù)從該通道讀取,然后再從另一個(gè)通道讀取。

讓我們看看代碼。

toProcess:=[]int{1,2,3,4,5,6,7,8,9}varinput=make(chanint,len(toProcess))fori,_:=rangetoProcess{input<-?i}close(input)var?wg?sync.WaitGroupfor?i?:=?0;?i?

上面的代碼先是創(chuàng)建了一個(gè)通道,循環(huán)我們的切片并將每個(gè)值放入其中。接著,為每個(gè)CPU內(nèi)核創(chuàng)建一個(gè)goroutine來處理輸入的值,然后等待它全部完成。要消化的代碼很多。

這不是一個(gè)你應(yīng)該怎么做的問題,因?yàn)槿绻愕那衅浅4螅憧赡懿幌胗幸粋€(gè)具有相同長(zhǎng)度的緩沖區(qū)的通道,所以你實(shí)際上應(yīng)該創(chuàng)建另一個(gè)goroutine來循環(huán)切片,并將這些值放入通道。當(dāng)處理完成后,它關(guān)閉通道。我已經(jīng)刪除了這個(gè)代碼,因?yàn)樗勾a變得更長(zhǎng),而且我已經(jīng)基本上知道怎么做了。

Java的做法和上面大致相同。

varfirstList=List.of(1,2,3,4,5,6,7,8,9);firstList=firstList.parallelStream().map(this::someSlowCalculation).collect(Collectors.toList());

是的,Go語言的通道(channel)和Java中的流(stream)并不是一回事,通道更接近于Java中的隊(duì)列(queue),但我們這里的目的不是1對(duì)1的對(duì)比。我們想要的是使用我們所有的CPU內(nèi)核來處理一個(gè)切片/列表。

當(dāng)然,如果某個(gè)slowcaluation實(shí)際上是一個(gè)在網(wǎng)絡(luò)上調(diào)用的方法,或者是其他一些需要大量CPU的方法,那么這就不是一個(gè)問題。在這種情況下,通道和goroutine都很出色。

這一問題與缺乏函數(shù)式編程有關(guān)。如果Go語言在slice/map對(duì)象之上有函數(shù)方法,那么添加這個(gè)功能是可能的。這也很煩人,因?yàn)槿绻鸊o支持泛型的話,就會(huì)有人可以把上面談到的寫成一個(gè)函數(shù)庫,就像Rust的Rayon一樣,每個(gè)人都會(huì)受益。

順便說一句,我認(rèn)為這一點(diǎn)阻礙了Go語言在數(shù)據(jù)科學(xué)領(lǐng)域的任何成功,因此,為什么Python仍然是那里的王者。而Go語言在數(shù)字操作中缺乏表現(xiàn)力和力量——以上就是原因。

垃圾回收(GC)

Go語言的垃圾回收機(jī)制非常可靠。每次Go語言版本更新,我都發(fā)現(xiàn)我的應(yīng)用程序變得更快了,原因通常是因?yàn)镚C的改進(jìn)。將延遲的優(yōu)先級(jí)置于所有其它要求之上,對(duì)于API和UI來說,是一個(gè)完全可以接受的選擇。同樣地它也適用于任何有網(wǎng)絡(luò)呼叫的情況,這些呼叫也會(huì)成為瓶頸。

關(guān)鍵是Go語言對(duì)UI功能的實(shí)現(xiàn)沒有任何好處(據(jù)我所知沒有合適的綁定),當(dāng)你需要盡可能大的吞吐量時(shí),這個(gè)選擇確實(shí)會(huì)傷害你。我在處理scc項(xiàng)目時(shí)遇到了一個(gè)大問題,scc是一個(gè)命令行應(yīng)用程序,對(duì)CPU的要求很高。這是個(gè)問題,我添加了一個(gè)邏輯來關(guān)閉內(nèi)存回收機(jī)制,直到內(nèi)存使用量達(dá)到閾值。但是,我不能禁用它,因?yàn)槌绦蛟谀承┣闆r下工作時(shí)很快就會(huì)耗盡內(nèi)存。

對(duì)GC缺乏控制有時(shí)令人沮喪。你學(xué)會(huì)了接受它,但有時(shí)你會(huì)說“嘿,這里的代碼真的需要盡可能快的運(yùn)行,所以如果能切換到高吞吐量模式一段時(shí)間,那就太好了。”

我認(rèn)為隨著Go語言的1.12版本的發(fā)布,這一點(diǎn)變得越來越不可能了,在這個(gè)版本中,GC看起來再次得到了改進(jìn),但是僅僅關(guān)閉和打開GC并不是我想要的控制。有時(shí)間的話我會(huì)再次深入了解一下。

錯(cuò)誤處理

我不是唯一一個(gè)對(duì)這點(diǎn)有抱怨的人,但我必須寫出來。

value,err:=someFunc()iferr!=nil{//Dosomethinghere}err=someOtherFunc(value)iferr!=nil{//Dosomethinghere}

上面的代碼看起來相當(dāng)乏味。Go語言甚至不強(qiáng)制你處理大家建議的錯(cuò)誤。你可以顯式忽略它(這是否算作處理它?),你甚至可以完全忽略它。例如,我可以像這樣重寫上面的內(nèi)容:

value,_:=someFunc()someOtherFunc(value)

你很容易發(fā)現(xiàn)我省略了somefunc返回的內(nèi)容,但是someotherfunc(value)同時(shí)也可以返回錯(cuò)誤,而我卻完全忽略了這個(gè)錯(cuò)誤,對(duì)它不作任何處理。

老實(shí)說,我不知道有這里有什么解決辦法。不過我喜歡Rust言語的問號(hào)(?)操作符,它可以避免這個(gè)問題。另外V-Lang(https://vlang.io/)看起來也可能有一些有趣的解決方案。

另一個(gè)想法是可選類型(Optional Type)和刪除nil,但是這些在Go語言的2.0版本中是永遠(yuǎn)不會(huì)出現(xiàn)的,因?yàn)樗鼤?huì)破壞向后兼容性。

總結(jié)

總的來講,Go仍然是一種相當(dāng)不錯(cuò)的語言。如果你要我要寫一個(gè)API,或者一些需要快速進(jìn)行大量磁盤/網(wǎng)絡(luò)調(diào)用的應(yīng)用,它仍然是我的第一選擇。事實(shí)上,我正處在這樣一個(gè)階段:Go已經(jīng)取代Python,成為我要完成的大量的一次性任務(wù)的首選語言。數(shù)據(jù)合并任務(wù)除外,因?yàn)槿狈瘮?shù)式編程仍然是一件痛苦的事情,這使得開發(fā)速度大受影響。

對(duì)諸如像字符串stringA == stringB和編譯錯(cuò)誤的比較,你會(huì)發(fā)現(xiàn)Go語言的切片用在這里非常合適。它不像我在上面用來比較的Java語言那樣經(jīng)常有出人意料的結(jié)果。

Go的二進(jìn)制文件的大小可以更小(一些編譯開關(guān)和upx(可執(zhí)行文件壓縮工具)可以解決這個(gè)問題),我希望它在某些方面運(yùn)行得更快一些,GOPATH不是很好,但也沒有每個(gè)人所說的那么糟糕,默認(rèn)的單元測(cè)試框架缺少很多功能,Mocking有點(diǎn)痛苦等等。

Go仍然是我使用過的一種更有效的語言。我會(huì)繼續(xù)使用它,盡管我希望https://vlang.io/最終能夠發(fā)布并且解決我的許多投訴的問題。它可能Go 2.0版,可能是Nim,也可能是Rust。現(xiàn)在有很多很酷的新語言可以玩。我們的開發(fā)人員真的被寵壞了。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 編程語言
    +關(guān)注

    關(guān)注

    10

    文章

    1951

    瀏覽量

    35019
  • 過濾器
    +關(guān)注

    關(guān)注

    1

    文章

    433

    瀏覽量

    19758
  • go語言
    +關(guān)注

    關(guān)注

    1

    文章

    158

    瀏覽量

    9094

原文標(biāo)題:Go 語言為何不受待見?

文章出處:【微信號(hào):AI_era,微信公眾號(hào):新智元】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Go語言中的整數(shù)類型

    Go 語言中,整型可以細(xì)分成兩個(gè)種類十個(gè)類型。
    發(fā)表于 07-20 15:25 ?978次閱讀

    Go語言開發(fā)有什么優(yōu)勢(shì)?怎么學(xué)?

    的方式全面的闡述Go在高并發(fā)、大流量方面的應(yīng)用,課程中采用的個(gè)項(xiàng)目全部來自大公司實(shí)實(shí)在在的線上案例,并不是通過簡(jiǎn)化的、閹割過的項(xiàng)目。可以學(xué)習(xí)到Go語言理論與應(yīng)用的最佳實(shí)踐,高并發(fā)服務(wù)
    發(fā)表于 12-19 16:08

    會(huì)go語言能做什么工作?

    Go語言主要用作服務(wù)器端開發(fā),其定位是用來開發(fā)“大型軟件”的,適合于很多程序員一起開發(fā)大型軟件,并且開發(fā)周期長(zhǎng),支持云計(jì)算的網(wǎng)絡(luò)服務(wù)。Go語言能夠讓程序員快速開發(fā),并且在軟件不斷的增長(zhǎng)
    發(fā)表于 03-22 15:03

    Go開發(fā)語言的優(yōu)勢(shì)在哪里?

    進(jìn)程。對(duì)于Go語言,一直存在著爭(zhēng)議,很多人善于用Go語言進(jìn)行開發(fā),但不是所有人都喜歡Go
    發(fā)表于 03-22 15:04

    購買充電電池存在四大誤區(qū)

    購買充電電池存在四大誤區(qū) 現(xiàn)今充電電池性能越來越好,價(jià)格越來越低,相對(duì)與普通不可充電池已經(jīng)顯得更經(jīng)濟(jì)環(huán)保,人們的
    發(fā)表于 11-04 15:22 ?989次閱讀

    購買充電電池存在四大誤區(qū)

    購買充電電池存在四大誤區(qū)  現(xiàn)今充電電池性能越來越好,價(jià)格越來越低,相對(duì)與普通不可充電池已經(jīng)顯得更經(jīng)濟(jì)環(huán)保,人們的充電電
    發(fā)表于 11-04 17:02 ?2856次閱讀

    網(wǎng)易有道CEO周楓推薦Go語言并介紹Go語言的3個(gè)優(yōu)點(diǎn)

    網(wǎng)易有道CEO周楓推薦Go語言。他認(rèn)為Go很好地繼承了C語言靈活、簡(jiǎn)單有效的思想;Go有很高的生產(chǎn)效率;
    的頭像 發(fā)表于 01-31 14:11 ?5247次閱讀

    詳解GO語言的趨勢(shì)與使用情況

    Go 語言簡(jiǎn)單易學(xué)、性能優(yōu)良。JetBrains Blog 發(fā)布了Go 語言的調(diào)查報(bào)告,看看GO 語言
    的頭像 發(fā)表于 03-17 11:05 ?3091次閱讀

    Go語言憑借什么成為云原生第一語言的?

    偶然看到有人說, Go 語言目前的火爆可能就是曇花一現(xiàn)而已。這個(gè)觀點(diǎn)我當(dāng)然是不認(rèn)同的。 近幾年,關(guān)于 Go 與 Java 還有 C 的對(duì)比和討論愈演愈烈,但不可否認(rèn)的是,在十年多的時(shí)間里,Go
    的頭像 發(fā)表于 04-22 10:15 ?3236次閱讀
    <b class='flag-5'>Go</b><b class='flag-5'>語言</b>憑借什么成為云原生第一<b class='flag-5'>語言</b>的?

    詳解剖析Go語言調(diào)度模型的設(shè)計(jì)

    kernel and perform most of their tasks. 所有在 UNIX 系統(tǒng)運(yùn)行的程序最終都會(huì)通過 C 系統(tǒng)調(diào)用來和內(nèi)核打交道。 用其他語言編寫程序進(jìn)行系統(tǒng)調(diào)用,方法不外乎兩個(gè):一是自己封裝,二是依賴 glibc、或者其他的運(yùn)行庫。
    的頭像 發(fā)表于 07-26 10:12 ?2150次閱讀
    詳解剖析<b class='flag-5'>Go</b><b class='flag-5'>語言</b>調(diào)度模型的設(shè)計(jì)

    go語言枚舉類型怎么用

    go 語言枚舉類型是這么用的?在什么場(chǎng)景下會(huì)用到枚舉?本文對(duì) go 語言枚舉做了詳細(xì)講解。 枚舉,是一種重要的數(shù)據(jù)類型,由一組鍵值對(duì)組成,通常用來在編程
    的頭像 發(fā)表于 09-02 09:43 ?5244次閱讀

    帶你了解go語言中的閉包

    ? 【 導(dǎo)讀】什么是閉包? 什么場(chǎng)景下會(huì)用閉包 ? 本文對(duì) go 語言中的閉包做了詳細(xì)介紹。 閉包是由函數(shù)及其相關(guān)引用環(huán)境組合而成的實(shí)體(即:閉包=函數(shù)+引用環(huán)境)。 Go中的閉包 閉包是函數(shù)式
    的頭像 發(fā)表于 11-02 15:27 ?2508次閱讀

    Go 語言在極小硬件的運(yùn)用(三) | Linux 中國

    Go 語言在極小硬件的運(yùn)用(三) | Linux 中國
    發(fā)表于 11-23 18:21 ?8次下載
    <b class='flag-5'>Go</b> <b class='flag-5'>語言</b>在極小硬件<b class='flag-5'>上</b>的運(yùn)用(三) | Linux 中國

    go語言中怎么使用HTTP代理

    go語言中怎么使用HTTP代理。
    的頭像 發(fā)表于 09-01 14:41 ?2474次閱讀

    go語言如何解決并發(fā)問題

    作為一個(gè)后端開發(fā),日常工作中接觸最多的兩門語言就是PHP和GO了。無可否認(rèn),PHP確實(shí)是最好的語言(手動(dòng)狗頭哈哈),寫起來真的很舒爽,沒有任何心智負(fù)擔(dān),字符串和整型壓根就不用區(qū)分,開發(fā)速度真的是比
    的頭像 發(fā)表于 10-23 13:38 ?181次閱讀
    <b class='flag-5'>go</b><b class='flag-5'>語言</b>如何解決并發(fā)問題
    主站蜘蛛池模板: 国产精品第九页 | 一区二区三区在线免费 | 寡妇一级a毛片免费播放 | 日本高清黄色 | 男女在线观看视频 | 8050午夜一级二级全黄 | 久久久久久人精品免费费看 | 日韩午夜精品 | 牛仔裤美女国产精品毛片 | xxx亚洲日本 | 亚洲三级在线免费观看 | 男女交性视频免费视频 | 久久九色 | 久久99精品久久久久久久不卡 | 大尺度在线播放 | 亚欧精品一区二区三区 | 午夜影剧院| 亚洲精品第三页 | 人人艹人人射 | 一区国产传媒国产精品 | 中文字幕一区二区三区在线观看 | 2021国产成人精品久久 | 久草福利在线播放 | 亚洲成人在线网 | 国产视频久 | 国产免费卡1卡2卡 | 日本黄色高清视频网站 | 日本媚薬痉挛在线观看免费 | 色99色| 天天干天天爱天天操 | 婷婷综合七月激情啪啪 | 欧美色视频日本片免费高清 | 4388x17亚洲最大成人网 | 欧美视频小说 | 免费看国产一级特黄aa大片 | 日本理论午夜中文字幕第一页 | 香港三澳门三日本三级 | 91九色成人 | 欧美网站在线播放 | 天天做人人爱夜夜爽2020 | bt在线搜索|