# Go 語言 ![image](https://hackmd.io/_uploads/ByghKV770.png) ## 介紹Golang henry ### 設計Golang的原因 * 大量的C++程式碼,同使引入Java及Python * 大量工程師(每個人風格都不同) * 數百萬的程式碼(如何減少程式碼產量) * 分散式編譯系統(交叉編譯速度) * 數百萬的伺服器(部署時間) ### 特性 * 沒有物件導向(繼承特性) * 強制類型 * Function和Method * 沒有錯誤處理 * 用字首來區別可否存取 * 不用的Import或變數會引起編譯錯誤 * 完整的標準函式 * 支援UTF-8格式 * 跨平台支援 ## GO 前端 go在1.11版本中,加入了對WebAssembly 的體驗支持 ```javascript package main import ( "syscall/js" ) btn := js.Global().Get("document").Call("getElementById", "test") btn.Set("innerHTML", "changed by go") ``` 在html引入go的js包 ```javascript <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button id="test"></button> </body> <script src="./wasm_exec.js"></script> <script> const go = new Go() WebAssembly.instantiateStreaming(fetch('app.wasm'), go.importObject) .then(result => go.run(result.instance)) </script> </html> ``` 測試 先將go的程式碼,編譯成WebAssembly,然後我們還需要用到go提供給我們的一個js函式庫,這個是用來在js中,呼叫go編譯產生的WebAssembly,然後執行裡面的程式碼邏輯用的 找到main.go ![image](https://hackmd.io/_uploads/ryA1s4m7A.png) 執行指令編譯 ```javascript GOOS=js GOARCH=wasm go build -o main.wasm main.go // GOARCH表示系統架構,例如可以指定為amd64或386等。在這裡,也可以指定為wasm ``` ![image](https://hackmd.io/_uploads/H1jz24X7A.png) ## Go 缺點 ### 錯誤處理過於簡單 沒有try...catch...finally,因此當方法中遇到錯誤的時候,會立刻停下當前的任務,返回錯誤。 ### 不支援Class類別 不支援繼承 不支援多型 ### GUI Library不好用 由於Go的開發模型在事件處理機制上與大部分GUI框架有較大差異,導致開發GUI變得比較困難。 ### 缺少穩定且功能強大的Web框架 ## Go 的應用 GO 目前主要應用在 1. 網路程式設計:Go 語言的標準庫提供了強大的網路程式設計支援,包括 HTTP 服務器和客戶端,JSON/XML 處理,Websockets 等。許多現代的網路應用,如微服務,都可以使用 Go 語言來開發。 2. 雲端服務:Go 語言被廣泛用於雲端服務的開發。例如,Google 的 Kubernetes,一個開源的容器編排平台,就是用 Go 語言寫的。Docker,一個開源的應用容器引擎,也是用 Go 語言開發的。 3. CLI:由於 Go 語言編譯出的執行檔是靜態的,不需要任何外部依賴,所以它非常適合用來開發命令行工具。例如,Google 的 gcloud CLI,就是用 Go 語言寫的。 4. 數據處理:Go 語言的並行處理能力使其非常適合用於數據處理和分析。例如,InfluxDB,一個開源的時序數據庫,就是用 Go 語言開發的。 5. 遊戲服務器:Go 語言的高效能和易於擴展的特性使其成為開發遊戲服務器的一個好選擇。例如,Agones,一個開源的遊戲服務器平台,就是用 Go 語言開發的。 許多知名的工具或服務都使用 Go 開發,如 Docker、Drone、Kubernetes 、Prometheus、etcd、InfluxDB。 Uber Twitch DropBox 等服務也是以 Go 開發 ## Go 語法 用 var 來定義變數,跟其他語言不大箱同的是,Go 必須將型態宣告寫在後面。 如果要同時宣告不同的變數,也可以用小括弧把變數括起來,但是一定要換行。 ```javascript var a // 不定型別的變數 var a int // 宣告成 int var a int = 10 // 初始化同時宣告 var a, b int // a 跟 b 都是 intvar a, b = 0, "" var a int , b string a := 0 a, b, c := 0, true, "tacolin" // 這樣就可以不同型別寫在同一行 var( a bool = false // 記得要不同行,不然會錯 b int c = "hello" ) ``` 短宣告 在函數中,「:=」 簡潔賦值語句在明確類型的地方,可以替代 var 定義。 Go 只有一種迴圈 --「 for 」 。 基本的「 for 」迴圈除了沒有了 「 () 」 之外(甚至強制不能使用它們),它看起來跟 C 或者 Java 中做的一樣,而 「 {} 」 是必須的。 ```javascript package main import "fmt" func main() { sum := 1 for ; sum < 1000; { sum += sum } fmt.Println(sum) } ``` if if 語句除了沒有了「 () 」 之外(甚至強制不能使用它們),看起來跟 C 或者 Java 中的一樣,而 「 {} 」 是必須的。 ```javascript package main import "fmt" func main() { /* 局部变量定义 */ var a int = 100; /* 判断布尔表达式 */ if a < 20 { /* 如果条件为 true 则执行以下语句 */ fmt.Printf("a 小于 20\n" ); } else { /* 如果条件为 false 则执行以下语句 */ fmt.Printf("a 不小于 20\n" ); } fmt.Printf("a 的值为 : %d\n", a); } ``` boolen Go 語言中的布林與其他語言一致,關鍵字一樣是 bool ,可欲賦予值為 true 和 false。 ```javascript package main import "fmt" func main() { var a bool a = true fmt.Println("a =", a) b := false fmt.Println("b =", b) fmt.Println(true && true) fmt.Println(true && false) fmt.Println(true || true) fmt.Println(true || false) fmt.Println(!true) } ``` ## GO VS JAVA #### 語言設計理念 ##### Java: * 物件導向(OOP):Java以面向對象編程為核心,強調類和繼承。 * 平台無關性:通過Java虛擬機(JVM)實現“一次編寫,處處運行”。 * 廣泛的標準庫和框架:Java擁有豐富的標準庫和第三方框架,如Spring、Hibernate等。 * 垃圾回收:Java內置自動垃圾回收機制,管理內存。 ##### Go: * 簡單且高效:Go語言設計簡潔,編譯快速,語法簡單直觀。 * 並發編程:內置強大的並發處理能力,通過goroutines和channels簡化並發編程。 * 靜態型別但有動態特性:強類型語言,但支持類型推斷和接口。 * 輕量級和跨平台:編譯後生成單一可執行文件,方便部署。 #### 語法與特性 ##### Java: * 複雜的類結構和設計模式:Java需要定義類、接口和繼承關係。 * 豐富的語法特性:支持泛型、注解、lambda表達式等。 * 錯誤處理:使用異常處理機制(try-catch-finally)。 ##### Go: * 簡單的語法結構:沒有類和繼承的概念,主要使用結構體和接口。 * 原生並發支持:通過goroutines和channels實現高效並發處理。 * 錯誤處理:通過返回值進行錯誤處理,沒有異常機制。 #### 性能與效率 ##### Java: * 內存管理:JVM負責內存管理和垃圾回收。 * 編譯和運行:源代碼編譯成字節碼,在JVM上運行,通過JIT(即時編譯器)優化性能。 * 啟動時間較慢:JVM啟動較慢,但在長期運行的應用中性能穩定。 ##### Go: * 內存管理:Go語言自帶垃圾回收,但更高效。 * 編譯和運行:直接編譯成機器碼,生成單一可執行文件,啟動快。 * 高效並發:通過輕量級的goroutines和高效的調度器實現高並發。 #### 開發與部署 ##### Java: * 依賴管理:使用Maven、Gradle等工具管理依賴。 * 開發工具:強大的IDE支持,如IntelliJ IDEA、Eclipse等。 * 部署:通過WAR/JAR包部署在各種伺服器上,如Tomcat、JBoss等。 ##### Go: * 依賴管理:使用go modules管理依賴。 * 開發工具:輕量級編輯器和IDE,如VS Code、GoLand等。 * 部署:生成單一可執行文件,部署簡單,不依賴運行時環境。 #### 生態系統與應用場景 ##### Java: * 企業應用:廣泛應用於企業級應用、金融系統、電商平台等。 * 大數據與分布式系統:在Hadoop生態系統、Apache Kafka等中廣泛使用。 * Android開發:Java是Android應用開發的主要語言。 ##### Go: * 微服務和容器化:適合構建高效能、輕量級的微服務架構,與Docker和Kubernetes結合緊密。 * 網絡服務和工具:在網絡服務、DevOps工具(如Terraform、Prometheus)中廣泛應用。 * 高效工具和CLI:適合開發高效的命令行工具和系統工具。 #### 社群活躍度 ##### JAVA Java已經存在了很長時間,幾乎所有的web開發、後台開發、Android開發都在使用它,成千上萬的人活躍在Java社區並提供大量的開源支持,對於後台開發有著一套完整的解決方案,比如,spring體系可以構建出一套高性能且穩定的服務。 ##### GO 而Golang算是個新項目,雖然社區一樣很活躍,但依然彌補不了它資源匱乏的事實,雖然對於後台開發也有整套的方案,但它還遠不足以匹敵Java。 ## Goroutine https://vocus.cc/article/64ff0f16fd8978000191a081 Goroutine 是 Go 語言中的一種輕量級執行緒,只需要創建一個函數,然後使用go關鍵字在要使用goroutine的函數前面就完成了。 Goroutine 的特性與限制 #### 特性 * 資源消耗極低:Goroutine 的創建相對輕量,主要消耗少量stack空間。這意味著你可以創建大量的 goroutine 而不必擔心資源耗盡的問題。 * 有效的線程管理:當一個 goroutine 被阻塞時,相應的管理線程將被擱置,但運行時會將其他 goroutine 分配給這個線程,使其繼續執行其他工作。這種機制確保了線程的高效使用,避免了資源浪費。 * 最大線程數限制:你可以透過設定 $GOMAXPROCS 來限制系統中的線程數量,確保它們不會無節制地增加。這有助於避免系統資源的過度消耗。 #### 限制 * Goroutine 數量限制:理論上,Go 語言可以創建極多的 Goroutine,但實際上,系統的可用資源(記憶體和 CPU)是有限的。因此,你需要謹慎控制 Goroutine 的數量,以避免過多的併發造成資源耗盡或性能下降。 * 競爭條件和死鎖:Goroutine 的併發操作需要謹慎處理共享資源,否則可能出現競爭條件(race condition)和死鎖(deadlock)。這不是直接的限制,但是在 Goroutine 的設計和使用中需要特別注意,以確保程式的正確性。