Slide 1

Slide 1 text

Introduction of GoLang Johnny Sung 圖片來源:https://www.gctel.com/gopher-bounty-match-program/

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

https://www.facebook.com/ProgrammersCreateLife/photos/a.962151813833697/5879918952056934/

Slide 4

Slide 4 text

App ⼯程師都做些什麼? •拉 UI 畫⾯ (Zeplin, Figma) •接 API (Swagger) •⼿機特殊功能 (例如:藍芽、相機...) •修 Bug

Slide 5

Slide 5 text

接 API •Swagger •API Testing

Slide 6

Slide 6 text

Go 語⾔介紹 Golang 是 2007 年由 Google 設計的,2009 年對外公開 
 主要⽬的是簡化軟體開發並提⾼效率。 
 它在設計上強調簡單性、易讀性和⾼性能, 
 特別適合編寫低延遲的後端服務和分佈式系統。

Slide 7

Slide 7 text

Why Go ? •強型別 (strongly typed) •靜態型別 (statically typed) •垃圾回收 (garbage collection) •平⾏運算、並⾏性 •體積⼩、效能快、多平台

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

Why Go ? https://www.docker.com/company/newsroom/media-resources/ https://kubernetes.io/ 都是使⽤ Go 語⾔編寫的

Slide 10

Slide 10 text

GoLand by JetBrains IDE https://www.jetbrains.com/go/

Slide 11

Slide 11 text

伺服器架構 •後端程式 •資料庫 •共享空間 •排程器 (Queue)

Slide 12

Slide 12 text

程式架構 •Data Model •商業邏輯 •DB Interface, HTTP Interface

Slide 13

Slide 13 text

Go 語⾔特性

Slide 14

Slide 14 text

:= 短變數宣告
 (Stort variable declaration) 變數建立 + 賦值 (assign) 的簡寫 package main import "fmt" func main() { var a int = 3 b := 3 fmt.Println(a) fmt.Println(b) }

Slide 15

Slide 15 text

https://twitter.com/cachecoherent/status/1539867862227091456 指標 (pointer)

Slide 16

Slide 16 text

指標 (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 (印出值) (印該變數記憶體位址) (印出儲存的位址) (印該變數記憶體位址) (存取指標印出值)

Slide 17

Slide 17 text

Array(陣列) & Slice(切⽚) •Array(陣列):固定⻑度 (Fixed length) 的清單 •Slice(切⽚):可以⾃由增加或減少⻑度的清單 (常⽤)

Slide 18

Slide 18 text

#include #include 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(陣列)

Slide 19

Slide 19 text

Slice(切⽚) https://pjchender.dev/golang/slice-and-array/

Slide 20

Slide 20 text

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) } }

Slide 21

Slide 21 text

Class(類別) •Go 語⾔沒有 class (類別) 只有 struct (結構) type Car struct { Brand string Year int }

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

接收器 讓 struct 有擴充 method 的可能 •值接收器 (value receiver) •指標接收器 (point receiver)

Slide 24

Slide 24 text

接收器 •值接收器 (value receiver)
 它會複製 struct 變數並傳進函式 (method) func (c Car) GetName() int { return c.Name }

Slide 25

Slide 25 text

•指標接收器 (point receiver)
 它會把 struct 轉成指標並傳進函式 (method) [常⽤] 接收器 func (p *Car) SetYear(year int) { p.Year = year }

Slide 26

Slide 26 text

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 }

Slide 27

Slide 27 text

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)

Slide 28

Slide 28 text

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)

Slide 29

Slide 29 text

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.") }

Slide 30

Slide 30 text

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 型態

Slide 31

Slide 31 text

多執⾏緒 & 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 }

Slide 32

Slide 32 text

(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)

Slide 33

Slide 33 text

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! ⚠ 無緩衝區

Slide 34

Slide 34 text

https://decomyplace.com/n.php?id=9357 ch := make(chan int, 1)

Slide 35

Slide 35 text

https://www.dnaindia.com/business/report-what-s-cooking-on-the-cloud-2752364

Slide 36

Slide 36 text

https://static.wixstatic.com/media/160302bd324b4187b67b7f265c3b8f24.jpg/v1/ fi ll/w_541,h_1333,al_c,q_85,enc_auto/160302bd324b4187b67b7f265c3b8f24.jpg ? to ch <- 1 fatal error: all goroutines are asleep - deadlock!

Slide 37

Slide 37 text

⽤ range 讀取 channel •⽤ range 讀取 channel 直到它被關閉 
 ,若無值可取就會「等待」 •channel 關閉後,進⼊ 唯讀 狀態 •for range 會讀完 所有值 才結束 ch := make(chan int) // ... do something for i := range ch { fmt.Println(i) }

Slide 38

Slide 38 text

https://blog.xuite.net/yafenyan/blog/60585613#

Slide 39

Slide 39 text

Fan out / Fan in https://betterprogramming.pub/writing-better-code-with-go-concurrency-patterns-9bc5f9f73519

Slide 40

Slide 40 text

package main import ( "fmt" "sync" "time" ) func main() { res := distributedSum(4, 1, 100) fmt.Printf("Total: %d\n", res) } Fan out / Fan in 範例

Slide 41

Slide 41 text

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 }

Slide 42

Slide 42 text

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 }

Slide 43

Slide 43 text

•完全⾃學!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/ 參考資料

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

Mobile Token (Session) JWT Docker Kubernetes (k8s) Load Balancer Database Cache Queue Swagger MongoDB RDBMS MySQL PostgreSQL Memcached Redis RabbitMQ Pod Service Ingress Logger

Slide 47

Slide 47 text

Mobile CI / CD grafana + prometheus Backup DRP (Disaster Recovery Plan) Logs BCP (Business Continuity Plan) Git

Slide 48

Slide 48 text

Q & A