go unicode เมื่อคิดถึง special characters

คำว่า special characters มันมีความไม่เท่ากันในแต่ละทีนะครับ อย่าลืมข้อนี้ บางทีแค่ $%& พวกนี้บางที่ก็เรียก special characters แล้ว มองบนหนึ่งทีแล้วไปต่อ
เนื่องจาก go นั้นทำงานกับ UTF-8 เป็น default ไม่เหมือนกับ c ที่มอง string เป็น char 8bits มาต่อกันเลย

เรามาดู package unicode ดีกว่าว่ามีอะไรให้ลอง

package main

import (
	"fmt"
	"unicode"

	"golang.org/x/text/runes"
	"golang.org/x/text/transform"
)


func main() {
	b := []byte{224, 184, 136, 224, 184, 136, 26}

	fmt.Println(b)
	fmt.Println(removeTransformer(b))
}

func removeTransformer(b []byte) []byte {
	t := transform.Chain(runes.Remove(runes.In(unicode.Cc)))
	nb, _, err := transform.Bytes(t, b)
	if err != nil {
		return b
	}
	return nb
}

 

 

จะเห็นว่ามีการใช้ package หลายตัวหน่อย
เริ่มจากการสร้างชุดข้อมูลที่มี จ จาน 2 ตัวต่อท้ายด้วย อะไรก็ไม่รู้ที่มี ascii เลข 26 ตัวนึง ทีนี้เราอยากจะเอามันออก ซึ่งโค้ดจะยาวๆหน่อย มาดูทีละตัว

unicode.Cc คือ constant ของ unicode ช่วงที่เป็น control characters ทั้งหมด ซึ่งเจ้า 26 ก็เป็นหนึ่งในนั้นที่เราอยากจะเอามันออก

runes.In คือการสร้างชุดของ rune ที่เราจะเอาออก ซึ่งก็คือเจ้าพวก control char

runes.Remove คือการบอกว่าจาก unicode ทั้งหมด ฉันจะไม่เอาเจ้าพวกนี้

transform.Chain คือการสร้างตัว transformer (ดนตรีมา….) ที่จะประกอบของตามลำดับที่ให้ไว้
transform.Bytes(t, b) สุดท้ายก็ส่งของเข้าไป แล้วมันก็จะคือของที่ไม่มี control char ออกมาให้
ผลลัพธ์ที่ได้ก็ลองรันกันดูครับ
ถ้าใครอยากเทส benchmark ก็ลองตามนี้ดู
package main

import "testing"

func BenchmarkUnicode(b *testing.B) {
	bb := []byte{224, 184, 136, 224, 184, 136, 26}

	for n := 0; n < b.N; n++ {
		removeTransformer(bb)
	}
}

 

ส่วนผลลัพธ์ก็ได้ประมาณนี้

goos: darwin
goarch: amd64
pkg: github.com/pallat/tis620
BenchmarkUnicode-4   	 3000000	       402 ns/op
PASS
ok  	github.com/pallat/tis620	1.633s

ยังไม่ได้พูดถึงการแปลง charset ยอดนิยมในอดีต TIS-620 มาเป็น UTF-8 ด้วย ไว้คราวหน้า ถ้าแฟนๆเรียกร้อง