LearnGo

@LearnGo

Team to learn Go

Public team

Community (0)
No community contribution yet

Joined on Feb 3, 2020

  • # OOP VS FP ###### tags: `OOP`,`FP` golang 不是一種 OOP (Object-oriented programming) ,反而比較偏向 FP (Functional Programming),雖然我個人認為它不是很純的 FP,但是它擁有 First-class function 的特性,所以可以用一些 script language 常見的手法,使用在 golang 上面。 ## 什麼是OOP? ## 什麼是FP? ## First-class function ## script language
     Like  Bookmark
  • # Go - Goroutine,Channel ###### tags: `Go`,`Goroutine`,`Channel` ## Goroutine、Channel 用途 Goroutine用於平行處理。也就是**非同步執行**。 執行時如果是單線程(Single Thread)的,那麼執行時只會用到一個 CPU,如果你的電腦有兩個以上的 CPU,那可以想辦法讓他們分工合作。 分工合作需要溝通,Channel用途在於可以讓不同的Goroutine去溝通。 ## 如何宣告Channel 搭配make()使用。 ```go= import "fmt" func main(){ s := make(chan string) //宣告一個 channel 變數 s <- "hello" //寫入 channel (sender) val <- s //讀取 channel (receiver) fmt.Println(val) } ``` 分辨讀寫非常容易,請看 <- 符號放在哪邊,**chan<
     Like  Bookmark
  • # Go - 循環引用 ###### tags: `Go` ## 循環引用錯誤 當你開始撰寫更複雜的系統時,你一定會遇到循環引用的問題。當 A 套件要引用 B 套件,但 B 套件又引用 A 套件時就會發生這樣的狀況(不管是直接引用或是透過其他套件間接引用)。這種情況編譯器是不會允許的。 ```go= package shopping import ( "shopping/db" ) type Item struct { Price float64 } func PriceCheck(itemId int) (float64, bool) { item := db.LoadItem(itemId) if item == nil { return 0, false } return item.Price, true } ``` ## 為何編譯器不允許
     Like  Bookmark
  • # GO - Pointer ###### tags: `Go`,`Pointer` ## Pointer 當我們在呼叫一個函式時帶入一個參數,則這個參數會被複製到函式中: ```go= func zero(x int) { x = 0 } func main() { x := 5 zero(x) fmt.Println(x) // x is still 5 } ``` 在這個程式中,zero 這個函式不會動到 main 函式中的 x 變數值,可是如果我們想要改,該怎麼做呢?一種方式是使用一個**特殊的資料型別,即所謂的指標(pointer)**: ```go= func zero(xPtr *int) { *xPtr = 0 } func main() { x := 5 zero(&x) fmt.Println(x) // x is 0 } ``` **指標可以取得儲存變數值的記憶體位置,而不是變數值本身(或是指向某物的指標值)**。透過指標 (*int),zero 函式可以修改原本的變數值。 ## 指標的理解:
     Like  Bookmark
  • # Go - 為何需要指標 ###### tags: `Go`,`Pointer` ## 說明 不使用指標的話,某些情況是沒法賦值給結構體的。 ## 範例 ```go= package main import ( "fmt" ) func Compute(a int) { a = 0 } func main() { x := 5 Compute(x) //0 fmt.Println(x) //5 } ``` 上面範例經過 Compute 這個 func ,x 值並無改變,因為在 golang ,運作行為是『複製』 變數傳進去,所以兩個變數是完全獨立且分開的。 ```go= package main import ( "fmt" ) func Compute(a *int) { *a = 0 } func main() { x := 5 Compute(&x) //0 fmt.Println(x)//0 } ``` 上面範例為什麼 x,會有不一樣? 是因為這時侯 golang 行為是傳送位址進去,所以在 Compute 裡面所改到的值是原始 x,所改到的值。
     Like  Bookmark
  • # Go - interface ###### tags: `Go`,`interface` ## interface是什麼? golang 的 interface,我覺得對初學者來說會有點疑惑,畢竟 interface 在這裡有兩個意思,一個代表『泛用型別』、一個代表類似傳統 OOP(Object-oriented programming) 所說的 interface,下面就來介紹兩種使用方式。 **介面是一種型態,它定義了宣告但沒有實作。** ## 泛用型別 interface{} 如果在後面加上兩個大括號,可以把它當作一種 type 使用。 在強型別語言中,如果濫用這個機制,會吃到不少苦頭。推薦的使用情境都是用在面對一個**型別不是太穩定的 api 需求**,會使用這種型別設計。 ```go= type Logger interface { Log(message string) } ``` 你可能會覺得這樣有什麼用處?**介面可以讓你的程式碼從實作中去耦合**。例如,你可能會有很多種不同的 loggers: * 範例1: ```go= type SqlLogger
     Like  Bookmark
  • # Go concurrency
     Like  Bookmark
  • # Go - Channel ###### tags: `Go`,`Channel` ## Channel是什麼? Goroutine用於平行處理。也就是**非同步執行**。 執行時如果是單線程(Single Thread)的,那麼執行時只會用到一個 CPU,如果你的電腦有兩個以上的 CPU,那可以想辦法讓他們分工合作。 分工合作需要溝通,Channel用途在於可以讓不同的Goroutine去溝通。 ## Unbuffered Channel 保證讀寫都需要執行完畢才可以結束主程式。 ## 範例 ```go= func main() { go func() { fmt.Println("GO GO GO") }() //立即執行的函式 time.Sleep(1 * time.Second) } ``` 上面的例子在執行完 main 函數,就會直接跳出,所以後面設定了等待一秒可以解決此問題,但是一般開發模式不會加上 Timeout,這邊該如何透過 Unbuffered Channel 方式來達到一樣的效果。 ```go= func main() {
     Like  Bookmark
  • # Go - goroutine ###### tags: `Go`,`goroutine` ## 用途 平行處理。也就是**非同步執行**。 執行時如果是單線程(Single Thread)的,那麼執行時只會用到一個 CPU,如果你的電腦有兩個以上的 CPU,那可以想辦法讓他們分工合作。 ```go= package main import ( "fmt" "time" ) func Print() { for i := 0; i < 10; i++ { fmt.Println(i) time.Sleep(1 * time.Second) } } func main() { go Print() for i := 1000; i < 1010; i++ { fmt.Println(i) time.Sleep(1 * time.Second) } } ``` 由上面範例可以看到,在 main 裡面的迴圈值跟 Print 裡面迴圈的值,交錯印出來。表示 Print 這個 func 跟 main 裡面,是平行處理的。 ## 主線程、子線程 ```g
     Like  Bookmark
  • # Websocket的使用 ###### tags: `Go` * https://www.youtube.com/watch?v=dniVs0xKYKk
     Like  Bookmark
  • # Links to share ###### tags: `Go` * [awesome-go](https://github.com/avelino/awesome-go)
     Like  Bookmark
  • # Go - build and package ###### tags: `Go` ## package 以下程式碼,檔案取名為:`main.go` ```go= package main import "fmt" func main() { fmt.Println("Hello, World") fmt.Println("哈囉!世界!") } ``` **每個 .go 原始碼,都必須從 package 定義開始**,而對於包括**程式進入點 main 函式的 .go 原始碼,必須是在 package main 之中。** 以下程式碼,檔案取名為:`hello.go` ```go= package main import "hello" func main() { hello.HelloWorld() } ``` main.go 中要用到剛建立的 hello 套件中的 HelloWorld 函式,這時 package 的設定就會發揮一下效用,你得將 hello.go 移到 src/hello 目錄之中,也就是**目錄名稱必須符合 package 設
     Like  Bookmark
  • # Basic Syntax (基礎語法) ###### tags: `Go` ## if ... else ... > https://gobyexample.com/if-else Example ```go if 7%2 == 0 { fmt.Println("7 is even") } else { fmt.Println("7 is odd") } ``` Output ``` 7 is odd ``` ## for loop > https://tour.golang.org/flowcontrol/1 Example ```go for i := 0; i < 10; i++ { sum += i } ``` ## foeach > https://syntaxdb.com/ref/go/for-each Example ```go studentGrades := [3]int{50, 89, 75} for _, grade := range studentGrades { fmt.Println("Gra
     Like  Bookmark
  • # Simple Http Client (簡易的Http服務器) ###### tags: `Go` #### Example Create file `project/main.go` ```go package main import ( "fmt" "log" "net/http" ) func homePage(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Home Page") } func wsEndpoint(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World") } func setupRoutes() { http.HandleFunc("/", homePage) http.HandleFunc("/ws", wsEndpoint) } func main() { fmt.Println("Server opened on p
     Like  Bookmark