Go ด้วยกัน Go ได้ไกล-pointers, struct, goroutines, channel, mutex [EP.5]

Grassroot Engineer
3 min readAug 12, 2024

--

https://www.softwebsolutions.com/resources/golang-web-development.html
  • Pointers = Refer memory address by & and use value by *
  • Struct = Like class in Python (but nothing method and OOP feature).
  • Goroutine = Lightweight thread.
  • Channel = Ways to return mutivalues with different types.
  • Mutex = To prevent goroutines to edit the same data in the same time.

1. Pointers (การอ้างอิง address ด้วย & และเอา value ออกมาด้วย *)

ในการทำ API จะใช้เยอะ เพราะจะได้ performance ที่ดีแบบที่ไม่ต้องจอง value เหมือน type แบบอื่นๆ เพราะจองแค่ address ใน memory เท่านั้น

  • เป็นการระบุว่าสิ่งที่เราจะหาอยู่ที่ไหน (แต่ไม่ได้ครอบครอง)
  • ค่าในตัวแปร pointers เป็นเพียง address ในหน่วยความจำ
  • ช่วยให้เราเปลี่ยนแปลงค่าที่ต้นทาง โดยไม่ต้องเปลี่ยนแปลงตำแหน่ง memory (เพราะปกติเวลาเราเปลี่ยนค่าใน value จะเป็นการเปลี่ยนค่าใน memory หรือมีการเขียนใหม่ใน RAM อ่ะนะ มันจึงช้ากว่า…เพราะไม่ได้ใช้ตำแหน่งเดิมไง)
  • Pointer ใน Go มีไว้แค่อ้างอิงตำแหน่งเท่านั้นนะ ไม่สามารถคำนวณ math ได้
  • เราจะใช้ * ในการแทน pointer นะ โดยค่าเริ่มต้นคือ nil นะ เช่น
    var p *int p เป็น pointer ที่มี type แบบ int
  • เราจะใช้ & เพื่อสร้าง pointer ที่ชี้ไปที่ค่าตัวแปรนั้นๆ เช่น
i := 42  // ตัวแปร i เก็บเลข42 ไว้
p = &i // ถัดมาตัวแปร p เก็บ address ของ i ไว้
  • เราจะใช้ * ดึงค่าภายใต้ address ที่ pointer นั้นชี้อยู่ออกมา
fmt.Println(*p)  // อ่านค่า pointer p โดยเป็นตำแหน่งที่ i อยู่นะ
*p = 21 // เป็นการ set ค่า 21 เข้าไปที่ pointer p หรือ ที่อยู่ของตัวแปร i นั่นเอง (ไม่งงเนอะ)... พูดง่ายๆ เอาเลข 21 ไปใส่ในตัวแปร i นั่นเอง
Pointers explaination (ดูภาพนี้ภาพเดียว น่าจะเข้าใจได้เลย)

จำง่ายๆนะ

  • ใช้ & ในการชี้ไปหา
    เช่น &i คือ point to i
  • ใช้ * ไปเอา value ออกมา
    เช่น *p คือ เอา value ที่เก็บไว้ในตำแหน่งของ p ออกมา หรือ
    ถ้าจะใส่ค่าใหม่ก็ *p = <new value> ได้เลย

2. Struct (โครงสร้างข้อมูล)

เป็น data type แบบหนึ่ง ที่ใช้ในการรวมกลุ่มของตัวแปรหลายๆตัวที่มีหลายๆ types เข้าด้วยกัน และเก็บค่าเข้าไปได้ด้วย

  • ง่ายๆคือ การรวมฟิลด์เข้ามาไว้ด้วยกัน
  • จิงๆ ผมว่าคล้ายๆกับ class ใน Python เลยนะ
    (แต่เป็น class ที่มีเพียง attribute, และไม่มี method ภายใน + inherit ไม่ได้)
  • เพราะไม่มี method ภายใน การจะให้มันทำอะไรต่อได้ ก็สร้าง function มารับ struct นั้นไปทำต่อได้เลย (ตามภาพด้านล่างเลยนะ อธิบายอย่างละเอียด)
Explain Struct in one photo

3. Goroutines

ในการเขียนโปรแกรมจะมี Sync and Async ซึ่งการทำงานแบบ Async ใน Go เราสามารถะใช้ Goroutines ได้เลยซึ่งเป็น lightweight thread (ถูกจัดการโดย runtime in Go + ใช้ resource น้อยกว่าการสร้าง thread จริงๆ)

  • ในการใช้งาน เราจะใช้ keyword go ไปนำหน้า function นั้นๆไว้นั่นเอง พูดง่ายๆ วาง go ไว้ข้างหน้าจะทำให้ function นั้นเป็น async (เหมือนไปทำงานใน background นั่นเอง หรือ concurrently)
  • ลองดูตัวอย่างคับ
ใช้ go keyword เพื่อทำให้ sayHello() เป็น goroutine (ทำงานแยกออกไป จึงไม่มีการรอกัน)
Explain goroutine very clear

4. Channel

เป็น another key feature in go เพื่อให้ goroutines สามารถสื่อสารกันได้อย่างปลอดภัย โดยเป็นการเชื่อม type เข้าด้วยกัน โดยสามารถส่งและรับค่าผ่าน <-

  • Channel จะเหมือนกับ map, slice ตรงที่ต้องสร้างขึ้นมาก่อนถึงจะนำไปใช่ได้ ดูตัวอย่างเลยดีกว่าคับ
goroutine with channel เพื่อให้ goroutine รอให้ทำงานเสร็จก่อน (ใช้แทน async, await นั่นเอง)
1 channel with auto size of elements

5. Mutex

มาจาก Mutual Exclusion เป็นกลไกที่ใช้ป้องกันไม่ให้หลาย Goroutines เข้าถึงและแก้ไขข้อมูลเดียวกัน ในเวลาเดียวกัน ซึ่งอาจทำให้เกิดข้อผิดพลาดในการประมวลผล (race condition) พูดง่ายๆ มันทำให้ synchronus นั่นเอง

  • ในการใช้งาน เราสามารถใช้ sync.Mutex จาก lib sync เพื่อจัดการการเข้าถึงข้อมูลที่ใช้ร่วมกันได้อย่างปลอดภัย (ป้องกันการเข้าถึงข้อมูลก้อนเดียวกัน ในเวลาเดียวกัน)
  • sync.Mutex มี 2 methods คือ Lock, Unlock ให้เราใช้ได้
package main

import (
"fmt"
"sync"
)

var (
counter int
mutex sync.Mutex
)

func increment(wg *sync.WaitGroup) {
mutex.Lock() // ล็อก mutex เพื่อป้องกันการเข้าถึงทรัพยากรที่ใช้ร่วมกัน
counter++ // ส่วนที่สำคัญ: เพิ่มค่า counter
mutex.Unlock() // ปลดล็อก mutex
wg.Done()
}

func main() {
var wg sync.WaitGroup

for i := 0; i < 10; i++ {
wg.Add(1)
go increment(&wg)
}

wg.Wait() // รอให้ goroutines ทั้งหมดทำงานเสร็จ
fmt.Println("ค่าสุดท้ายของ counter:", counter)
}
Explain Mutex

If you think it’s useful for you, just clap your hands 👏 to be encouraged me.

GRASSROOT ENGINEER 😘

แล้วพบกันใหม่ตอนถัดไปคับ

--

--

Grassroot Engineer
Grassroot Engineer

Written by Grassroot Engineer

ATM engineer who is interested in CODING and believe in EFFORT. — https://grassrootengineer.com

No responses yet