ข้ามไปยังเนื้อหา

fmt, strings และ strconv

Package fmt คือจุดเริ่มต้นของ output เกือบทั้งหมดใน Go มีสามฟังก์ชันหลักที่ครอบคลุมกรณีการใช้งานส่วนใหญ่:

  • fmt.Println(args...) — พิมพ์แต่ละ argument คั่นด้วยช่องว่าง แล้วขึ้นบรรทัดใหม่
  • fmt.Printf(format, args...) — พิมพ์โดยใช้ format string ที่มี verb
  • fmt.Sprintf(format, args...) — คืนค่า string ที่ฟอร์แมตแล้วแทนที่จะพิมพ์
Verbความหมาย
%vการแสดงผลแบบ default
%+vStruct พร้อมชื่อ field
%#vการแสดงผลแบบ Go syntax
%TType ของค่า
%dเลขฐานสิบ (decimal integer)
%sString (ไม่มีเครื่องหมายคำพูด)
%qString ในเครื่องหมายคำพูดคู่พร้อม Go escaping
%fทศนิยม (floating-point decimal)
type Person struct { Name string; Age int }
p := Person{"Alice", 30}
fmt.Printf("%v\n", p) // {Alice 30}
fmt.Printf("%+v\n", p) // {Name:Alice Age:30}
fmt.Printf("%#v\n", p) // main.Person{Name:"Alice", Age:30}
fmt.Printf("%T\n", p) // main.Person

Package strings ให้บริการฟังก์ชันสำหรับการค้นหา แยก รวม และแปลง string ใน Go นั้น string เป็น immutable UTF-8 byte sequence ดังนั้นฟังก์ชันเหล่านี้จะคืนค่า string ใหม่แทนที่จะแก้ไข in-place

s := "hello, world"
strings.Contains(s, "world") // true
strings.HasPrefix(s, "hello") // true
strings.Split(s, ", ") // ["hello" "world"]
strings.Join([]string{"a","b"}, "-") // "a-b"
strings.ReplaceAll(s, "l", "L") // "heLLo, worLd"
strings.ToUpper(s) // "HELLO, WORLD"
strings.TrimSpace(" hi ") // "hi"

เมื่อสร้าง string จากหลายส่วนในลูป ให้ใช้ strings.Builder แทน += เพราะ += จะสร้าง string ใหม่ทุกครั้งที่วนซ้ำ ส่วน Builder เขียนลงใน buffer ที่ขยายตัวได้และ allocate string สุดท้ายเพียงครั้งเดียว

var b strings.Builder
for i := 0; i < 5; i++ {
fmt.Fprintf(&b, "item%d ", i)
}
result := strings.TrimSpace(b.String()) // "item0 item1 item2 item3 item4"

strconv แปลงระหว่าง string และ numeric type ฟังก์ชันที่พบบ่อยที่สุด:

n, err := strconv.Atoi("42") // string → int
s := strconv.Itoa(42) // int → string
f, err := strconv.ParseFloat("3.14", 64) // string → float64
b, err := strconv.ParseBool("true") // string → bool

Atoi และ ParseFloat คืนค่า (value, error) เพราะ input อาจไม่ใช่ตัวเลขที่ถูกต้อง ควรตรวจสอบ error ก่อนใช้ค่าเสมอ

package main
import (
"fmt"
"strconv"
"strings"
)
type Person struct {
Name string
Age int
}
func main() {
// fmt verbs
p := Person{Name: "Alice", Age: 30}
fmt.Printf("%v\n", p)
fmt.Printf("%+v\n", p)
fmt.Printf("%#v\n", p)
fmt.Printf("%T\n", p)
fmt.Printf("%d %s %q\n", 42, "hello", "world")
// Sprintf builds a string
s := fmt.Sprintf("Name: %s, Age: %d", p.Name, p.Age)
fmt.Println(s)
// strings package
text := " Go is great "
fmt.Println(strings.TrimSpace(text))
fmt.Println(strings.Contains(text, "great"))
fmt.Println(strings.ToUpper(strings.TrimSpace(text)))
words := strings.Split("one,two,three", ",")
fmt.Println(words)
fmt.Println(strings.Join(words, " | "))
fmt.Println(strings.ReplaceAll("aabbcc", "b", "x"))
// strings.Builder — efficient concatenation
var b strings.Builder
for i := 0; i < 3; i++ {
fmt.Fprintf(&b, "item%d ", i)
}
fmt.Println(strings.TrimSpace(b.String()))
// strconv
n, err := strconv.Atoi("123")
if err == nil {
fmt.Println(n + 1)
}
fmt.Println(strconv.Itoa(456))
f, err := strconv.ParseFloat("3.14", 64)
if err == nil {
fmt.Printf("%.2f\n", f)
}
}
สิ่งที่ได้ประโยชน์ต้นทุน
fmt.Sprintfflexible string formattingallocate string ใหม่ทุกครั้ง
fmt.Fprintf(w, …)write to any io.Writerต้องระวัง error return
strings.Builderefficient string concatenationต้อง Reset() ถ้า reuse
%v / %+v / %#vinspect any valuereflect-based — ช้ากว่า explicit conversion
  • fmt.Println เหมาะสำหรับ production logging — ใช้ structured logger (log/slog, zap) แทนใน production — fmt ไม่รองรับ log level, structured fields, หรือ JSON output
  • string concatenation ด้วย + เร็วกว่า fmt.Sprintf — ขึ้นกับจำนวน concatenation — strings.Builder เร็วที่สุดสำหรับหลาย pieces ใน loop
  • %d กับ %v ต่างกันมาก — %d explicit สำหรับ integer, %v generic แต่ผลลัพธ์เหมือนกันสำหรับ int; ต่างกันสำหรับ struct
  • rune กับ byte เหมือนกัน — byte คือ uint8 (1 byte), rune คือ int32 (1-4 bytes สำหรับ Unicode codepoint)

💡 ตัวอย่างจากของจริง

Kubernetes: kubectl output ใช้ fmt.Fprintf + tabwriter สำหรับ table formatting ที่ align column อัตโนมัติ

Prometheus: metric label string construction ใช้ fmt.Sprintf — เช่น http_requests_total{method="GET",path="/api"}

Go HTTP server: error response ใช้ fmt.Sprintf สร้าง message แล้วส่งผ่าน http.Error() ซึ่งรับ string

Format verb ใดที่พิมพ์ struct พร้อมชื่อ field?
strings.ReplaceAll("aabbcc", "b", "x") คืนค่าอะไร?
ทำไม strings.Builder จึงเป็นที่นิยมกว่า += ในการสร้าง string ในลูป?
strconv.Atoi("42") คืนค่าประเภทใด?