มาเขียน Golang ขั้นพื้นฐานกัน

Golang เป็นภาษาถูกสร้างโดย Google ที่ใช้สำหรับทำ API หรือ Microservices เป็นภาษาหนึ่งที่จะถูกสร้างแบบ Compiler โดย Source Code จะถูกสร้างเป็นภาษาเครื่องทั้งหมดทำให้เร็วต่อการประมวลผล และทำงานแบบ Multi-Thread ได้ทำให้เร็วมาก (สุดท้ายก็ไปคอขวดที่ db หยอกๆ 5555) ซึ่งจะต่างจาก ภาษา Javascript(nodejs nodets) และ PHP อ้างอิงเฉพาะภาษาที่ผมเขียนจริงจังนะครับ ที่จะถูกแปลงใหม่ทุก รอบและทำแบบ Single-Thread จริงๆระดับผู้ใช้งานก็ไม่รู้สึกครับอันไหนก็ได้ให้เข้ากับงานที่จะทำ เพราะสมัยใหม่แทบทุกที่เขียนเป็น Microservices อยู่แล้ว Aplication เดียวจะมี API กี่เส้นและกี่ภาษาก็ได้ ประเทศไทยใครก็ได้…ไม่น่าจะเกี่ยว

Golang เป็นภาษาที่ต้องทำ Static Type เมื่อมีการ Compiler จะถูกตรวจสอบ Type ก่อนฉนั้นต้องกำหนด Type ให้ตัวแปลเสมอคือดีเพราะเป็นการบังคับไปในตัวไม่ใส่ก็รันไม่ผ่าน

มาติดตั้งโปรเจคกันเลยดีกว่าครับ

mkdir example
cd example
go mod init example/hello

จากนั้นผมจะสร้าง file hello.go ขึ้นมา

package main

import "fmt"

func main() {
fmt.Println("Hello, World!")
}

จากนั้นลอง run ดูโดยใช้คำสั่ง

go run hello.go

จะได้ output ออกมาตามรูป

จากนั้นจะลอง import package มาเพิ่ม

จะขึ้นแดงๆเพราะมันหาไม่เจอเราก็มาทำการ install มันก่อนโดยใช้คำสั่ง

go mod tidy

แล้วทำการ restart VSCode เพื่อให้มันหายแดงแล้วลอง run ดูเหมือนเดิมก็จะได้ output ตามภาพ

ส่วนอันนี้ผมจะมัดรวมคำสั่งต่างๆแล้วอธิบายไปทีละส่วนนะครับ

การประกาศ variable ใน go จะต้องมี :
<var> <ชื่อตัวแปร><type> = <value>
แต่สามารถเขียนย่อ ได้ด้วย <ชื่อตัวแปร> := <value> มันจะ auto type ให้เราได้ทันทีตามภาพที่แสดงด้านล่าง
ส่วน fmt เป็นคำสั่งปริ้นหรือ console เอาค่า output ออกมาแสดง

วิธีประกาศ array และการวนลูปจากภาพเรารู้วิธีกาศประกาศตัวแปรแบบสั้นแล้วเราก็ประกาศแบบสั้นจะเห็นว่าผมประกาศไว้ 2 แบบแบบกำหนดขนาดและไม่กำหนดขนาด

วิธีการประกาศ function และ return ค่าเราต้องระบุด้วยว่าจะ type ที่จะ return ของ function นั้นด้วย โดยข้างล่างจะเป็น function รวมชื่อ และ บวกเลขจำนวนเต็ม หรือจะเป็น function ที่ return 2 ตัวแปร เราก็ต้องกำหนด type ที่จะ return ใน function มาให้ครบ ซึ่งผลลับก็เหมือนกัน

วิธีสร้าง Struct บน Go โดยจะกำหนด variable และ type ใน struct สมมุติมีการส่งค่ามาเพราะ Go มักจะค่อนข้างเปะเราเลยต้องมีการสร้าง struct ให้เปะๆกับค่าที่จะรับมาซึ่งจะมีการพูดต่อบทความหน้าโดยจะใช้ Gin Framework

*** Go ไม่มี Class มีแต่ Struct ที่มาทดแทน ซึ่งมาเขียนใหม่ๆก็จะแปลกหน่อยๆแต่ไม่เป็นปัญหาครับชีวิต DEV ต้องลื่นไหลไปให้ได้ 55555

ถึงไม่มี class แต่ก็ไม่เชิงว่าไม่เป็น OOP มันก็เป็นถึงจะไม่ 100% ก็ตามมันก็ยังสั่งบวกเลขได้อยู่ อย่างรูปคือ function ที่ใช้ได้เฉพาะ struct ที่มีชื่อว่า struct1

มาต่อเรื่อง Pointer มันคืออะไรจำเป็นไหมเพราะจาก code ข้างต้นมันก็รับส่งค่าได้ปกติมันจำเป็นต้องมี Pointer ไหมจริงๆมันจำเป็นมากเรื่อง performance เพราะ Pointer เนี่ย memmory มันจะไปจดจำ address คือใช้ address อ้างอิงแทน variable งงไหม 5555 เพราะก็ต้องกำหนด variable อยู่ดี เอาเป็นว่ามาดูกัน

ผมจะยก function + เลขให้เห็นภาพจากภาพ c รับค่าจาก a และ b +กัน มันเกิดการ coppy ค่าส่งต่อๆกันไปจนมา coppy ค่าลง c คือมันจะเหมือนเขียนใหม่ทุกครั้งแล้วส่งต่อจนสำเร็จอันนี้คือการทำงานปกติของโปรแกรมทั่วไป

จากภาพผมไปเอา code มาจากซักที่จำไม่ได้ว่าเอาจากไหนเลยไม่ได้อ้างอิงถึง
ทำการ check เช็คสัญลักษณ์เพิ่มเติมได้ที่นี่
https://pkg.go.dev/fmt
%T การบอก type
%p การบอก address ที่ memmery ถูกจองอยู่
%v แสดงค่า value ออกมา

& ค่าของ address ที่ memmery ถูกจองอยู่
* ค่าที่ pointer นั้นชี้อยู่

STEP 1
จะเห็นว่ามีการประกาศ i := 42

STEP 2
1. main — i int: &i=0xc000012088 i=42 คือการบอก type address และ value

STEP 3
เปรียบเสมือนการประกาศตัวว่า var p *int := &i คือเหมือนการ p ชี้ไปที่อยู่ address ของ i

STEP 4
2. main — p *int: &p=0xc000006030 p=&i=0xc000012088 *p=i=42
จะเห็นว่า ที่อยู่ของ &p ก็มีนะแต่มันถูกชี้ไปที่อยู่ของ i ค่ามันเลยไปเท่ากับ i คือ42

STEP 5
จะเห็นว่ามีการส่ง p เข้า func byval ซึ่งรับค่าที่เป็น pointer ของ int ซึ่ง p ก็เข้าตามเงื่อนไข
3. byval — q *int: &q=0xc000006038 q=&i=0xc000012088 *q=i=42 ซึ่งไม่มีอะไรแปลกใหม่ที่อธิบายไปด้านบน q ก็มี address ใหม่ของตัวมันเองแต่มันก็ถูกชี้ไปที่ p ซึ่ง p ถูกชี้ไปที่ &i ค่าก็เท่า 42 ดังเดิม

STEP 6 จะเห็นว่ามีการเปลี่ยน *q =4143 คือการชี้ Pointer นั้นให้เปลี่ยนค่า value
4. byval — q *int: &q=0xc000006038 q=&i=0xc000012088 *q=i=4143 ซึ่งค่า *q ก็ถูกเปลี่ยน

STEP 6 & 7
5. main — p *int: &p=0xc000006030 p=&i=0xc000012088 *p=i=4143
6. main — i int: &i=0xc000012088 i=4143
จะเห็นได้ว่าทั้งค่าที่ *p และ i มีค่าเท่ากัน

ก็พอจะเห็นภาพแล้วมาถึงตรงนี้ระหว่าง coppy กับ pointer ซึ่ง coppy ก็ตามชื่อเขียนขึ้นมาใหม่ทุกครั้ง แต่ pointer ชี้ไปตรงจุดเดียวเปลี่ยนที่เดียว ก็มาช่วยของเรื่อง performance ให้ดีขึ้น

มาถึงตัวสุดท้าย defer อันนี้คือคำสั่งทำจะทำคำสั่งหรือ function นี้เป็นลำดับสุดท้ายซึ่งจากภาพผมจะสมมุติเหมือนต่อ database จากนั้นจะสั่งให้ปิดดาต้าเบสเป็นลำดับสุดท้าย defer ไหนอยู่ก่อนก็จะทำลำดับที่ท้ายกว่าซึ้งจาก output จะเห็นว่าจะ Log ก่อน ปิดฐานข้อมูล

ส่วนอันนี้เป็น source code และ output ทั้งหมดของวันนี้

วันนี้ก็น่าจะปูพื้นฐานไว้ประมาณนี้ครับ รอบหน้าจะมาทำ GIN Framework และจะเขียนต่อไปจนไปถึง deploy ขึ้น aws lambda จนไปถึงทำ microservices ผ่าน api gateway รอติดตามได้เลยครับ

( CR. ธำรงค์ ไชยวงค์ )

--

--

No responses yet