Go Variable , Type and Type Inference
Tags: go
Published: 2020-07-01 23:58:51

โพสต์นี้ไม่ได้จะมาอธิบาย type ของ Go ทุกตัวที่ติดมากับภาษา แต่จะอธิบายหลักการคร่าวๆของเรื่อง variable, type และ type inference ของ Go

## Variable
เริ่มแรก Variable ตัวแปรถูกสร้างมาเพื่อให้เราสร้างที่เก็บข้อมูลที่เราใช้ระหว่างประมวลผลข้อมูลในโปรแกรม พร้อมกับตั้งชื่อให้ข้อมูลชุดนั้นด้วย ซึ่งถ้าเราไม่สร้างภาษาที่ใช้ Variable ที่ให้เราตั้งชื่อสำหรับข้อมูลที่เก็บอยู่ในหน่วยความจำแล้วนั้น เราก็ต้องไปนั่งจำ memory address แบบการใช้ภาษาเครื่องเขียนโดยตรง ซึ่งไม่สนุกแน่นอน

## Type
ส่วน Type นั้น ช่วยทั้งคนเขียนคนอ่านโค้ดและช่วยตัว compiler เองด้วย คือ Type นั้นช่วยให้คนเขียน จำกัดข้อมูลที่จะถูกกำหนดให้ตัวแปรได้ ทำให้ลดการผิดพลาดที่เกิดจากการใส่ข้อมูลผิดประเภทลงไปตอน runtime เนื่องจากความพิดพลาดพวกนี้จะถูก compiler ตรวจสอบไว้หมดตั้งแต่ตอน compile time และคนอ่านโค้ดก็จะเข้าใจได้ว่าตัวแปรนั้นเก็บอะไรได้บ้าง นอกจากนั้น compiler ก็ใช้ข้อมูลจาก Type เนี่ยแหละในการแปลงจากภาษาที่เราเขียน ไปเป็นโค้ด machine code ที่ใช้พื้นที่หน่วยความจำได้เหมาะสมกับประเภทข้อมูล และจัดการ optimize ให้ดีที่สุดสำหรับแต่ละ Type

นอกจากนั้น Type ยังเป็นข้อมูลที่ช่วยให้สร้างเครื่องมือเขียนโค้ดอย่าง IDE ได้ง่ายขึ้นด้วยเพราะมันจะช่วยให้หาได้ว่า method ของ Type นี้มีอะไรบ้างทำให้ IDE สร้าง autocomplete ได้ง่ายขึ้น

## Go Variable
กลับมาที่ Go ซึ่งก็เป็นภาษาหนึ่งที่ออกแบบให้เราสร้างตัวแปรเก็บข้อมูลโดยที่แต่ละตัวแปรมีประเภทข้อมูลของตัวเอง เช่น 

```go
var name string
name = "Weerasak"
var age int
age = 35
```

คือเราใช้ var เป็น keyword ในการสร้างตัวแปร ตามด้วยชื่อตัวแปร และประเภทข้อมูล ซึ่งถ้าเราประกาศตัวแปรเฉยๆแบบโค้ดด้านบนนั้นแต่ละตัวแปรใน Go จะมีค่า zero value (หรือ default value) ของแต่ละประเภทอยู่เช่น string มี zero value คือ `""` ส่วน int มี zero value เป็น `0`

หลังจากนั้นเราก็ใช้ `=` เป็นการกำหนดค่าให้ตัวแปร ซึ่งก็หมายถึงกำหนดค่าลงหน่วยความจำที่เราอ้างอิงด้วยชื่อตัวแปรที่เราตั้งไว้นั่นเอง

นอกจากเขียนแบบด้านบนคือประกาศตัวแปรก่อน แล้วเอาไปกำหนดค่านั้น ถ้าเราต้องการสร้างตัวแปร พร้อมค่าเริ่มต้นค่าอื่นที่ไม่ได้ต้องการให้เป็น zero value เราสามารถกำหนดค่าพร้อมประกาศตัวแปรได้ในบรรทัดเดียวได้เลยแบบนี้

```go
var name string = "Weerasak"
var age int = 35
```

## Go Type Inference
ทีนี้นอกจากการประกาศตัวแปรพร้อมระบุชื่อ type ให้กับตัวแปรแล้วนั้น Go มีกลไกที่ชื่อว่า type inference โดยที่ Go compiler สามารถรู้ type ของข้อมูลได้โดยดูจาก literal ที่กำหนดค่าลงไปให้ตัวแปร ( เรื่อง literal อ่านต่อได้ที่นี่ https://dev.to/iporsut/literal-2m3d ) ทำให้เราย่อโค้ดด้านบนเหลือแบบนี้ได้

```go
var name = "Weerasak"
var age = 35
```

เพราะว่า Go สามารถ infer type จาก literal อย่าง "Weerasak" ว่าเป็น string และ literal อย่าง 35 ว่าเป็น int ได้นั่นเอง

สรุปก็คือถ้าเราสร้างตัวแปรโดยไม่ระบุ type แต่กำหนดค่าให้ตัวแปรลงไปเลยแล้วนั้น Go compiler จะรู้ type ของตัวแปรได้เองจากค่าที่เรากำหนดให้นั่นเอง

สุดท้ายสำหรับตัวแปรที่เป็น local variable ที่ประกาศในฟังก์ชัน เราสามารถเขียนให้สั้นลงโดยใช้ operator `:=` ช่วยได้ทำให้ไม่ต้องเขียน `var` ด้านหน้าชื่อตัวแปร จากโค้ดด้านบนก็จะเหลือแบบนี้

```go
name := "Weerasak"
age := 35
```

ย้ำอีกที `:=` ใช้ได้แต่กับตัวแปรที่สร้างภายใต้ function เท่านั้น

## สรุป
Variable ตัวแปรเกิดมาเพื่อให้คนเขียนโค้ดสร้างที่เก็บข้อมูลในโปรแกรมตัวเองพร้อมตั้งชื่อที่จะทำให้คนอ่านต่อไปเข้าใจง่ายว่าข้อมูลเก็บอะไร

Type ประเภทข้อมูลเกิดมาเพื่อให้คนเขียนจำกัดค่าที่เป็นไปได้ในการเก็บทำให้ลดข้อผิดพลาดในการเขียน และ ทำให้คนอ่านรู้ได้ทันทีว่าจะทำอะไรกับตัวแปรประเภทนั้นได้ และทำให้สร้างเครื่องมืออย่าง IDE เพื่อช่วย guide สิ่งที่ทำกับตัวแปรนั้นๆได้เช่นสร้าง autocomplete ให้ได้ นอกจากนั้นก็ช่วย compiler ให้แปลงเป็น machine code ที่เหมาะสมในการจัดการหน่วยความจำนั่นเอง

Type inference ช่วยให้เราเขียนโค้ดได้สั้นลงโดยไม่จำเป็นต้องระบุชื่อประเภทข้อมูลของตัวแปรตลอด เพราะตัว literal หรือค่าที่เรากำหนดให้ตัวแปรนั้น compiler สามารถรู้ (infer) ได้อยู่แล้วว่าเป็นประเภทข้อมูลแบบไหน