ทำ forEach เลียนแบบ Java 8

Golang นั้นรองรับการเขียน Anonymous function มาอยู่แล้ว และสามารถใช้ function เป็น value ได้ คือทำตัวเป็น lambda ได้นั่นเอง ตัวอย่างเช่น

add := func(x, y int) int { return x+y; }

เราสามารถเรียกแบบนี้ได้

result := add(10, 20)

และจากที่ผมเขียนบอกไปว่า go นั้นมีการวนซ้ำในรูปแบบเท่านี้ http://golang.in.th/2015/01/08/for-loop/ ถ้าเรามีข้อมูลในลิสต์แบบนี้

members := []string {“John”, “Mike”, “Joe”}

เราสามารถวนซ้ำและแสดงค่าใน slice โดยใช้ for range ได้ดังนี้

for _, m := range members {

fmt.Println(m)

}

ทีนี้ผมเขียน blog อธิบายของใหม่ใน Java 8 ไปเรื่อง forEach ที่ใช้วนซ้ำใน List และเรียกใช้ lambda ที่ส่งเข้าไปโดยเอาแต่ละ element ของ List เป็น parameter ให้การเรียก lambda แต่ละครั้ง เลยมาลองใช้ความสามารถของ Go สร้างของแบบ forEach ดูบ้าง

ปกติถ้าเรามี members := []string {“John”, “Mike”, “Joe”} เราจะไม่สามารถเรียก method อะไรที่ตัวแปล members ได้ ถ้าเราต้องการสร้าง method แบบนี้ให้เราสร้าง type ใหม่โดยให้มีข้อมูลแบบเดียวกับ []string ดังนี้

type Members []string

หลังจากนั้นกำหนดค่า members ใหม่โดยแปลงเป็น Members ดังนี้

members := Members([]string {“John”, “Mike”, “Joe”})

และให้เราทำการเพิ่ม method ให้ Members ชื่อ forEach โดยให้รับค่าเป็น function ที่รับค่า string เข้าไปดังนี้

func (ms Members) forEach(lamb func(it string)) {
for _, m := range ms {
lamb(m)
}
}

จะเห็นว่าภายใน forEach เราก็ทำการวนด้วย for range เหมือนเดิม และใน for ให้เราทำการเรียกใช้ lamb โดยส่ง m ไปให้ เท่านี้เราก็สามารถใช้ได้แบบ forEach ใน java 8 แล้วสำหรับข้อมูลแบบ []string ตัวอย่างเต็มๆแบบนี้

package main

import (
	"fmt"
)

type Members []string

func (ms Members) forEach(lambda func(it string)) {
	for _, m := range ms {
		lambda(m)
	}
}

func main() {
	members := Members([]string{"John", "Mike", "Joe"})
	members.forEach(func(it string) { fmt.Println(it) })
}