Golang Basic EP2 | ตัวแปรและ zero value
Published: 2024-07-05 11:46:47

ในภาษาGo ตัวแปรสามารถแบ่งออกเป็นชนิดต่างๆ ได้หลายประเภท และแน่นอนว่าผมเองก็ไม่เคยใช้มันหมดทุกตัวหรอกนะ

ตัวเลข (Integer Types)
```
- int
- int8
- int16
- int32
- int64
- uint
- uint8
- uint16
- uint32
- uint64
- uintptr
```

ตัวเลขทศนิยม (Floating Point Types)
```
- float32
- float64
```

ตัวเลขเชิงซ้อน (Complex Types)
```
- complex64
- complex128
```

บูลีน (Boolean)
```
- bool
```

อักขระและสตริง (Character and String Types)
```
- string
- rune (alias สำหรับ int32)
- byte (alias สำหรับ uint8)
```

> _ดูเพิ่มเติมได้ที่: [go.dev](https://go.dev/ref/spec#Types)_

## ซึ่งการประกาศตัวแปรในภาษาGo นั้น เขียนได้ 2 แบบคือ
- เติมคำว่า `var` ข้างหน้าชื่อตัวแปรพร้อมกับ type ข้างหลังเช่น `var a1 string` นั่นหมายความว่า เราได้สร้างตัวแปรที่ชื่อว่า a1 ที่มี type เป็น string ขึ้นมาแล้วนะ ซึ่งมีค่า zero value คือ empty string

> เอ๊ะ แล้ว zero value มันคืออะไร ? 
> zero value ก็คือค่า default ของ type นั้นๆ เมื่อเราประกาศตัวแปรแบบไม่ได้ระบุค่ามันจะมีค่าเป็น default value เสมอ ซึ่ง string มีค่าเป็น "" หรือที่เรียกกันว่า empty, int ก็จะมีค่าเป็น 0, bool มีค่าเป็น false, slice มีค่าเป็น nil อะไรประมาณนี้

กลับมาเรื่องการประกาศตัวแปร ถ้าเราต้องการประกาศตัวแปรพร้อมกับระบุค่าเราก็จะเขียนได้แบบนี้ `var a1 string = "Hello world"` หรือ `var a1 = "Hello world"` ซึ่งแบบหลัง เราไม่ต้องระบุ type ก็ได้ เพราะภาษาGo มันเดาค่าที่คุณระบุเข้าไปได้

- การประกาศตัวแปรอีกแบบ เราเรียกมันว่า `shorthand` ซึ่งเขียนได้แบบนี้คือ `a1 := ""` หรือถ้าอยากระบุค่า ก็แค่เขียนแบบนี้ `a1 := "Hello world"`

## แล้ว 2 แบบนี้มันต่างกันยังไง?

- การประกาศแบบใช้ `var` มันสามารถประกาศนอก function ได้ เป็น `global variable` (ตัวแปรที่ function หรือ package ใดๆ ก็สามารถเรียกใช้ได้) ในขณะที่การประกาศแบบ `shorthand` มันไม่สามารถประกาศนอก function ได้ ต้องเขียนใน function เท่านั้น

- การประกาศแบบใช้ var สามารถที่จะ `ไม่ระบุค่าได้` กล่าวคือ หากคุณประกาศ boolean แบบ `var a1 bool` คุณก็จะได้รับค่า zero value ที่เป็น false เลย ในขณะที่การประกาศแบบ `shorthand` คุณต้องระบุค่าให้มันเสมอ นั่นก็คือ `a1 := false` 

เพื่อให้เห็นภาพ ให้คุณลองดูโค้ดนี้ดู

![how to declear variable in golang](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9rejr1qfqac0zdmbsu2e.png)

ลองสังเกตุดีๆ จะเห็นว่า ต้วแปร a2 ที่อยู่นอก func main กับ a2 ที่อยู่ใน main ทำไมมันถึงสามารถใช้ชื่อเดียวกันได้ นั่นก็เพราะว่า มันทำงานกันคนละ scope มันคือคนละตัวกัน ถ้าคุณประกาศตัวแปรที่ชื่อ a2 ใน function main คุณจะไม่มีทางใช้ตัวแปร a2 ที่อยู่นอก main ได้ แต่ถ้าหากคุณต้องการใช้ตัวแปร a2 ที่อยู่ข้างนอก main ละ ต้องทำยังไง? คำตอบก็คือดูในรูปนี้

![variable](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/751lqmtpppo03ytczuuz.png)

ที่นี่ลองพิจารณาดูรูปข้างล่างนี้ดูว่าทำไมถึง error ล่ะ
![variable](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pvlfw0mkhujwqc1oskne.png)

> คำตอบก็คือ คอมพิวเตอร์มันอ่านโค้ด มันอ่านจากบนลงล่างมาเรื่อยๆ
> บรรทัดที่ 9 บอกว่า a2 เป็น `int` นะ (จากการระบุค่า 10 เข้าไป) เมื่อมาถึงบรรทัดที่ 10 เราประกาศ `var a3 bool = a2` นั่นหมายความว่า มันจะไปเอาค่าจาก a2 บรรทัดข้างบนล่าสุด นั่นก็คือบรรทัดที่ 9 ใส่ให้กับ a3 ซึ่งมันจะเป็น `var a3 bool = 10` หรือเปล่า? 

เปล่า มันไม่สามารถเป็นแบบนั้นได้ เพราะภาษาGo เป็นภาษาที่คุณประกาศ type อะไรมา คุณต้องระบุค่าเข้าไปให้ถูกต้องกับ type ดังนั้นจากตัวอย่างนี้มันเลยระบุไม่ได้ เพราะ a3 เราประกาศเป็น boolean ซึ่งค่าของ boolean คือ `true` กับ `false` ส่วน `10` นั้นเป็นตัวเลข มันเลยเกิด error นั่นเองง

## กลับมาที่ var กับ := แล้วเราจะใช้แบบไหนดีล่ะ? ผมสรุปให้ว่า

```
การประกาศตัวแปรแบบใช้ var นั้น
- เหมาะสำหรับการประกาศตัวแปรในระดับ package
- ใช้เมื่อคุณต้องการระบุชนิดข้อมูลอย่างชัดเจน
- ใช้เมื่อคุณต้องการประกาศตัวแปรโดยไม่ต้องกำหนดค่าเริ่มต้น
```

```
ส่วนการประกาศตัวแปรแบบใช้ := นั้น
- เหมาะสำหรับการประกาศตัวแปรภายในฟังก์ชัน
- สะดวกและรวดเร็วในการเขียนโค้ด โดยไม่ต้องระบุชนิดข้อมูล
- ใช้เมื่อคุณต้องการประกาศและกำหนดค่าเริ่มต้นในบรรทัดเดียว
```

แต่ทั้งนี้ทั้งนั้น มันก็แล้วแต่ความสะดวกของคุณเองแหละ แต่ใช้ให้ถูกหลักมันก็เป็นสิ่งที่ดี :)