Go Interfaces
Back to Go Index
Interface Concept
Interface คือรูปแบบลักษณะที่ตกลงร่วมกันและเข้ากันได้ (method signature)
Empty Interface
- Go v1.8 ขึ้นไป
anyกับinterface{}เป็นตัวเดียวกัน ใช้เพื่อระบุว่า ใช้ได้กับทุก Type
func main() {
var v any
v = 36
fmt.Println(v)
v = "hello"
fmt.Println(v)
}Type Assertion
ใช้ Type assertion เพื่อให้ type ตรงกันกับ function
func show(val int) { // int
i := val + 2
fmt.Println(i)
}
func main() {
var v any
v = 36
show(v.(int)) // type assertion
}Type Assertion with Safety Check
หรือเปลี่ยนให้ type parameter เป็น any ก็จะใช้ได้กับทั้งหมด แต่จะไม่สามารถดำเนินการแบบ int ใน function ได้เหมือนเดิม ต้องทำ Type assertion
ใช้ตัวแปร ok เพื่อเช็ค type ก่อน ป้องกันไม่ให้เกิด runtime error ตอน assert type ได้
func show(val any) { // any
i, ok := val.(int) // type assertion checking
if ok {
i = i + 1
fmt.Println(i)
} else {
fmt.Println("Not int")
}
}
func main() {
var v any
v = 36
show(v)
}Type Switch
ใช้ switch case เพื่อจัดการกับแต่ละ Type ได้ tips
func show(val any) {
switch v := val.(type) { // switch case type
case int:
i := v + 1
fmt.Println("int:", i)
case string:
s := v + "Hi"
fmt.Println("string:", s)
default:
fmt.Println("unknown")
}
}
func main() {
var v any
v = 36
show(v)
}Type Assertion vs Type Conversion
ทั้งสอง Concept นี้ ใช้เพื่อแปลงค่าจาก type หนึ่งไปเป็น type ใหม่ แต่มีจุดแตกต่างดังนี้
| Type Assertions | Type Conversions | |
|---|---|---|
| Syntax | x.(T) | T(value) |
| Use case | Extract a value of a specific type from an interface value | Explicitly convert a value of one type to another |
| Result | Returns the value of the asserted type and a boolean indicating whether the assertion succeeded or failed | Returns a new value of the specified type |
| Failure | Fails if the value being asserted is not of the specified type | Fails if the value being converted is not compatible with the target type |
| Performance | Generally slower than type conversions due to additional runtime checks | Generally faster than type assertions because they involve a simple conversion operation |
Interface Implementation
- ประกาศ interface แล้วตั้งชื่อว่า promotion ที่มี method signature ไว้
- ประกาศ struct ชื่อ course แล้วมี 2 method คือ
discount()และinfo() - จะเห็นว่า course เป็นไปตาม interface promotion เพราะมี method
discount()จึงเป็นการ implement อัตโนมัติโดยไม่ต้องเขียน และไม่ได้สนใจinfo() - ดังนั้น
sale()จึงรับ parameter course เข้ามา แล้วสามารถใช้discount()ได้ - แต่จะใช้
info()ไม่ได้ เพราะ course เข้ามาในsale()ในฐานะ interface promotion
type promotion interface {
discount() float64
}
type course struct{}
func (c course) discount() float64 {
return 0.1
}
func (c course) info() {
fmt.Println("Course info", c)
}
func sale(val promotion) {
fmt.Printf("Sale: %#v\n", val.discount())
}
func main() {
v := course{}
sale(v)
}Embedding Interface
เราสามารถนำ Interface มาหลอมรวมกันใน Interface ตัวอื่นๆ ได้
- ประกาศ interface ตั้งชื่อว่า presenter โดยรวม promotioner และ infoer
- course เป็นไปตาม interface presenter ที่มีทั้ง method
discount()และinfo()จึงเป็นการ implement อัตโนมัติ summary()จึงสามารถรับ course เข้ามาได้
type promotioner interface {
discount() float64
}
type infoer interface {
info()
}
type presenter interface { // Embedding Interface
promotioner
infoer
}
type course struct{}
func (c course) discount() float64 {
return 0.1
}
func (c course) info() {
fmt.Println("Course info", c)
}
func summary(val presenter) {
fmt.Printf("Sale: %#v\n", val.discount())
val.info()
}
func main() {
v := course{}
summary(v)
}Related: