0Pricing
Go Academy · บทเรียน

อินเทอร์เฟซ Stringer

กำหนดวิธีพิมพ์ของชนิดเอง

อินเทอร์เฟซ Stringer เป็นบทเรียน Go Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Go Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน

การพิมพ์โครงสร้างตามค่าเริ่มต้น

ตามค่าเริ่มต้น การพิมพ์โครงสร้างด้วย %v จะแสดงฟิลด์ดิบของโครงสร้าง ซึ่งเหมาะสำหรับการดีบัก แต่อาจไม่ได้อ่านง่ายสำหรับผู้อ่านเสมอไป

package main

import "fmt"

type Color struct{ R, G, B int }

func main() {
    c := Color{255, 0, 0}
    fmt.Println(c)
}

อินเทอร์เฟซ Stringer

อินเทอร์เฟซ fmt.Stringer มีเมธอดหนึ่งรายการ:

  • String() string

ประเภทใดก็ตามที่กำหนดเมธอดนี้จะควบคุมวิธีแสดงผลของประเภทนั้นเมื่อพิมพ์

package main

import "fmt"

type Greeting struct{ Name string }

func (g Greeting) String() string {
    return "Hello, " + g.Name
}

func main() {
    fmt.Println(Greeting{"Ada"})
}

นำไปใช้โดยอัตโนมัติ

เมื่อประเภทมีเมธอด String() ทั้ง Println, Printf ที่ใช้ %v หรือ %s และฟังก์ชันที่เกี่ยวข้องจะเรียกใช้เมธอดนี้โดยอัตโนมัติ

package main

import "fmt"

type Greeting struct{ Name string }

func (g Greeting) String() string {
    return "Hi " + g.Name
}

func main() {
    g := Greeting{"Bob"}
    fmt.Printf("%s and %v\n", g, g)
}

การจัดรูปแบบภายใน String()

สร้างผลลัพธ์ด้วย fmt.Sprintf เพื่อให้ได้การแสดงผลที่สะอาดและกำหนดเองได้

package main

import "fmt"

type Color struct{ R, G, B int }

func (c Color) String() string {
    return fmt.Sprintf("rgb(%d, %d, %d)", c.R, c.G, c.B)
}

func main() {
    fmt.Println(Color{255, 128, 0})
}

Stringer กับประเภทที่ตั้งชื่อ

Stringer ไม่ได้มีไว้สำหรับโครงสร้างเท่านั้น ประเภทที่ตั้งชื่อใด ๆ แม้แต่ประเภทที่มีพื้นฐานเป็น int ก็สามารถทำให้สอดคล้องกับอินเทอร์เฟซนี้ได้ นี่คือรูปแบบ enum แบบคลาสสิก

package main

import "fmt"

type Day int

func (d Day) String() string {
    names := []string{"Mon", "Tue", "Wed"}
    return names[d]
}

func main() {
    fmt.Println(Day(1))
}

ค่าแจกแจงที่แสดงผลได้อ่านง่าย

ใช้ iota ร่วมกับ Stringer เพื่อให้ค่าคงที่แสดงเป็นชื่อที่อ่านได้แทนตัวเลข

package main

import "fmt"

type State int

const (
    Idle State = iota
    Running
    Done
)

func (s State) String() string {
    return []string{"Idle", "Running", "Done"}[s]
}

func main() {
    fmt.Println(Running)
}

ตัวรับค่าเทียบกับตัวรับพอยน์เตอร์

หาก String() ใช้ตัวรับค่า ทั้งค่าและพอยน์เตอร์จะแสดงผลได้อย่างเหมาะสม แต่ถ้าใช้ตัวรับพอยน์เตอร์ จะมีเพียงพอยน์เตอร์เท่านั้นที่เรียกใช้เมธอดนี้

package main

import "fmt"

type Tag struct{ Name string }

func (t Tag) String() string { return "#" + t.Name }

func main() {
    t := Tag{"go"}
    fmt.Println(t)
    fmt.Println(&t)
}

หลีกเลี่ยงการเรียกซ้ำไม่รู้จบ

อย่าเรียก fmt.Sprintf("%v", t) กับประเภทเดียวกัน ภายใน String() ของประเภทนั้นเอง เพราะจะเรียก String() ซ้ำไปเรื่อย ๆ ให้จัดรูปแบบฟิลด์โดยตรง

package main

import "fmt"

type Money struct{ Cents int }

func (m Money) String() string {
    return fmt.Sprintf("$%.2f", float64(m.Cents)/100)
}

func main() {
    fmt.Println(Money{1050})
}

Stringer ในสไลซ์

เมื่อคุณพิมพ์สไลซ์ของค่าที่สอดคล้องกับ Stringer แต่ละองค์ประกอบจะถูกจัดรูปแบบด้วยเมธอด String() ขององค์ประกอบนั้น

package main

import "fmt"

type Tag struct{ Name string }

func (t Tag) String() string { return "#" + t.Name }

func main() {
    tags := []Tag{{"go"}, {"web"}}
    fmt.Println(tags)
}

การใช้ในฐานะอินเทอร์เฟซ

คุณสามารถเก็บค่า Stringer ใด ๆ ไว้ในตัวแปร fmt.Stringer และเรียก String() ผ่านอินเทอร์เฟซได้

package main

import "fmt"

type City struct{ Name string }

func (c City) String() string { return "City of " + c.Name }

func main() {
    var s fmt.Stringer = City{"Oslo"}
    fmt.Println(s.String())
}

เหตุใดจึงสำคัญ

การทำให้ประเภทสอดคล้องกับ Stringer ช่วยให้ได้เอาต์พุตที่สะอาดทุกครั้งที่มีการพิมพ์หรือบันทึกประเภทนั้น โดยไม่ต้องเขียนโค้ดจัดรูปแบบเพิ่มเติมในแต่ละจุดที่เรียกใช้

package main

import "fmt"

type Temp float64

func (t Temp) String() string {
    return fmt.Sprintf("%.1f°C", float64(t))
}

func main() {
    fmt.Println(Temp(21.5))
}

ตรวจสอบอย่างรวดเร็ว

ประเภทต้องกำหนดเมธอดใดจึงจะสอดคล้องกับ fmt.Stringer

สรุปทบทวน: อินเทอร์เฟซ Stringer

คุณได้เรียนรู้การปรับแต่งการพิมพ์แล้ว:

  • กำหนด String() string เพื่อให้สอดคล้องกับ fmt.Stringer
  • fmt จะเรียกใช้เมธอดนี้โดยอัตโนมัติสำหรับ %v และ %s
  • เหมาะสำหรับ enum แต่ควรหลีกเลี่ยงการใช้ %v แบบเรียกซ้ำกับประเภทเดียวกัน
package main

import "fmt"

type Level int

func (l Level) String() string {
    return []string{"low", "mid", "high"}[l]
}

func main() {
    fmt.Println(Level(2))
}

คำถามที่พบบ่อย

บทเรียน “อินเทอร์เฟซ Stringer” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “อินเทอร์เฟซ Stringer” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Go Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Go Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “อินเทอร์เฟซ Stringer”

กำหนดวิธีพิมพ์ของชนิดเอง คุณปฏิบัติ Go Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Go Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Go Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “อินเทอร์เฟซ Stringer” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Go Academy นี้ได้ไหม

ได้ บทเรียน Go Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เวิร์บของ Printf
  2. Sprintf และ Fprintf
  3. อินเทอร์เฟซ Stringer
  4. การสแกนข้อมูลนำเข้า
← กลับไปที่ Go Academy