Alan's BLOG
  • archives
  • posts
  • tags
  • about
  • quote
  • search
Home

Posts

探索Goroutine:Go語言的併發魔法

👨‍💻簡介 在日常生活中,如果能同時做很多事情,效率肯定大大提升,那麼在Go語言中,該如何做到呢,答案就是今天的主角Goroutine了,在Go語言中,讓併發變得簡單的強大工具,今天就是來給他一個快速介紹。 什麼是Goroutine? 首先,讓我們以一個簡單的方式來解釋什麼是Goroutine。Goroutine是Go語言的一個特別的功能,它就像是小型的工作任務,可以讓我們同時處理很多事情,而不需要浪費太多電腦資源。可以把它想像成比傳統方式更聰明的方式來處理多項工作,而不會讓電腦變得超級忙碌。這種功能讓Go語言在處理大量同時執行的工作時變得非常強大。 如何創建和啟動Goroutine 要使用Goroutine很簡單,只需要創建一個函數,然後使用go關鍵字在要使用goroutine的函數前面就完成了。可以看以下範例: package main import ( "fmt" ) func main() { go sayHello() // 主程式不會等待Goroutine完成 } func sayHello() { fmt.Println("Hello, Goroutine!") } 在這個例子中,我們使用go關鍵字啟動一個新的Goroutine,Goroutine執行了sayHello函數。但須注意,主程式main不會等待Goroutine完成,所以可能不會看到有印出任何東西來。 可以稍微讓main主程式睡一下,就可以看到輸出了 package main import ( "fmt" "time" ) func main() { go sayHello() time.Sleep(1) } func sayHello() { fmt.Println("Hello, Goroutine!") } Goroutine的執行過程 下面提供了一個簡單的小程式,在主程式裡有兩個goroutine,試著執行一下程式可以發現輸出是一段一段的,會是0跟1交錯印出,代表兩邊的goroutine會搶著印出,呈現競爭狀態 package main import ( "fmt" "time" ) func main() { go print1() go print2() time.Sleep(time.Second) } func print1() { for i := 0; i < 100; i++ { fmt....

2023-09-11 · 2 min · 279 words · Alan

淺談Go中的Pointer和記憶體管理

👨‍💻簡介 當我們在宣告變數時,電腦會為該變數在記憶體中分配一個位置,然後將這個變數值儲存在這個位置上,需要讀取或修改這個變數值時,電腦是透過記憶體位置來存取這個值。 今天來簡單介紹一下go的Pointer,他的特性以及常見用法。 什麼是Pointer? Pointer是一種資料類型,用來儲存變數的記憶體地址。在Go中,我們可以通過使用 * 符號來宣告和操作Pointer。這允許我們直接訪問和修改變數的內容,而不僅僅是讀取或複製它們的值。 Pointer的特性、限制與常見用法 特性 Pointer的值和地址 每個變數都有一個記憶體地址,我們可以使用Pointer變數來儲存這個地址。讓我們看一個範例: package main import "fmt" func main() { x := 42 var p *int // 宣告一個整數Pointer p = &x // 將p指向x的地址 fmt.Println("x =", x) fmt.Println("p =", p) } 在這個例子中,我們創建了一個整數變數 x,並宣告了一個整數Pointer p,然後將 p 設為 x 的地址。現在,p 裡面存放的就是 x 的地址。 Pointer的初始化 Go中的Pointer可以通過 new 函數來初始化,這將為指定的類型分配記憶體並返回其地址。範例: package main import "fmt" func main() { var p *int p = new(int) // 初始化一個整數Pointer *p = 123 // 將Pointer所指向的記憶體設置為123 fmt....

2023-09-08 · 2 min · 403 words · Alan

錯誤處理的精髓:快速了解Go語言的 error、panic和recover

👨‍💻簡介 在軟體開發中,錯誤無所不在。無論是網路請求失敗、檔案不存在,還是數學計算錯誤,處理錯誤是任何開發者的日常工作,系統的穩定度基本取決於對於錯誤處理是否全面,好的錯誤處理也可以產生適當的錯誤訊息,讓 Debug 更加容易。在Go語言中,有一些獨特的功能在處理錯誤和資源管理方面非常有用。,其中包括error、panic和recover。今天就來介紹這三個關鍵字與錯誤處理的簡單用法。 Error 什麼是Error? 在Go中,Error是一個擁有error interface的類型,可以看到他只有一個方法,該方法主要用來描述一個錯誤的字串。 type error interface { Error() string } 如何產生錯誤訊息 errors.New() 使用方式很簡單,在裡面放入要顯示的錯誤訊息 package main import ( "errors" "fmt" ) func main() { err := errors.New("This is a custom error message") fmt.Println(err.Error()) // output:This is a custom error message } fmt.Errorf() 主要用在格式化錯誤訊息的情況下 package main import ( "fmt" ) func main() { name := "John" err := fmt.Errorf("Hello, %s! This is a custom error message", name) fmt....

2023-09-07 · 3 min · 559 words · Alan

Go語言的defer:確保後置操作的執行

👨‍💻簡介 當我們在寫程式時,有時候會需要在程式結束時關閉某些資源,而defer這個關鍵字,可以讓你輕鬆的實現,下面來簡單介紹一下defer以及常用的範例。,它為程式設計師提供了一種簡單而強大的工具,用於管理資源和確保程式的正確執行。在本篇文章中,我們將深入探討Go語言中的defer,並提供一些實際的程式碼範例,以幫助你理解它的工作原理以及如何運用它來提高程式的可讀性和可維護性。 什麼是defer? defer是一個關鍵字,用來延遲函數的執行,直到包含它的函數執行完畢。這代表你可以在函數中的任何位置使用defer來安排某個操作,並確保它將在函數返回之前執行。defer通常用於執行一些清理或資源回收的操作。 package main import "fmt" func main() { defer fmt.Println("World") fmt.Print("Hello, ") } 使用方式也很簡單,在要執行的函數前面加上defer就完成了,所以上面的範例會印出 Hello World Defer的特性 延遲執行:defer 語句允許你安排一段程式碼,使它在包含它的函數返回之前執行,無論函數是否正常返回或出現錯誤。 堆疊特性:多個 defer 語句按照後進先出(LIFO)的順序執行,這意味著最後一個被延遲的語句會最先執行。 package main import "fmt" func main() { fmt.Println("Start") defer fmt.Println("Deferred 1") defer fmt.Println("Deferred 2") fmt.Println("End") } 根據defer特性的後進先出,輸出會是下面這個樣子 Start End Deferred 2 Deferred 1 Defer的限制 延遲的函數必須是無參數函數:你只能延遲無參數的函數調用,因為 defer 不允許傳遞參數。 順序性:defer 語句的效果在函數內是有限定範圍的,它只在包含它的函數範圍內有效,無法跨函數使用。 常見用法 資源清理 最常見的用途之一是在函數返回前關閉文件、釋放鎖、關閉資料庫連接等,以確保資源被正確釋放。 func readFile(filename string) (string, error) { file, err := os.Open(filename) if err != nil { return "", err } defer file....

2023-09-06 · 1 min · 135 words · Alan

保證型別安全:使用Go的Type Assertions避免型別錯誤

👨‍💻簡介 在Go中,假如我要判斷一個資料類型是甚麼,該怎麼做呢? Golang有一個功能叫做Type Assertions(類型斷言),它的作用就是能夠在運行時檢查我的資料類型,讓我在傳遞類型時能確保資料類型是正確的。 Type Assertions 的基本概念 在Go中,Type Assertions的主要目的是在運行時將 interface 型別的值轉換為特定的實際型別。interface 是一種特殊的類型,它可以保存任何值的實例,但在運行時,我們可能需要確定該值的實際類型以執行相應的操作,以確保我們能夠安全地操作資料,這就是Type Assertions的作用。 Type Assertions的基本語法如下: value, ok := someInterface.(T) 這個表達式意思為將someInterface轉換為類型T。如果成功,它將value設置為轉換後的值,並將ok設置為true。如果轉換失敗,則value將是零值,而ok將是false。 Type Assertions的用途 Type Assertions 的主要用途包括: 資料型別的轉換 當我們處理interface型別的資料時,可能需要將其轉換為具體的型別,以便進行特定操作。 func process(someInterface interface{}) { if str, ok := someInterface.(string); ok { // 將interfacce轉換為string類型並進行操作 fmt.Printf("Length of string: %d\n", len(str)) } else { fmt.Println("Not a string") } } 確保型別的正確性 使用 Type Assertions,我們可以在執行特定操作之前,確保資料的型別是我們期望的。這有助於防止因型別錯誤而引發的執行時錯誤。 if val, ok := someInterface.(int); ok { // someInterface 是一個int類型 fmt.Printf("Value is an int: %d\n", val) } else { // someInterface 不是一個int類型 fmt....

2023-09-05 · 2 min · 397 words · Alan

從零開始:使用make函數創建資料結構

👨‍💻簡介 make函數在slice、map和之後會介紹到的channel的初始化中扮演著關鍵的角色。本文將會簡單介紹make函數的用法,以及在初始化不同資料結構時的差異,讓你更好地理解和利用make函數。 make函數基本概念 首先,讓我們來了解一下make函數的基本概念。在Go中,make函數用於動態分配記憶體並初始化slice、map和channel。 // 創建一個切片,長度為5,容量為10 mySlice := make([]int, 5, 10) 在上面的範例中,我們使用make函數創建了一個整數切片(slice),其長度為5,容量為10。這意味著切片可以容納5個元素,但它的底層陣列的容量是10,這為後續的操作提供了一定的靈活性。 make函數的語法 make函數的語法相對簡單。它的一般形式是: make(類型, 長度, 容量) 類型:指定要創建的資料類型,可以是切片、map或通道。 長度:表示資料結構的初始長度。 容量:只適用於切片和通道,表示底層陣列的容量。 使用make初始化切片 接下來,讓我們看看如何使用make函數初始化切片。 // 創建一個整數切片,長度為3,容量為5 mySlice := make([]int, 3, 5) mySlice[0] = 1 mySlice[1] = 2 mySlice[2] = 3 在這個例子中,我們首先使用make函數創建了一個長度為3、容量為5的整數切片。然後,我們分配了三個整數值到切片中。 使用make初始化Map 現在,讓我們看看如何使用make函數初始化Map。map是一種鍵值對的資料結構,非常適合用於存儲關聯性資料。 // 創建一個字符串到整數的map myMap := make(map[string]int) myMap["apple"] = 1 myMap["banana"] = 2 myMap["cherry"] = 3 在這個範例中,我們使用make函數創建了一個空的字符串到整數的map,然後添加了三個鍵值對。 make 函數在 Go 語言中常見用法包括初始化切片、map和通道。然而,它的使用也受到一些限制和約束。以下是 make 函數的常見用法以及相關的使用限制: 使用make初始化通道 最後,我們來看看如何使用make函數初始化通道。通道是Go語言中用於並發通信的重要機制。 // 創建一個通道,用於傳輸字符串資料 myChannel := make(chan string) go func() { myChannel <- "Hello" myChannel <- "World" }() 在這個例子中,我們使用make函數創建了一個通道,它可以傳輸字符串資料。然後,我們使用Go協程向通道發送了兩個字符串。...

2023-09-04 · 1 min · 153 words · Alan

Package:Golang 專案的組織策略

👨‍💻簡介 套件(Package)在Golang中扮演著組織和管理程式碼的重要角色。 package就像工具箱一樣,裡面裝滿各種不同的工具,每個工具都有特定的功能。這些工具能夠幫助你完成不同的任務,從修理家具到蓋小屋,樣樣都行。 今天這篇文章將快速瞭解 Golang 的package,學習如何建立package、匯入package以及一些使用技巧。 什麼是 Package? 在 Golang 中,Package 是一種組織程式碼的方式,它將相關的函式、變數和資源放在一個目錄中。這不僅有助於保持程式碼的整潔,還能讓我們更容易地重複使用程式碼。 Package 名稱與資料夾名稱的一致性 通常建議在建立package時,將package名稱與所在資料夾名稱保持一致,這樣有助於提高程式碼的可讀性和一致性。Golang 的匯入機制是基於package的 import 路徑來識別package,而 import 路徑通常會反映package的資料夾結構。這種一致性可以讓其他開發人員更容易理解你的程式碼,並且不需要額外的查找工作,因為package的名稱與資料夾名稱一致。 舉例來說,假設你的資料夾結構如下: project/ |-- greetings/ | |-- greetings.go | |-- main/ | |-- main.go 如果我們建立的package名稱為 greetings,我們可以在 greetings.go 中這樣定義: // greetings.go package greetings func Hello(name string) string { return "Hello, " + name } 然後在 main.go 中使用這個package: // main.go package main import ( "fmt" "your/project/path/greetings" ) func main() { message := greetings.Hello("Alan") fmt....

2023-09-01 · 2 min · 281 words · Alan

Interface:Go 語言中的抽象關鍵

👨‍💻簡介 在Go語言中,Interface 是一個重要且強大的概念。Interface提供了一種方式來定義對象之間的契約,讓你可以設計更具有靈活性和可擴展性的程式碼。 你可以把Interface想像成是一種約定,讓不同的東西彼此溝通的方式變得特別靈活和好擴充,告訴程式裡的各個元件彼此要怎麼合作。 什麼是Interface 在 Go 語言中,Interface是一種關鍵的概念,用於定義方法的契約,而不關心具體的實現。它是一種抽象的型別,描述了物件應該具備的方法。Interface在實現多態性、抽象和模組化設計等方面扮演著重要角色。 Interface是一種抽象的類型,它定義了一組方法簽名(method signatures),但不包含方法的實際實現。這些方法簽名定義了對象應該支援的操作,從而允許不同類型的對象實現同一個Interface並進行交互。 一聽可能有點高深,但其實它就像是一份約定,不管實際怎麼做,只要能遵循這份約定就行。 就好像你和朋友約好要出去玩,你們約定好一起出門、一起玩,但具體怎麼玩,是不是吃火鍋還是去唱歌,那就隨你們。這些約定就是你們的「Interface」,告訴大家「我們一起要做這些事情!」。 當然,這在程式碼裡的作用更大。透過這個「Interface」,你可以讓不同種類的東西,像是車、狗、電腦,都能夠用一樣的方式進行互動。不管是車、狗、還是電腦,只要符合了這個「Interface」約定的方法,你就可以放心地拿來用了。 Interface的基本使用 透過Interface,我們可以在不關心具體類型的情況下,對對象進行操作。這種多態性的概念讓程式碼更具彈性,能夠適應不同的實現。 // 定義一個Interface Shape,它具有一個 Area 方法 type Shape Interface { Area() float64 } // 定義一個 Circle 結構體,實現了 Shape Interface的 Area 方法 type Circle struct { Radius float64 } func (c Circle) Area() float64 { return 3.14 * c.Radius * c.Radius } // 定義一個 Rectangle 結構體,實現了 Shape Interface的 Area 方法 type Rectangle struct { Width, Height float64 } func (r Rectangle) Area() float64 { return r....

2023-08-31 · 4 min · 673 words · Alan

探索 Golang 中的結構體:如何有效地組織複雜資料

👨‍💻簡介 在程式開發的世界中,我們經常需要處理各式各樣的資料,可能是一個人的個人資訊,也可能是一個商品的詳細訊息。當我們面對這麼多的資料時,如何將它們有系統地整理起來,讓我們能夠輕鬆地找到所需,便成了一個重要的課題。這時,結構體的概念就像是一道曙光,為我們提供了一個非常有力的工具。 結構體基礎 結構體,就像是一張設計圖,讓我們畫下我們腦袋裡的想法,就像是一個多功能的工具箱,結構體讓我們能夠以組織化的方式來儲存各種資料片段,就像是將資料拼湊成了一個個獨特的拼圖。今天,我們將深入探討 Golang 中結構體的神奇之處,以及如何通過結構體來更有效地組織和處理複雜資料。 首先,我們來看看如何定義和使用結構體。結構體是一個自定義的資料類型,它允許我們組織不同類型的資料在一個單一的單位中。 type Person struct { FirstName string LastName string Age int } 以一個人的資訊為例,我們可以創建一個名為 Person 的結構體,其中包含了 FirstName、LastName 和 Age 這三個基本資料。這些資料如同載體,讓我們能夠更方便地一次性儲存和訪問它們。 現在,我們可以創建一個 Person 的實例,並訪問其字段: func main() { person := Person{ FirstName: "John", LastName: "Doe", Age: 30, } fmt.Println("First Name:", person.FirstName) fmt.Println("Last Name:", person.LastName) fmt.Println("Age:", person.Age) } 複雜資料的嵌套組織 但有時候,我們還需要更複雜的資料結構,例如住址。這時,結構體的嵌套就派上用場了,我們可以在 Person 結構體中嵌套另一個結構體,用來表示住址的相關資訊,如 Street、City 和 Country。 type Address struct { Street string City string Country string } type Person struct { FirstName string LastName string Age int Address Address } 也可以直接寫在裡面...

2023-08-30 · 2 min · 299 words · Alan

🚀 Golang 函數:從入門到精通

👨‍💻簡介 在 Go 語言中,函數(Function)是一個強大且重要的概念,就像食譜一樣,告訴你應該如何處理食材,最後得到一道美味的料理。經過哪些程序讓程式更有組織性和可讀性。函數可幫助你將程式碼區塊組織成可重複使用的元件,進而執行特定的任務。本文要帶你一探究竟,深入了解 Golang 裡的函數有哪些不同的方面。從基本的概念開始,一路講到更高級的技巧,我們會告訴你怎麼樣用函數來處理各種不同的情況。 函數基本概念 函數在 Golang 中是一組程式語句的組合,用於執行特定的任務。它們接受輸入(參數)並返回輸出(返回值),從高層次來看,就像是黑盒子,你提供輸入,它交付結果。在每個 Golang 程式中,最常見的函數是 main(),它是程式的入口點。 函數名稱與命名規則 在 Golang 中,函數名稱的命名規則如下: 名稱必須以字母開始,後面可以是任意數量的字母和數字。 函數名稱不能以數字開頭。 函數名稱不能包含空格。 如果函數名稱以大寫字母開頭,則可以被其他套件引用。如果以小寫字母開頭,則不能被其他套件引用,但可以在同一套件內部使用。 如果名稱由多個單詞組成,從第二個單詞開始的每個單詞首字母應大寫,例如 empName、EmpAddress 等。 函數名稱區分大小寫,即 car、Car 和 CAR 是三個不同的變數。 創建函數 在 Golang 中,創建函數的基本語法如下: func 函數名稱(參數1 型別1, 參數2 型別2, ...) 返回型別 { // 函數程式碼 return 返回值 } 首先,用 func 關鍵字開始函數宣告,然後是你想要給函數的名稱,一對括號 (),然後是一個包含函數程式碼的區塊。 以下是一個簡單的範例,它不接受任何參數,也不返回任何值。 package main import "fmt" // SimpleFunction 印出一個訊息 func SimpleFunction() { fmt.Println("Hello World") } func main() { SimpleFunction() // 呼叫 SimpleFunction 函數 } 接受參數的函數 如果要將資訊傳遞給函數,可以通過參數來實現。參數就像變數一樣。...

2023-08-29 · 5 min · 978 words · Alan
« Prev  Next  »
© 2024 艾倫的程式之旅 Powered by Hugo & PaperMod