บันทึก Golang #01 Receiver ต่างกับ Function อย่างไร
โปรดจงเรียกข้าว่า method in type
บทความนี้ผมตั้งใจจะบันทึกเรื่องราวชวนน่าค้นหาในภาษา Go เก็บไว้ ซึ่งแต่ละบทความจะไม่เน้น Basic Go มากนัก เพราะ หาอ่านได้หลายที่ โดยเนื้อหาที่ผมเน้น คือ เจาะลึกลงไป เพื่อให้เห็นว่าภาษา Go นั้น แตกต่าง หรือ มีแนวคิดอย่างไร เมื่อเทียบกับ ภาษาอื่นๆ และในวันนี้จะขอเริ่มจากเรื่องราวของ …“Receiver ต่างกับ Function อย่างไร?”…
สิ่งที่เราต้องรู้คือ Go ไม่มี Class
นั่นหมายความว่า เราจะไม่มี method ที่สามารถเข้าถึง element ใน object เราได้
เช่น การเข้าถึง member ใน object ด้วย keyword this ใน JavaScript
const profile = { firstname: 'foo', lastname: 'bar', getFullname: () => `${this.firstname} ${this.lastname}`
};profile.getFullname(); // "foo bar"
แล้วถ้าหากเราต้องการ concept นี้ ให้ประยุกต์ใช้กับภาษา Go จะทำได้ไหม คำตอบ คือ ได้ครับ เราเรียกวิธีการนั้นว่า “Receiver”
Receiver คืออะไร?
Go does not have classes. However, you can define methods on types.
A method is a function with a special receiver argument.
จากประโยค ข้างบน method != function ลองดูที่นี่ เพื่อเห็นภาพมากขึ้น
Function คือ กลุ่มของ Code มี/ไม่มี parameter และ มี/ไม่มี return value
Method คือ เหมือนกับ function แต่จะเกี่ยวของกับ scope ของ object/class หรือ อยู่ภายใต้ object
Method ใน Go คือ function ที่มี receiver argument
การที่จะให้ Method ผูกติดเฉพาะ member ที่เราระบุนั้น เราจำเป็นต้องสร้างสิ่งที่เรียกว่า Receiver ขึ้นมา โดยจะผูกติดกับ type ที่เรากำหนดขึ้น
วิธีการสร้าง Receiver method
กำหนด type
type Profile struct { firstname string lastname string}
สร้าง Receiver method ที่มี argument type Profile
func (p Profile) getFullname() string { return p.firstname + " " + p.lastname}
จากโค๊ดข้างบนเราได้สร้าง receiver method ขึ้นมา โดยมี argument p ซึ่งมี type Profile และเมื่อมีการเรียก receiver method คนที่เรียกจะได้คุณสมบัติ getFullname() ติดไปด้วย
Binding receiver method เข้าตัวแปร
func main() { f := Profile{"Teerapong", "Singthong"} fmt.Println(f.getFullname())}
ทำการสร้างตัวแปร f ขึ้นมา โดยกำหนดให้มี type Profile และทำการกำหนดค่า ซึ่งจะเห็นได้ว่า ตัวแปร f สามารถใช้ . (dot reference) หา method getFullname() ได้ คล้ายกับภาษาที่รองรับ object
ลองดูอีกตัวอย่าง
ถ้าหากมีการ เรียก receiver method ผ่านการกำหนด type reat เช่น
cal := rect{100, 200}// ตัวแปร cal จะมี area() และ perim() ติดมาด้วย
สรุป การใช้ method receiver คือ การให้ golang มีคุณสมบัติคล้ายกับการทำงานแบบ keyword this หรือ เป็นการ binding method เข้า type ที่เรากำหนดนั่นเอง
หรือจะมองว่า method in type ก็คงไม่ผิดนัก
อย่าสับสนระหว่าง method receiver กับ function นะครับ เพราะจริงๆ แล้วคนละวิธีการกันเลย และมีจุดประสงค์ต่างกัน จำไว้เลยว่า method receiver จะมี scope manipulate data ได้กับแค่ type ที่มันทำงานด้วยเท่านั้น
— golf