當前位置:首頁 » 編程軟體 » go編譯太慢

go編譯太慢

發布時間: 2023-06-28 13:48:31

㈠ 筆記本電腦編譯C語言特別的慢,請問下原因

筆記本C語言程序運行慢是怎麼回事
用的什麼版本的c++?如果是vs2003以上的就是機器配置太低,如果是6.0還這么慢的話有可能是裝的有問題,重新裝一下沒准就能好一些了,最好默認安裝,如果是n年以前的機器那就沒辦法了,只能是配置太低,不過我們實驗室的機器256的內存都能用6.0,再有就是看看有沒有被中肉機。
如果是gcc或者tc的話,那隻能是裝壞了或者中毒了。

㈡ Golang 讀文件為什麼這么慢

我發現golang用做webserver較多,和nodejs做webserver類似,但golang是靜態語言,更容易在編譯時發現錯誤,避免編程隨意性。golang把代碼靜態編譯成windows,linux,osx的各個平台的可執行文件,不需要依賴其他的東西就可以直接運行。同時自動了很...

㈢ 為什麼許多原本的 Java 項目都試圖用 go 進行重寫開源

項目推倒重構是項目開發大忌,一方面我們要盡量避免做項目推倒重構,盡量在前期就規劃好,另一方面,我們又希望項目能常做小重構,這對項目可持續性開發是很有幫助的。而語言的重構,把Java項目用Go語言重寫一遍,無疑是一次重大的推倒重來。


一、Go語言的優勢在哪裡

Go語言領先於Java的最大優勢,就在於快。Go語言會被編譯成機器代碼,直接執行;Java語言則使用JVM運行其代碼,這比Go語言要慢了很多。另外,Java語言的內存管理,相比於Go語言,也復雜得多,而內存管理,不管對於程序運行,還是對程序員的開發,都極為重要。最後,Go語言沒有引用只有指針,這比Java語言處處引用,又領先了一個身位。

㈣ windows 怎麼編譯 go語言

1、解壓壓縮包到go工作目錄,如解壓到E:\opensource\go\go,解壓後的目錄結構如下:

E:\opensource\go\go
├─api
├─bin
│ ├─go.exe
│ ├─godoc.exe
│ └─gofmt.exe
├─doc
├─include
├─lib
├─misc
├─pkg
├─src
└─test

2、增加環境變數GOROOT,取值為上面的go工作目錄
3、Path環境變數中添加";%GOROOT%\bin",以便能夠直接調用go命令來編譯go代碼,至此go編譯環境就配置好了
註:如果不想手動設置系統環境變數,也可下載go啟動環境批處理附件,
修改goenv.bat文件中的GOROOT值為上面的go工作目錄後直接雙擊該bat文件,go編譯環境變數即設置完成。
4、測試go編譯環境,啟動一個cmd窗口,直接輸入go,看到下面的提示就是搭建成功了

E:\opensource\go\go>go
Go is a tool for managing Go source code.

Usage:

go command [arguments]

The commands are:

build compile packages and dependencies
clean remove object files
doc run godoc on package sources
env print Go environment information
fix run go tool fix on packages
fmt run gofmt on package sources
get download and install packages and dependencies
install compile and install packages and dependencies
list list packages
run compile and run Go program
test test packages
tool run specified go tool
version print Go version
vet run go tool vet on packages

Use "go help [command]" for more information about a command.

Additional help topics:

gopath GOPATH environment variable
packages description of package lists
remote remote import path syntax
testflag description of testing flags
testfunc description of testing functions

Use "go help [topic]" for more information about that topic.

5、編譯helloworld測試程序,go語言包中test目錄帶有helloworld.go測試程序,源碼見"附一 helloworld.go",
直接調用"go build helloworld.go"就生成了"helloworld.exe"可執行程序,運行一下這個程序看到了我們期望的hello,wolrd。

E:\opensource\go\go\test>go build helloworld.go

E:\opensource\go\go\test>helloworld.exe
hello, world

E:\opensource\go\go\test>

附一 helloworld.go

// cmpout

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Test that we can do page 1 of the C book.

package main

func main() {
print("hello, world\n")
}

㈤ 為什麼要使用 Go 語言Go 語言的優勢在哪裡

已經有好多程序員都把Go語言描述為是一種所見即所得(WYSIWYG)的編程語言。這是說,代碼要做的事和它在字面上表達的意思是完全一致的。 在這些新語言中,包含D,Go,Rust和Vala語言,Go曾一度出現在TIOBE的排行榜上面。與其他新語言相比,Go的魅力明顯要大很多。Go的成熟特徵會得到許多開發者的欣賞,而不僅僅是因為其誇大其詞的曝光度。下面我們來一起探討一下谷歌開發的Go語言以及談談Go為什麼會吸引眾多開發者: 快速簡單的編譯 Go編譯速度很快,如此快速的編譯使它很容易作為腳本語言使用。關於編譯速度快主要有以下幾個原因:首先,Go不使用頭文件;其次如果一個模塊是依賴A的,這反過來又取決於B,在A裡面的需求改變只需重新編譯原始模塊和與A相依賴的地方;最後,對象模塊裡麵包含了足夠的依賴關系信息,所以編譯器不需要重新創建文件。你只需要簡單地編譯主模塊,項目中需要的其他部分就會自動編譯,很酷,是不是? 通過返回數值列表來處理錯誤信息 目前,在本地語言裡面處理錯誤的方式主要有兩種:直接返回代碼或者拋異常。這兩種都不是最理想的處理方式。其中返回代碼是非常令人沮喪的,因為返回的錯誤代碼經常與從函數中返回的數據相沖突。Go允許函數返回多個值來解決這個問題。這個從函數裡面返回的值,可以用來檢查定義的類型是否正確並且可以隨時隨地對函數的返回值進行檢查。如果你對錯誤值不關心,你可以不必檢查。在這兩種情況下,常規的返回值都是可用的。 簡化的成分(優先於繼承) 通過使用介面,類型是有資格成為對象中一員的,就像Java指定行為一樣。例如在標准庫裡面的IO包,定義一個Writer來指定一個方法,一個Writer函數,其中輸入參數是位元組數組並且返回整數類型值或者錯誤類型。任何類型實現一個帶有相同簽名的Writer方法是對IO的完全實現,Writer介面。這種是解耦代碼而不是優雅。它還簡化了模擬對象來進行單元測試。例如你想在資料庫對象中測試一個方法,在標准語言中,你通常需要創建一個資料庫對象,並且需要進行大量的初始化和協議來模擬對象。在Go裡面,如果該方法需要實現一個介面,你可以創建任何對該介面有用的對象,所以,你創建了MockDatabase,這是很小的對象,只實現了幾個需要運行和模擬的介面——沒有構造函數,沒有附件功能,只是一些方法。 簡化的並發性 相對於其他語言,並發性在Go裡面顯得更加容易。把『go』關鍵字放在任意函數前面然後那個函數就會在其go-routine自動運行(一個很輕的線程)。go-routines是通過通道進行交流並且基本上封鎖了所有的隊列消息。普通工具對相互排斥是有用,但是Go通過使用通道來踢掉並發性任務和坐標更加容易。 優秀的錯誤消息 所有與Go相似的語言,自身作出的診斷都是無法與Go相媲美的。例如,一個死鎖程序,在Go運行時會通知你目前哪個線程導致了這種死鎖。編譯的錯誤信息是非常詳細全面和有用的。 其他 這里還有許多其他吸引人的地方,下面就一概而過的介紹一下,比如高階函數、垃圾回收、哈希映射和可擴展的數組內置語言(部分語言語法,而不是作為一個庫)等等。 當然,Go並不是完美無瑕。在工具方面還有些不成熟的地方和用戶社區較小等,但是隨著谷歌語言的不斷發展,肯定會有整治措施出來。盡管許多語言,尤其是D、Rust和Vala旨在簡化C++並且對其進行簡化,但它們給人的感覺仍是「C++看上去要更好」。

㈥ 使用Go 語言開發大型 MMORPG 游戲伺服器怎麼樣

使用Go 語言開發大型 MMORPG 游戲伺服器怎麼樣

如果是大型網路游戲的話,我覺得是不合適的。現階段go語言的執行效率還是太低了。在底層編譯器的優化方面做得和c++相比還是差了不少。go語言也是比較適合快速開發的專案比較合適

從2013年起,經朋友推薦開始用Golang編寫游戲登殲兆陸伺服器, 配合C++做第三方平台驗證. 到編寫獨立工具導表工具GitHub - davyxu/tabtoy: 跨平台的高效能便捷電子表格匯出器. 以及網路庫GitHub - davyxu/cell: 簡單,方便,高效的Go語言的游戲伺服器底層. 最終使用這些工具及庫編寫整個游戲伺服器框架, 我的感受是很不錯的
細節看來, 有如下的幾個點:
語言, 庫
Golang語言特性和C很像, 簡單, 一張A4紙就能寫完所有特性. 你想想看, C++到了領悟階段, 也只用那幾個簡單特性, 剩下的都是一大堆解決各種記憶體問題的技巧. 而Golang一開始就簡單, 何必浪費生命去研究那一大堆的奇技淫巧呢?
Golang的坑只有2個:1. interface{}和nil配合使用, 2. for迴圈時, 將迴圈變數引入閉包(Golang, Lua, C#閉包變數捕獲差異) 完全不影響正常使用, 復合語言概念, 只是看官方後面怎麼有效的避免
用Golang就忘記繼承那套東西, 用組合+介面
用Golang伺服器如何保證解決游戲伺服器存檔一致性問題? s the world是肯定的, 但是Golang可以從語言層並發序列化玩家資料, 再通過後台存檔
channel是goroutine雖然是Golang的語言特性. 但是在編寫伺服器時, 其實只有底層用的比較多.
Golang的第三方庫簡直多如牛毛, 好的也很多
不要說模板了, C#的也不好用, 官方在糾結也不要加, 使用中, 沒模板確實有點不方便. 用interface{}/反射做泛型對於Golang這種強型別語言來說,還是有點打臉
執行期
Golang和C++比效能的話, 這是C++的優勢, Golang因為沒虛擬機器, 只有薄薄的一層排程層. 因此效能是非常高的, 用一點效能犧牲換開發效率, 妥妥的
1.6版後的GC優化的已經很好了, 如果你不是高效能,高並發Web應用, 非要找出一堆的優化技巧的話. 只用Golang寫點游戲伺服器, 那點GC損耗可以忽略不計
和其他現代語言一樣, 崩潰捕捉是標配功能, 我用Golang的伺服器線上跑, 基本沒碰到過崩潰情況
熱更新: 官方已經有plugin系統的提交, 跨平台的. 估計很快就可以告別手動cgo做so熱更新
開發, 除錯, 部署, 優化
LiteIDE是我首選尺改卜的Golang的IDE, 雖然有童鞋說B格不高. 但這估計實在是找不到缺點說了, 別跟我說Visual Studio, 那是宇宙級的...
曾經聽說有人不看好Golang, 我問為啥: 說這么新的語言, 不陵穗好招人,後面打聽到他是個策劃... 好吧
真實情況是這樣的: Golang對於有點程式設計基礎的新人來說, 1周左右可以開始貢獻程式碼. 老司機2~3天.
開發效率還是不錯的, 一般大的游戲功能, 2*2人一周3~4個整完. 這換C++時代, 大概也就1~2個還寫不完. 對接伺服器sdk的話, 大概1天接個10多個沒問題
Golang自帶效能調優工具, 從記憶體, CPU, 阻塞點等幾個方面直接出圖進行分析, 非常直觀, 可以參考我部落格幾年前的分析: 使用Golang進行效能分析(Profiling)
Golang支 *** 叉編譯, 跨平台部署, 什麼概念? linux是吧? 不問你什麼版本, 直接windows上編譯輸出一個elf, 甩到伺服器上開跑.不超過1分鍾時間..

1.為什麼golang的開發效率高?
golang是一編譯型的強型別語言,它在開發上的高效率主要來自於後發優勢,不用考慮舊有惡心的歷史,又有一個較高的工程視角。良好的避免了程式設計師因為「 { 需不需要獨佔一行 」這種革命問題打架,也解決了一部分趁編譯時間找產品妹妹搭訕的階級敵人。
它有自己的包管理機制,工具鏈成熟,從開發、除錯到釋出都很簡單方便;
有反向介面、defer、coroutine等大量的syntactic sugar;
編譯速度快,因為是強型別語言又有gc,只要通過編譯,非業務毛病就很少了;
它在語法級別上支援了goroutine,這是大家說到最多的內容,這里重點提一下。首先,coroutine並不稀罕,語言並不能超越硬體、作業系統實現神乎其神的功能。golang可以做到事情,其他語言也可以做到,譬如c++,在boost庫裡面自己就有的coroutine實現(當然用起來跟其他boost庫一樣惡心)。golang做的事情,是把這一套東西的使用過程簡化了,並且提供了一套channel的通訊模式,使得程式設計師可以忽略諸如死鎖等問題。
goroutine的目的是描述並發程式設計模型。並發與並行不同,它並不需要多核的硬體支援,它不是一種物理執行狀態,而是一種程式邏輯流程。它的主要目的不是利用多核提高執行效率,而是提供一種更容易理解、不容易出錯的語言來描述問題。
實際上golang預設就是執行在單OS程序上面的,通過指定環境變數GOMAXPROCS才能轉身跑在多OS程序上面。有人提到了網易的pomelo,開源本來是一件很不錯的事情,但是基於自己對callback hell的偏見,我一直持有這種態度:敢用nodejs寫大規模游戲伺服器的人,都是真正的勇士 : ) 。
2、Erlang與Golang的coroutine有啥區別,coroutine是啥?
coroutine本質上是語言開發者自己實現的、處於user space內的執行緒,無論是erlang、還是golang都是這樣。需要解決沒有時鍾中斷;碰著阻塞式io,整個程序都會被作業系統主動掛起;需要自己擁有排程式控制制能力(放在並行環境下面還是挺麻煩的一件事)等等問題。那為啥要廢老大的勁自己做一套執行緒放user space裡面呢?
並發是伺服器語言必須要解決的問題;
system space的程序還有執行緒排程都太慢了、佔用的空間也太大了。
把執行緒放到user space的可以避免了陷入system call進行上下文切換以及高速緩沖更新,執行緒本身以及切換等操作可以做得非常的輕量。這也就是golang這類語言反復提及的超高並發能力,分分鍾給你開上幾千個執行緒不費力。
不同的是,golang的並發排程在i/o等易發阻塞的時候才會發生,一般是內封在庫函式內;erlang則更誇張,對每個coroutine維持一個計數器,常用語句都會導致這個計數器進行rection,一旦到點,立即切換排程函式。
中斷介入程度的不同,導致erlang看上去擁有了preemptive scheling的能力,而golang則是cooperative shceling的。golang一旦寫出純計算死迴圈,程序內所有會話必死無疑;要有大計算量少io的函式還得自己主動叫runtime.Sched()來進行排程切換。
3、golang的執行效率怎麼樣?
我是相當反感所謂的pingpong式benchmark,執行效率需要放到具體的工作環境下面考慮。
首先,它再快也是快不過c的,畢竟底下做了那麼多工作,又有排程,又有gc什麼的。那為什麼在那些benchmark裡面,golang、nodejs、erlang的響應效率看上去那麼優秀呢,響應快,並發強?並發能力強的原因上面已經提到了,響應快是因為大量非阻塞式io操作出現的原因。這一點c也可以做到,並且能力更強,但是得多寫不少優質程式碼。
然後,針對游戲伺服器這種高實時性的執行環境,GC所造成的跳幀問題確實比較麻煩,前面的大神 @達達 有比較詳細的論述和緩解方案,就不累述了 。隨著golang的持續開發,相信應該會有非常大的改進。一是遮蔽記憶體操作是現代語言的大勢所趨,它肯定是需要被實現的;二是GC演演算法已經相當的成熟,效率勉勉強強過得去;三是可以通過incremental的操作來均攤cpu消耗。
用這一點點效率損失換取一個更高的生產能力是不是值得呢?我覺得是值得的,硬體已經很便宜了,人生苦短,讓自己的生活更輕松一點吧: )。
4、基於以上的論述,我認為採用go進行小范圍的MMORPG開發是可行的。

如果跟C語言比,大部分指令碼都勝出啊。Go, Node.js, Python ......
網易弄過一個Node.js的開源伺服器框架。
至於IDE, 不重要,做伺服器開發很少會要開著IDE除錯的。最常用的手段就是打Log. 設定了斷點也很難調,多個客戶端並發。
那種單客戶端連線進來就可以重現的bug倒是可以用IDE調,但是這種bug本來就容易解決。
用指令碼語言,有一個很大的好處是容易做自動測試,可以更好地保證程式碼質量。
--------------------------
開發效率當然是指令碼高。執行效率,其實更重要的是並發,框架合理的話增加機器就可以直接提高效率增加人數。

用Go開發大型mmorpg服務端不會有問題的,如果掉坑裡肯定不會是語言的問題。
唯一比較可能掉進去的坑就只有GC,其實很容易預防和調整的,具體細節可以看我部落格分享的文章。
但是技術選型不只是選語言,如果當時我手頭有一套效能滿意,開發效率OK,人員補給不會有問題的技術方案,不管是什麼語言的,我肯定不會放棄它而選擇冒險的。

public void actionPerformed(ActionEvent e)
{
if(e.getSource()==xinjian)
{
text.setText("");
}
if(e.getSource()==dakai)
{
openFD.show();
String s;

㈦ 駁狗屎文 "我為什麼放棄Go語言

此篇文章流傳甚廣, 其實裡面沒啥干貨, 而且裡面很多觀點是有問題的. 這個文章在 golang-china 很早就討論過了.
最近因為 Rust 1.0 和 1.1 的發布, 導致這個文章又出來毒害讀者.
所以寫了這篇反駁文章, 指出其中的問題.

有好幾次,當我想起來的時候,總是會問自己:我為什麼要放棄Go語言?這個決定是正確的嗎?是明智和理性的嗎?其實我一直在認真思考這個問題。
開門見山地說,我當初放棄Go語言(golang),就是因為兩個「不爽」:第一,對Go語言本身不爽;第二,對Go語言社區里的某些人不爽。毫無疑問,這是非常主觀的結論。但是我有足夠詳實的客觀的論據,用以支撐這個看似主觀的結論。
文末附有本文更新日誌。
確實是非常主觀的結論, 因為裡面有不少有問題的觀點(用來忽悠Go小白還行).
第0節:我的Go語言經歷
先說說我的經歷吧,以避免被無緣無故地當作Go語言的低級黑。
2009年底,Go語言(golang)第一個公開版本發布,籠罩著「Google公司製造」的光環,吸引了許多慕名而來的嘗鮮者,我(Liigo)也身居其中,籠統的看了一些Go語言的資料,學習了基礎的教程,因對其語法中的分號和花括弧不滿,很快就遺忘掉了,沒拿它當一回事。
在2009年Go剛發布時, 確實是因為「Google公司製造」的光環而吸引了(包括文章作者和諸多IT記者)很多低級的嘗鮮者.
還好, 經過5年的發展, 這些純粹因為光環來的投機者所剩已經不多了(Google趨勢).
目前, 真正的Go用戶早就將Go用於實際的生產了.
說到 其語法中的分號和花括弧不滿, 我想說這只是你的 個人主觀感受, 還有很多人對Go的分號和花括弧很滿意,
包括水果公司的的 Swift 的語言設計者也很滿意這種風格(Swift中的分號和花括弧和Go基本相同).
如果只談 個人主觀感受, 我也可以說 Rust 的 fn 縮寫也很蛋疼!
兩年之後,2011年底,Go語言發布1.0的計劃被提上日程,相關的報道又多起來,我再次關注它,重新評估之後決定深入參與Go語言。我訂閱了其users、nuts、dev、commits等官方郵件組,堅持每天閱讀其中的電子郵件,以及開發者提交的每一次源代碼更新,給Go提交了許多改進意見,甚至包括修改Go語言編譯器源代碼直接參與開發任務。如此持續了數月時間。
這個到是事實, 在 golang-china 有不少吵架的帖子, 感興趣的可以去挖下, 我就不展開說了.
到2012年初,Go 1.0發布,語言和標准庫都已經基本定型,不可能再有大幅改進,我對Go語言未能在1.0定型之前更上一個台階、實現自我突破,甚至帶著諸多明顯缺陷走向1.0,感到非常失望,因而逐漸疏遠了它(所以Go 1.0之後的事情我很少關心)。後來看到即將發布的Go 1.1的Release Note,發現語言層面沒有太大改變,只是在庫和工具層面有所修補和改進,感到它尚在幼年就失去成長的動力,越發失望。外加Go語言社區里的某些人,其中也包括Google公司負責開發Go語言的某些人,其態度、言行,讓我極度厭惡,促使我決絕地離棄Go語言。
真的不清楚樓主說的可以在 Go1.0 之前短時間內能實現的 重大改進和諸多明顯缺陷 是什麼.
如果是樓主說前面的 其語法中的分號和花括弧不滿 之類的重大改進, 我只能說這只是你的 個人主觀感受 而已,
你的很多想法只能說服你自己, 沒辦法說服其他絕大部分人(不要以為像C++或Rust那樣什麼特性都有就NB了, 各種NB特性加到一起只能是 要你命3000, 而絕對不會是什麼 銀彈).
Go 1.1的Release Note,發現語言層面沒有太大改變. 語言層沒有改變是是因為 Go1 作出的向後兼容的承諾. 對於工業級的語言來說, Go1 這個只能是優點. 如果連語言層在每個版本都會出現諸多大幅改進, 那誰還敢用Go語言來做生產開發呢(我承認Rust的改動很大膽, 但也說明了Rust還處於比較幼稚和任性的階段)?
說 Go語言社區里的某些人固執 的觀點我是同意的. 但是這些 固執 的人是可以講道理的, 但是他們對很多東西的要求很高(特別是關於Go的設計哲學部分).
只要你給的建議有依據(語言的設計哲學是另外一回事情), 他們絕對不會盲目的拒絕(只是討論的周期會比較長).
關於樓主提交的給Go文件添加BOM的文章, 需要補充說明下.
在Go1.0發布的時候, Go語言的源文件(.go)明確要求必須是UTF8編碼的, 而且是無BOM的UTF8編碼的.
注意: 這個 無BOM的UTF8編碼 的限制僅僅是 針對 Go語言的源文件(.go).
這個限制並不是說不允許用戶處理帶BOM的UTF8的txt文件!
我覺得對於寫Go程序來說, 這個限制是沒有任何問題的, 到目前為止, 我還從來沒有使用過帶BOM的.go文件.
不僅是因為帶BOM的.go文件沒有太多的意義, 而且有很多的缺陷.
BOM的原意是用來表示編碼是大端還是小端的, 主要用於UTF16和UTF32. 對於 UTF8 來說, BOM 沒有任何存在的意義(正是Go的2個作者發明了UTF8, 徹底解決了全球的編碼問題).
但是, 在現實中, 因為MS的txt記事本, 對於中文環境會將txt(甚至是C/C++源文件)當作GBK編碼(GBK是個爛編碼),
為了區別到底是GBK還是UTF8, MS的記事本在前面加了BOM這個垃圾(被GBK佔了茅坑), 這里的bom已經不是表示位元組序本意了. 不知道有沒有人用ms的記事本寫網頁, 然後生成一個帶bom的utf8網頁肯定很有意思.
這是MS的記事本的BUG: 它不支持生成無BOM的UTF8編碼的文本文件!
這些是現實存在的帶BOM的UTF8編碼的文本文件, 但是它們肯定都不是Go語言源文件!
所以說, Go語言的源文件即使強制限制了無BOM的UTF8編碼要求, 也是沒有任何問題的(而且我還希望有這個限制).
雖然後來Go源文件接受帶BOM的UTF8了, 但是運行 go fmt 之後, 還是會刪除掉BOM的(因為BOM就是然並卵). 也就是說 帶 BOM 的 Go 源文件是不符合 Go語言的編碼風格的, go fmt 會強制刪除 BOM 頭.
前面說了BOM是MS帶來的垃圾, 但是BOM的UTF8除瞭然並卵之外還有很多問題, 因為BOM在string的開頭嵌入了垃圾,
導致正則表達式, string的鏈接運算等操作都被會被BOM這個垃圾所污染. 對於.go語言, 即使代碼完全一樣, 有BOM和無BOM會導致文件的MD5之類的校驗碼不同.
所以, 我覺得Go用戶不用糾結BOM這個無關緊要的東西.
在上一個10年,我(Liigo)在我所屬的公司里,深度參與了兩個編程語言項目的開發。我想,對於如何判斷某個編程語言的優劣,或者說至少對於如何判斷某個編程語言是否適合於我自己,我應該還是有一點發言權的。
第1節:我為什麼對Go語言不爽?
Go語言有很多讓我不爽之處,這里列出我現在還能記起的其中一部分,排名基本上不分先後。讀者們耐心地看完之後,還能淡定地說一句「我不在乎」嗎?
1.1 不允許左花括弧另起一行
關於對花括弧的擺放,在C語言、C++、Java、C#等社區中,十餘年來存在持續爭議,從未形成一致意見。在我看來,這本來就是主觀傾向很重的抉擇,不違反原則不涉及是非的情況下,不應該搞一刀切,讓程序員或團隊自己選擇就足夠了。編程語言本身強行限制,把自己的喜好強加給別人,得不償失。無論傾向於其中任意一種,必然得罪與其對立的一群人。雖然我現在已經習慣了把左花括弧放在行尾,但一想到被禁止其他選擇,就感到十分不爽。Go語言這這個問題上,沒有做到「團結一切可以團結的力量」不說,還有意給自己樹敵,太失敗了。
我覺得Go最偉大的發明是 go fmt, 從此Go用戶不會再有花括弧的位置這種無聊爭論了(當然也少了不少灌水和上tiobe排名的機會).
是這優點, Swift 語言也使用和 Go 類似的風格(當然樓主也可能鄙視swift的作者).
1.2 編譯器莫名其妙地給行尾加上分號
對Go語言本身而言,行尾的分號是可以省略的。但是在其編譯器(gc)的實現中,為了方便編譯器開發者,卻在詞法分析階段強行添加了行尾的分號,反過來又影響到語言規范,對「怎樣添加分號」做出特殊規定。這種變態做法前無古人。在左花括弧被意外放到下一行行首的情況下,它自動在上一行行尾添加的分號,會導致莫名其妙的編譯錯誤(Go 1.0之前),連它自己都解釋不明白。如果實在處理不好分號,乾脆不要省略分號得了;或者,Scala和JavaScript的編譯器是開源的,跟它們學學怎麼處理省略行尾分號可以嗎?
又是樓主的 個人主觀感受, 不過我很喜歡這個特性. Swift 語言也是類似.
1.3 極度強調編譯速度,不惜放棄本應提供的功能
程序員是人不是神,編碼過程中免不了因為大意或疏忽犯一些錯。其中有一些,是大家集體性的很容易就中招的錯誤(Go語言里的例子我暫時想不起來,C++里的例子有「基類析構函數不是虛函數」)。這時候編譯器應該站出來,多做一些檢查、約束、核對性工作,盡量阻止常規錯誤的發生,盡量不讓有潛在錯誤的代碼編譯通過,必要時給出一些警告或提示,讓程序員留意。編譯器不就是機器么,不就是應該多做臟活累活雜活、減少人的心智負擔么?編譯器多做一項檢查,可能會避免數十萬程序員今後多年內無數次犯同樣的錯誤,節省的時間不計其數,這是功德無量的好事。但是Go編譯器的作者們可不這么想,他們不願意自己多花幾個小時給編譯器增加新功能,覺得那是虧本,反而減慢了編譯速度。他們以影響編譯速度為由,拒絕了很多對編譯器改進的要求。典型的因噎廢食。強調編譯速度固然值得贊賞,但如果因此放棄應有的功能,我不贊成。
編譯速度是很重要的, 如果編譯速度夠慢, 語言再好也不會有人使用的.
比如C/C++的增量編譯/預編譯頭文件/並發編譯都是為了提高編譯速度.
Rust1.1 也號稱 比 1.0 的編譯時間減少了32% (注意: 不是運行速度).
當然, Go剛面世的時候, 編譯速度是其中的一個設計目標.
不過我想樓主, 可能想說的是因為編譯器自己添加分號而導致的編譯錯誤的問題.
我覺得Go中 { 不能另起一行是語言特性, 如果修復這個就是引入了新的錯誤.
其他的我真想不起來還有哪些 調編譯速度,不惜放棄本應提供的功能 (不要提泛型, 那是因為還沒有好的設計).
1.4 錯誤處理機制太原始
在Go語言中處理錯誤的基本模式是:函數通常返回多個值,其中最後一個值是error類型,用於表示錯誤類型極其描述;調用者每次調用完一個函數,都需要檢查這個error並進行相應的錯誤處理:if err != nil { /*這種代碼寫多了不想吐么*/ }。此模式跟C語言那種很原始的錯誤處理相比如出一轍,並無實質性改進。實際應用中很容易形成多層嵌套的if else語句,可以想一想這個編碼場景:先判斷文件是否存在,如果存在則打開文件,如果打開成功則讀取文件,如果讀取成功再寫入一段數據,最後關閉文件,別忘了還要處理每一步驟中出現錯誤的情況,這代碼寫出來得有多變態、多醜陋?實踐中普遍的做法是,判斷操作出錯後提前return,以避免多層花括弧嵌套,但這么做的後果是,許多錯誤處理代碼被放在前面突出的位置,常規的處理邏輯反而被掩埋到後面去了,代碼可讀性極差。而且,error對象的標准介面只能返回一個錯誤文本,有時候調用者為了區分不同的錯誤類型,甚至需要解析該文本。除此之外,你只能手工強制轉換error類型到特定子類型(靜態類型的優勢沒了)。至於panic - recover機制,致命的缺陷是不能跨越庫的邊界使用,註定是一個半成品,最多隻能在自己的pkg裡面玩一玩。Java的異常處理雖然也有自身的問題(比如Checked Exceptions),但總體上還是比Go的錯誤處理高明很多。
話說, 軟體開發都發展了半個世紀, 還是無實質性改進. 不要以為弄一個異常的語法糖就是革命了.
我只能說錯誤和異常是2個不同的東西, 將所有錯誤當作異常那是SB行為.
正因為有異常這個所謂的銀彈, 導致很多等著別人幫忙擦屁股的行為(注意 shit 函數拋出的絕對不會是一種類型的 shit, 而被其間接調用的各種 xxx_shit 也可能拋出各種類型的異常, 這就導致 catch 失控了):
int main() {
try {
shit();
} catch( /* 到底有幾千種 shit ? */) {
...
}
}

Go的建議是 panic - recover 不跨越邊界, 也就是要求正常的錯誤要由pkg的處理掉.
這是負責任的行為.
再說Go是面向並發的編程語言, 在海量的 goroutine 中使用 try/catch 是不是有一種不倫不類的感覺呢?
1.5 垃圾回收器(GC)不完善、有重大缺陷
在Go 1.0前夕,其垃圾回收器在32位環境下有內存泄漏,一直拖著不肯改進,這且不說。Go語言垃圾回收器真正致命的缺陷是,會導致整個進程不可預知的間歇性停頓。像某些大型後台服務程序,如游戲伺服器、APP容器等,由於佔用內存巨大,其內存對象數量極多,GC完成一次回收周期,可能需要數秒甚至更長時間,這段時間內,整個服務進程是阻塞的、停頓的,在外界看來就是服務中斷、無響應,再牛逼的並發機制到了這里統統失效。垃圾回收器定期啟動,每次啟動就導致短暫的服務中斷,這樣下去,還有人敢用嗎?這可是後台伺服器進程,是Go語言的重點應用領域。以上現象可不是我假設出來的,而是事實存在的現實問題,受其嚴重困擾的也不是一家兩家了(2013年底ECUG Con 2013,京東的劉奇提到了Go語言的GC、defer、標准庫實現是性能殺手,最大的痛苦是GC;美團的沈鋒也提到Go語言的GC導致後台服務間隔性停頓是最大的問題。更早的網路游戲仙俠道開發團隊也曾受Go垃圾回收的沉重打擊)。在實踐中,你必須努力減少進程中的對象數量,以便把GC導致的間歇性停頓控制在可接受范圍內。除此之外你別無選擇(難道你還想自己更換GC演算法、甚至砍掉GC?那還是Go語言嗎?)。跳出圈外,我近期一直在思考,一定需要垃圾回收器嗎?沒有垃圾回收器就一定是歷史的倒退嗎?(可能會新寫一篇博客文章專題探討。)
這是說的是32位系統, 這絕對不是Go語言的重點應用領域!! 我可以說Go出生就是面向64位系統和多核心CPU環境設計的. (再說 Rust 目前好像還不支持 XP 吧, 這可不可以算是影響巨大?)
32位當時是有問題, 但是對實際生產影響並不大(請問樓主還是在用32位系統嗎, 還只安裝4GB的內存嗎). 如果是8位單片機環境, 建議就不要用Go語言了, 直接C語言好了.
而且這個問題早就不存在了(大家可以去看Go的發布日誌).
Go的出生也就5年時間, GC的完善和改進是一個持續的工作, 2015年8月將發布的 Go1.5將採用並行GC.
關於GC的被人詬病的地方是會導致卡頓, 但是我以為這個主要是因為GC的實現還不夠完美而導致的.
如果是完美的並發和增量的GC, 那應該不會出現大的卡頓問題的.
當然, 如果非要實時性, 那用C好了(實時並不表示性能高, 只是響應時間可控).
對於Rust之類沒有GC的語言來說, 想很方便的開發並發的後台程序那幾乎是不可能的.
不要總是吹Rust能代替底層/中層/上層的開發, 我們要看有誰用Rust真的做了什麼.
1.6 禁止未使用變數和多餘import
Go編譯器不允許存在被未被使用的變數和多餘的import,如果存在,必然導致編譯錯誤。但是現實情況是,在代碼編寫、重構、調試過程中,例如,臨時性的注釋掉一行代碼,很容易就會導致同時出現未使用的變數和多餘的import,直接編譯錯誤了,你必須相應的把變數定義注釋掉,再翻頁回到文件首部把多餘的import也注釋掉,……等事情辦完了,想把剛才注釋的代碼找回來,又要好幾個麻煩的步驟。還有一個讓人蛋疼的問題,編寫資料庫相關的代碼時,如果你import某資料庫驅動的pkg,它編譯給你報錯,說不需要import這個未被使用的pkg;但如果你聽信編譯器的話刪掉該import,編譯是通過了,運行時必然報錯,說找不到資料庫驅動;你看看程序員被折騰的兩邊不是人,最後不得不請出大神:import _。對待這種問題,一個比較好的解決方案是,視其為編譯警告而非編譯錯誤。但是Go語言開發者很固執,不容許這種折中方案。
這個問題我只能說樓主的吐槽真的是沒水平.
為何不使用的是錯誤而不是警告? 這是為了將低級的bug消滅在編譯階段(大家可以想下C/C++的那麼多警告有什麼卵用).
而且, import 即使沒有使用的話, 也是用副作用的, 因為 import 會導致 init 和全局變數的初始化.
如果某些代碼沒有使用, 為何要執行 init 這些初始化呢?
如果是因為調試而添加的變數, 那麼調試完刪除不是很正常的要求嗎?
如果是因為調試而要導入fmt或log之類的包, 刪除調試代碼後又導致 import 錯誤的花,
樓主難道不知道在一個獨立的文件包裝下類似的輔助調試的函數嗎?
import (
"fmt"
"log"
)

func logf(format string, a ...interface{}) {
file, line := callerFileLine()
fmt.Fprintf(os.Stderr, "%s:%d: ", file, line)
fmt.Fprintf(os.Stderr, format, a...)
}

func fatalf(format string, a ...interface{}) {
file, line := callerFileLine()
fmt.Fprintf(os.Stderr, "%s:%d: ", file, line)
fmt.Fprintf(os.Stderr, format, a...)
os.Exit(1)
}

import _ 是有明確行為的用法, 就是為了執行包中的 init 等函數(可以做某些注冊操作).
將警告當作錯誤是Go的一個哲學, 當然在樓主看來這是白痴做法.
1.7 創建對象的方式太多令人糾結
創建對象的方式,調用new函數、調用make函數、調用New方法、使用花括弧語法直接初始化結構體,你選哪一種?不好選擇,因為沒有一個固定的模式。從實踐中看,如果要創建一個語言內置類型(如channel、map)的對象,通常用make函數創建;如果要創建標准庫或第三方庫定義的類型的對象,首先要去文檔里找一下有沒有New方法,如果有就最好調用New方法創建對象,如果沒有New方法,則退而求其次,用初始化結構體的方式創建其對象。這個過程頗為周折,不像C++、Java、C#那樣直接new就行了。
C++的new是狗屎. new導致的問題是構造函數和普通函數的行為不一致, 這個補丁特性真的沒啥優越的.
我還是喜歡C語言的 fopen 和 malloc 之類構造函數, 構造函數就是普通函數, Go語言中也是這樣.
C++中, 除了構造不兼容普通函數, 析構函數也是不兼容普通函數. 這個而引入的坑有很多吧.
1.8 對象沒有構造函數和析構函數
沒有構造函數還好說,畢竟還有自定義的New方法,大致也算是構造函數了。沒有析構函數就比較難受了,沒法實現RAII。額外的人工處理資源清理工作,無疑加重了程序員的心智負擔。沒人性啊,還嫌我們程序員加班還少嗎?C++里有析構函數,Java里雖然沒有析構函數但是有人家finally語句啊,Go呢,什麼都沒有。沒錯,你有個defer,可是那個defer問題更大,詳見下文吧。
defer 可以覆蓋析構函數的行為, 當然 defer 還有其他的任務. Swift2.0 也引入了一個簡化版的 defer 特性.
1.9 defer語句的語義設定不甚合理
Go語言設計defer語句的出發點是好的,把釋放資源的「代碼」放在靠近創建資源的地方,但把釋放資源的「動作」推遲(defer)到函數返回前執行。遺憾的是其執行時機的設置似乎有些不甚合理。設想有一個需要長期運行的函數,其中有無限循環語句,在循環體內不斷的創建資源(或分配內存),並用defer語句確保釋放。由於函數一直運行沒有返回,所有defer語句都得不到執行,循環過程中創建的大量短暫性資源一直積累著,得不到回收。而且,系統為了存儲defer列表還要額外佔用資源,也是持續增加的。這樣下去,過不了多久,整個系統就要因為資源耗盡而崩潰。像這類長期運行的函數,http.ListenAndServe()就是典型的例子。在Go語言重點應用領域,可以說幾乎每一個後台服務程序都必然有這么一類函數,往往還都是程序的核心部分。如果程序員不小心在這些函數中使用了defer語句,可以說後患無窮。如果語言設計者把defer的語義設定為在所屬代碼塊結束時(而非函數返回時)執行,是不是更好一點呢?可是Go 1.0早已發布定型,為了保持向後兼容性,已經不可能改變了。小心使用defer語句!一不小心就中招。
前面說到 defer 還有其他的任務, 也就是 defer 中執行的 recover 可以捕獲 panic 拋出的異常.
還有 defer 可以在 return 之後修改命名的返回值.
上面2個工作要求 defer 只能在函數退出時來執行.
樓主說的 defer 是類似 Swift2.0 中 defer 的行為, 但是 Swift2.0 中 defer 是沒有前面2個特性的.
Go中的defer是以函數作用域作為觸發的條件的, 是會導致樓主說的在 for 中執行的錯誤用法(哪個語言沒有坑呢?).
不過 for 中 局部 defer 也是有辦法的 (Go中的defer是以函數作用域):
for {
func(){
f, err := os.Open(...)
defer f.Close()
}()
}

在 for 中做一個閉包函數就可以了. 自己不會用不要怪別人沒告訴你.
1.10 許多語言內置設施不支持用戶定義的類型
for in、make、range、channel、map等都僅支持語言內置類型,不支持用戶定義的類型(?)。用戶定義的類型沒法支持for in循環,用戶不能編寫像make、range那樣「參數類型和個數」甚至「返回值類型和個數」都可變的函數,不能編寫像channel、map那樣類似泛型的數據類型。語言內置的那些東西,處處充斥著斧鑿的痕跡。這體現了語言設計的局限性、封閉性、不完善,可擴展性差,像是新手作品——且不論其設計者和實現者如何權威。延伸閱讀:Go語言是30年前的陳舊設計思想,用戶定義的東西幾乎都是二等公民(Tikhon Jelvis)。
說到底, 這個是因為對泛型支持的不完備導致的.
Go語言是沒啥NB的特性, 但是Go的特性和工具組合在一起就是好用.
這就是Go語言NB的地方.
1.11 沒有泛型支持,常見數據類型介面醜陋
沒有泛型的話,List、Set、Tree這些常見的基礎性數據類型的介面就只能很醜陋:放進去的對象是一個具體的類型,取出來之後成了無類型的interface{}(可以視為所有類型的基礎類型),還得強制類型轉換之後才能繼續使用,令人無語。Go語言缺少min、max這類函數,求數值絕對值的函數abs只接收/返回雙精度小數類型,排序介面只能藉助sort.Interface無奈的迴避了被比較對象的類型,等等等等,都是沒有泛型導致的結果。沒有泛型,介面很難優雅起來。Go開發者沒有明確拒絕泛型,只是說還沒有找到很好的方法實現泛型(能不能學學已經開源的語言呀)。現實是,Go 1.0已經定型,泛型還沒有,那些醜陋的介面為了保持向後兼容必須長期存在著。
Go有自己的哲學, 如果能有和目前哲學不沖突的泛型實現, 他們是不會反對的.
如果只是簡單學學(或者叫抄襲)已經開源的語言的語法, 那是C++的設計風格(或者說C++從來都是這樣設計的, 有什麼特性就抄什麼), 導致了各種腦裂的編程風格.
編譯時泛型和運行時泛型可能是無法完全兼容的, 看這個例子:
type Adder<T> interface {
Add(a, b T) T
}

熱點內容
實現秘聞存儲的方法 發布:2025-02-08 10:23:33 瀏覽:168
怎麼在微信發文件夾 發布:2025-02-08 10:09:45 瀏覽:795
cryengine源碼 發布:2025-02-08 09:50:58 瀏覽:394
aardio可以反編譯嗎 發布:2025-02-08 09:50:53 瀏覽:484
公司營業執照密碼是什麼 發布:2025-02-08 09:47:56 瀏覽:855
體驗腳本 發布:2025-02-08 09:46:15 瀏覽:691
醫學生需要什麼配置的筆記本 發布:2025-02-08 09:45:34 瀏覽:772
騷擾電話資料庫 發布:2025-02-08 09:45:34 瀏覽:180
u盤文件加密器 發布:2025-02-08 09:40:35 瀏覽:770
plc數據存儲app 發布:2025-02-08 09:37:17 瀏覽:709