Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (In...

[Golang] 以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)

Golang Taiwan Gathering #70 @Dcard
以 Mobile App 工程師視角,帶你進入 Golang 的世界 (Introduction of GoLang)

主題介紹:第一次嘗試使用 Golang?我也是!

透過學習 Golang,探索後端伺服器開發的精髓,並分享一些與其他語言的差異以及撰寫時需注意的事項,希望能夠為大家提供入門的指南。

講者介紹:Mobile App 工程師,因為從事 App 開發工作的經驗,開始對後端技術產生濃厚的興趣,並開始學習 Golang 這門語言。

Johnny Sung

April 26, 2023
Tweet

More Decks by Johnny Sung

Other Decks in Programming

Transcript

  1. Full stack developer Johnny Sung (宋岡諺) https://fb.com/j796160836 https://blog.jks.co ff ee/

    https://www.slideshare.net/j796160836 https://github.com/j796160836
  2. App ⼯程師都做些什麼? •拉 UI 畫⾯ (Zeplin, Figma) •接 API (Swagger)

    •⼿機特殊功能 (例如:藍芽、相機...) •修 Bug
  3. Go 語⾔介紹 Golang 是 2007 年由 Google 設計的,2009 年對外公開 


    主要⽬的是簡化軟體開發並提⾼效率。 
 它在設計上強調簡單性、易讀性和⾼性能, 
 特別適合編寫低延遲的後端服務和分佈式系統。
  4. Why Go ? •強型別 (strongly typed) •靜態型別 (statically typed) •垃圾回收

    (garbage collection) •平⾏運算、並⾏性 •體積⼩、效能快、多平台
  5. := 短變數宣告
 (Stort variable declaration) 變數建立 + 賦值 (assign) 的簡寫

    package main import "fmt" func main() { var a int = 3 b := 3 fmt.Println(a) fmt.Println(b) }
  6. 指標 (pointer) package main import "fmt" func main() { var

    a int = 3 var p *int = &a fmt.Println(a) fmt.Println(&a) fmt.Println(p) fmt.Println(&p) fmt.Println(*p) } // 3 // 0x14000124008 // 0x14000124008 // 0x14000126018 // 3 (印出值) (印該變數記憶體位址) (印出儲存的位址) (印該變數記憶體位址) (存取指標印出值)
  7. #include <stdio.h> #include <stdlib.h> int main() { int *arr; int

    i; arr = malloc( 10 * sizeof(int) ); for (i = 0; i < 10; i++) { arr[i] = i; } for (i = 0; i < 10; i++) { printf("%d ", arr[i]); } free(arr); return 0; } package main import "fmt" func main() { var arr [10]int for i := 0; i < 10; i++ { arr[i] = i } for i := 0; i < 10; i++ { fmt.Printf("%d ", arr[i]) } } Golang C Array(陣列)
  8. for 搭配 range package main import "fmt" func main() {

    var arr = []int{46, 15, 73, 16, 66, 35} for index, value := range arr { fmt.Printf("%d ", index, value) } }
  9. type Car struct { Brand string Year int } func

    (p *Car) SetBrand(brand string) { p.Brand = brand } func (p *Car) SetYear(year int) { p.Year = year } func (p *Car) GetBrand() string { return p.Brand } func (p *Car) GetYear() int { return p.Year } public class Car { private String brand; private int year; public Car(String brand, int year) { this.brand = brand; this.year = year; } public void setBrand(String brand) { this.brand = brand; } public void setYear(int year) { this.year = year; } public String getBrand() { return brand; } public int getYear() { return year; } } Golang Java
  10. func (p *Car) SetYear(year int) { p.Year = year }

    func (p *Car) SetYear(year int) { (*p).Year = year } 同義 ⾃動解除參照(語法糖) type Car struct { Brand string Year int }
  11. Error package main import ( "fmt" "strconv" ) func main()

    { v = "s2" s2, err := strconv.Atoi(v) if err != nil { fmt.Println(err) // strconv.Atoi: parsing "s2": invalid syntax } fmt.Printf("%T, %v\n", s2, s2) // int, 0 } Atoi (string to int)
  12. Error package main import ( "fmt" "strconv" ) func main()

    { v := "10" s, err := strconv.Atoi(v) if err != nil { fmt.Println(err) } fmt.Printf("%T, %v\n", s, s) // int, 10 } Atoi (string to int)
  13. defer(推遲、延後) (⽰意簡化版範例) package main import ( "fmt" "os" ) func

    main() { userFile := "my_file.txt" fout, err := os.Create(userFile) if err != nil { fmt.Println(userFile, err) return } defer fout.Close() fout.WriteString("Hello, World.") }
  14. channel(通道) package main import "fmt" func main() { ch :=

    make(chan int, 1) defer close(ch) ch <- 1 fmt.Print(<-ch) } var ch chan int ch = make(chan int) ch := make(chan int) 宣告 塞值、取值 fatal error: all goroutines are asleep - deadlock! 緩衝區為 1 channel 型態
  15. 多執⾏緒 & WaitGroup package main import ( "fmt" "sync" )

    func main() { wg := sync.WaitGroup{} wg.Add(2) go func() { defer wg.Done() // Do something }() go func() { defer wg.Done() // Do something }() wg.Wait() fmt.Println("Done") } package main import ( "fmt" "sync" ) func main() { wg := sync.WaitGroup{} wg.Add(2) go worker(&wg) go worker(&wg) wg.Wait() fmt.Println("Done") } func worker(wg *sync.WaitGroup) { defer wg.Done() // Do something }
  16. (async () => { await Promise.all([ (async () => {

    console.log('Worker 1 started'); await sleep(1000); console.log('Worker 1 finished'); })(), (async () => { console.log('Worker 2 started'); await sleep(2000); console.log('Worker 2 finished'); })(), ]); console.log('Done'); })(); async function sleep(ms) { return new Promise(resolve => setTimeout(() => resolve(), ms)); } package main import ( "fmt" "sync" "time" ) func main() { wg := sync.WaitGroup{} wg.Add(2) go func() { defer wg.Done() fmt.Println("Worker 1 started") time.Sleep(time.Millisecond * 1000) fmt.Println("Worker 1 finished") }() go func() { defer wg.Done() fmt.Println("Worker 2 started") time.Sleep(time.Millisecond * 2000) fmt.Println("Worker 2 finished") }() wg.Wait() fmt.Println("Done") } Golang JavaScript (NodeJS)
  17. channel(通道) package main import "fmt" func main() { ch :=

    make(chan int) defer close(ch) ch <- 1 fmt.Print(<-ch) } fatal error: all goroutines are asleep - deadlock! ⚠ 無緩衝區
  18. ⽤ range 讀取 channel •⽤ range 讀取 channel 直到它被關閉 


    ,若無值可取就會「等待」 •channel 關閉後,進⼊ 唯讀 狀態 •for range 會讀完 所有值 才結束 ch := make(chan int) // ... do something for i := range ch { fmt.Println(i) }
  19. package main import ( "fmt" "sync" "time" ) func main()

    { res := distributedSum(4, 1, 100) fmt.Printf("Total: %d\n", res) } Fan out / Fan in 範例
  20. func distributedSum(numOfWorkers int, from int, to int) int { wg

    := &sync.WaitGroup{} wg.Add(numOfWorkers) in := make(chan int, (to-from)-1) out := make(chan int, numOfWorkers) res := make(chan int, 1) for i := 0; i < numOfWorkers; i++ { go sumWorker(in, out, wg) } go compilationWorker(out, res) for i := 0; i <= to; i++ { in <- i // 塞資料給各個 sumWorkers } close(in) // 關閉資料窗⼝ (通知各個 sumWorkers 停⽌讀值) wg.Wait() // 等待所有 workers 結束 close(out) // 關閉資料窗⼝ (通知 compilationWorker 停⽌讀值) return <-res }
  21. func sumWorker(in chan int, out chan int, wg *sync.WaitGroup) {

    defer wg.Done() num := 0 for n := range in { // 讀取通道直到通道被關閉 num += n time.Sleep(time.Millisecond * 30) } fmt.Printf("partial sum: %d\n", num) out <- num } func compilationWorker(in chan int, out chan int) { sum := 0 for i := range in { // 讀取通道直到通道被關閉 sum += i } out <- sum }
  22. •完全⾃學!Go 語⾔ (Golang) 實戰聖經 
 (The Go Workshop: Learn to

    write clean, efficient code and build high-performance applications with Go) https://www.tenlong.com.tw/products/9789863126706 •下班加減學點 Golang 與 Docker https://ithelp.ithome.com.tw/users/20104930/ironman/2647 •被選召的 Gopher 們,從零開始探索 Golang, Istio, K8s 數碼微服務世界 https://ithelp.ithome.com.tw/articles/10240228 •PJCHENder 未整理筆記 https://pjchender.dev/golang/go-getting-started/ 參考資料
  23. Mobile API CRUD Login / Logout Token (Session) JWT /

    Clean Architecture Unit Test Docker Kubernetes (k8s) Load Balancer Database Cache Queue Swagger channel mutex lock CI / CD MongoDB RDBMS MySQL PostgreSQL Memcached Redis RabbitMQ grafana + prometheus Pod Service Ingress SOLID 5 OOP 3 goroutine Backup DRP (Disaster Recovery Plan) Logs BCP (Business Continuity Plan) Git Logger
  24. obile API CRUD Login / Logout Token (Session) JWT /

    Clean Architecture Unit Test Docker Kubernetes (k8s) Swagger channel mutex lock Pod Service Ingress SOLID 5 OOP 3 goroutine
  25. Mobile Token (Session) JWT Docker Kubernetes (k8s) Load Balancer Database

    Cache Queue Swagger MongoDB RDBMS MySQL PostgreSQL Memcached Redis RabbitMQ Pod Service Ingress Logger
  26. Mobile CI / CD grafana + prometheus Backup DRP (Disaster

    Recovery Plan) Logs BCP (Business Continuity Plan) Git