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

การกำหนดและใช้งาน interface

การทำให้สอดคล้องโดยปริยายและ interface ว่าง

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

อินเทอร์เฟซคืออะไร

อินเทอร์เฟซใน Go คือชุดลายเซ็นของเมธอด ชนิดข้อมูลใดก็ตามที่มีเมธอดเหล่านั้นครบจะรองรับอินเทอร์เฟซโดยอัตโนมัติ — ไม่จำเป็นต้องใช้คีย์เวิร์ด implements แนวคิดนี้เรียกว่าการกำหนดชนิดข้อมูลตามโครงสร้างหรือการกำหนดชนิดแบบเป็ด

การประกาศอินเทอร์เฟซ

กำหนดอินเทอร์เฟซด้วยคีย์เวิร์ด type:

package main
import "fmt"

type Shape interface {
    Area() float64
    Perimeter() float64
}

type Circle struct{ Radius float64 }
func (c Circle) Area() float64      { return 3.14159 * c.Radius * c.Radius }
func (c Circle) Perimeter() float64 { return 2 * 3.14159 * c.Radius }

func main() {
    var s Shape = Circle{5}
    fmt.Printf("Area: %.2f\n", s.Area())
}

การรองรับโดยอัตโนมัติ

ไม่จำเป็นต้องประกาศเจตนา หากชนิดข้อมูลมีเมธอดที่ถูกต้อง ก็จะรองรับอินเทอร์เฟซโดยอัตโนมัติ:

package main
import "fmt"

type Greeter interface{ Greet() string }

type English struct{}
func (e English) Greet() string { return "Hello" }

type Spanish struct{}
func (s Spanish) Greet() string { return "Hola" }

func say(g Greeter) { fmt.Println(g.Greet()) }

func main() {
    say(English{})
    say(Spanish{})
}

อินเทอร์เฟซว่าง

interface{} (หรือ any ใน Go 1.18 ขึ้นไป) ได้รับการรองรับจากชนิดข้อมูลทุกชนิด ใช้เมื่อไม่ทราบชนิดข้อมูลขณะคอมไพล์:

package main
import "fmt"

func printAny(v any) { fmt.Printf("%T: %v\n", v, v) }

func main() {
    printAny(42)
    printAny("hello")
    printAny([]int{1,2,3})
}

ค่าอินเทอร์เฟซ

ค่าอินเทอร์เฟซประกอบด้วยสองสิ่ง ได้แก่ ชนิดข้อมูลรูปธรรมและค่ารูปธรรม อินเทอร์เฟซ nil จะมีทั้งสองส่วนเป็น nil:

package main
import "fmt"

type Animal interface{ Sound() string }
type Dog struct{}
func (d Dog) Sound() string { return "woof" }

func main() {
    var a Animal
    fmt.Println(a == nil) // true
    a = Dog{}
    fmt.Println(a == nil) // false
    fmt.Println(a.Sound())
}

การรองรับอินเทอร์เฟซหลายรายการ

ชนิดข้อมูลหนึ่งสามารถรองรับอินเทอร์เฟซหลายรายการพร้อมกันได้:

package main
import "fmt"

type Reader interface{ Read() string }
type Writer interface{ Write(string) }
type ReadWriter interface{ Reader; Writer }

type File struct{ content string }
func (f *File) Read() string       { return f.content }
func (f *File) Write(s string)     { f.content = s }

func main() {
    var rw ReadWriter = &File{}
    rw.Write("hello")
    fmt.Println(rw.Read())
}

การกำหนดค่าให้อินเทอร์เฟซ

อินเทอร์เฟซที่กว้างกว่าสามารถเก็บค่ารูปธรรมที่แคบกว่าได้ การกำหนดค่าระหว่างชนิดอินเทอร์เฟซจำเป็นต้องให้ชนิดรูปธรรมรองรับอินเทอร์เฟซทั้งสอง:

package main
import "fmt"

type Stringer interface{ String() string }

type Point struct{ X, Y int }
func (p Point) String() string { return fmt.Sprintf("(%d,%d)", p.X, p.Y) }

func main() {
    var s Stringer = Point{3, 4}
    fmt.Println(s.String())
}

กับดักอินเทอร์เฟซ nil

อินเทอร์เฟซที่ไม่เป็น nil แต่เก็บค่ารูปธรรมที่เป็น nil จะไม่เท่ากับ nil:

package main
import "fmt"

type MyErr struct{}
func (e *MyErr) Error() string { return "oops" }

func bad() error {
    var e *MyErr // nil pointer
    return e     // returns non-nil interface!
}

func main() {
    err := bad()
    fmt.Println(err == nil) // false — common gotcha
}

อินเทอร์เฟซช่วยให้ทดสอบได้

การกำหนดส่วนพึ่งพาเป็นอินเทอร์เฟซทำให้สามารถสลับการทำงานจริงเป็นการทำงานจำลองในชุดทดสอบได้:

package main
import "fmt"

type EmailSender interface{ Send(to, body string) error }

type MockSender struct{ Sent []string }
func (m *MockSender) Send(to, body string) error {
    m.Sent = append(m.Sent, to)
    return nil
}

func notify(s EmailSender, addr string) { s.Send(addr, "hello") }

func main() {
    mock := &MockSender{}
    notify(mock, "a@b.com")
    fmt.Println(mock.Sent) // [a@b.com]
}

รับอินเทอร์เฟซ คืนค่าโครงสร้าง

แนวทางปฏิบัติที่ดีของ Go คือ พารามิเตอร์ฟังก์ชันควรเป็นอินเทอร์เฟซเพื่อความยืดหยุ่น ส่วนชนิดค่าที่คืนควรเป็นชนิดรูปธรรม เพื่อให้ผู้เรียกทราบว่าจะได้รับอะไร:

package main

type Logger interface{ Log(string) }

type FileLogger struct{}
func (f *FileLogger) Log(s string) {}

func NewFileLogger() *FileLogger { // returns concrete
    return &FileLogger{}
}

func process(l Logger) {} // accepts interface

func main() { process(NewFileLogger()) }

ทำให้อินเทอร์เฟซมีขนาดเล็ก

ไลบรารีมาตรฐานของ Go นิยมใช้อินเทอร์เฟซขนาดเล็กมาก: io.Reader มีเมธอดเดียว และ io.Writer ก็มีเมธอดเดียว อินเทอร์เฟซขนาดเล็กนำไปประกอบใช้ได้ง่ายกว่าและสร้างการทำงานจำลองได้ง่ายกว่า

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

ชนิดข้อมูลจำเป็นต้องประกาศหรือไม่ว่ารองรับอินเทอร์เฟซ

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

ประเด็นสำคัญ:

  • อินเทอร์เฟซกำหนดพฤติกรรม ไม่ใช่ข้อมูล
  • การรองรับเกิดขึ้นโดยอัตโนมัติ — ไม่ต้องใช้คีย์เวิร์ด implements
  • อินเทอร์เฟซว่าง (any) รองรับชนิดข้อมูลทุกชนิด
  • ระวังกับดักอินเทอร์เฟซ nil
  • ทำให้อินเทอร์เฟซมีขนาดเล็กและมุ่งเน้นเฉพาะงาน

โจทย์ฝึกปฏิบัติ

กำหนดอินเทอร์เฟซ Storage ที่มี Save(key, value string) error และ Load(key string) (string, error) จากนั้นสร้างการทำงานด้วย MemStorage ที่ใช้แมปเป็นโครงสร้างข้อมูลเบื้องหลังและทดสอบการทำงาน

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

บทเรียน “การกำหนดและใช้งาน interface” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “การกำหนดและใช้งาน interface”

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

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

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

บทเรียน “การกำหนดและใช้งาน interface” ใช้เวลานานแค่ไหน

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

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

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

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

  1. การกำหนดและใช้งาน interface
  2. interface ของไลบรารีมาตรฐานหลัก
  3. การยืนยันชนิดข้อมูลและสวิตช์ชนิดข้อมูล
  4. การประกอบ interface และแนวทางปฏิบัติที่ดี
← กลับไปที่ Go Academy