Shall we Go ตอนที่ 6 – Function

เราเรียนรู้ Go กันมาหลายตอนแล้ว คิดว่าคงจะเริ่มคุ้นเคยกับภาษานี้บ้างแล้ว โดยเฉพาะ Function เราเคยเขียน main() และ Uppercase() จากตอนก่อนๆ ตอนนี้เราจะมาดูเรื่อง Function เพิ่มเติมกัน

โครงสร้างเบื้องต้นของ Function
อธิบายด้วย Code จะเข้าได้ง่ายกว่า

func divide(num int) float64 {
	return float64(num) / 2
}

จาก Code ข้างต้น:

  • Function นี้ชื่อ divide
  • Parameter มี 1 ตัว ชื่อ num มี type เป็น int
  • Return value มี 1 ตัว type เป็น float64
  • Logic การทำงานก็เอา num มาหารด้วย 2 แล้ว return ค่าไป

Multiple Parameters
ปรับ Code ให้สามารถรับ Parameter เป็น 2 ตัว เพื่อบอกว่าจะหารด้วยจำนวนเท่าไหร่

func divide(num int, by int) float64 {
	return float64(num) / float64(by)
}

Multiple Return Values
ปรับ Code ให้สามารถ return ค่าเป็น 2 ตัว เพื่อบอกว่า function ทำงานมี error หรือไม่

func divide(num int, by int) (float64, bool) {
	if by == 0 {
		return 0, true
	}
	return float64(num) / float64(by), false
}

Named Return Values
ปรับ Code ให่อ่านง่ายขึ้นด้วยการกำหนดชื่อตัวแปรที่จะ return

func divide(num int, by int) (result float64, err bool) {
	if by == 0 {
		err = true
		return
	}
	result = float64(num) / float64(by)
	return
}

ข้อสังเกตุ กำหนดชื่อตัวแปรที่จะ return เราสามารถเขียนแค่ return เฉยๆ โดยมันจะ return ค่าในตัวแปรชื่อนั้นๆโดยอัตโนมัติ หรือจะเขียน return แบบเดิมๆก็ได้ เช่น return 0, false

Exported Function
จาก Code ปัจจุบัน ถ้าลองเอา function นี้ไปอยู่ใน main package และเขียน main() มาเรียกใช้ใน ก็จะทำงานได้ปกติ แต่ถ้าเราแยก function นี้ออกจาก main package และ import package นั้นเข้ามาเพื่อให้ main() เรียกใช้
main.go

1
2
3
4
5
6
7
8
9
10
11
12
package main
 
import (
	"fmt"
 
	"github.com/shall-we-go/math"
)
 
func main() {
	fmt.Println(math.divide(9, 2))
	fmt.Println(math.divide(9, 0))
}

จะเกิด error ตอนเรียก $ go run main.go ประมาณนี้

# command-line-arguments
./main.go:10:14: cannot refer to unexported name math.divide
./main.go:10:14: undefined: math.divide
./main.go:11:14: cannot refer to unexported name math.divide
./main.go:11:14: undefined: math.divide

เนื่องจาก math.divide ยังไม่ได้ถูก export เพื่อให้ package อื่นเรียกใช้ วิธีแก้คือเปลี่ยนชื่อ function เป็นขึ้นต้นด้วยตัวใหญ่ Divide()
divide.go

1
2
3
4
5
6
7
8
9
10
package math
 
func Divide(num int, by int) (result float64, err bool) {
	if by == 0 {
		err = true
		return
	}
	result = float64(num) / float64(by)
	return
}

main.go

1
2
3
4
5
6
7
8
9
10
11
12
package main
 
import (
	"fmt"
 
	"github.com/shall-we-go/math"
)
 
func main() {
	fmt.Println(math.Divide(9, 2))
	fmt.Println(math.Divide(9, 0))
}

Variadic Function
เราสามารถเขียน function เพื่อให่รับ parameter ที่มีจำนวนไม่แน่นอนได้ (แต่ต้องเป็น type เดียวกัน หรือ type interface{} ซึ่งจะอธิบายในตอนต่อๆไป)

func Sum(nums ...int) int {
	total := 0
	for _, num := range nums {
		total += num
	}
	return total
}

โดยมีเงือนไขว่าต้องเป็น parameter ตัวท้ายสุดใน function นั้น เช่น SomeFunction1(text ...string) หรือ SomeFunction2(num int, text ...string) แต่แบบนี้จะไม่ได้ SomeFunction3(text ...string, num int)

Function Literal หรือ Closure หรือ Anonymous Function
เราสามารถเขียน Anonymous Function หลายแบบดังนี้

someFunc := func(a int, b int) int {
	return a + b
}
fmt.Println(someFunc(1, 2))
someResult := func(a int, b int) int {
	return a + b
}(1, 2)
fmt.Println(someResult)
func toDoSomething(callback func()) {
	fmt.Println("say something first")
	callback()
}
 
func main() {
	toDoSomething(func() {
		fmt.Println("say something later")
	})
}

ติดตามต่อตอนหน้า มาดูเรื่อง Variable กัน

Leave a Reply

Your email address will not be published. Required fields are marked *