什麼是介面
- 即:將一些共性方法集合在一起
- 方法的集合,不需要方法的具體內容
package main
import "fmt"
// 定義介面 使用 interface. 結合 struct 結構體使用
type USB interface {
input() // 輸入 方法
output() // 輸出 方法
}
type Mouse struct {
name string
}
type KeyBord struct {
name string
}
// 實現 介面的全部方法,就代表實現類這個介面
func (m Mouse) input() {
fmt.Println(m.name, "滑鼠輸入")
}
func (m Mouse) output() {
fmt.Println(m.name, "滑鼠輸出")
}
func (k KeyBord) input() {
fmt.Println(k.name, "鍵盤輸入")
}
func (k KeyBord) output() {
fmt.Println(k.name, "鍵盤輸入")
}
func realizeUsb(usb USB) {
usb.input()
usb.output()
}
func main() {
/*
go中的介面
- 什麼是介面? 即:將一些共性方法集合在一起
- 介面是:方法的集合,不需要方法的具體內容
*/
// 透過傳入`介面` 來實現呼叫
mouse := Mouse{name: "羅技"}
// realizeUsb 的引數 是介面型別,如果一個結構體實現這個介面的所有方法,則結構體就是介面型別
realizeUsb(mouse)
keyboard := KeyBord{name: "鐳射"}
realizeUsb(keyboard)
// 定義高階型別
var usb USB
usb = mouse
// 只能呼叫usb介面中的方法,不能呼叫 mouse 結構體中的屬性
// usb.name // usb.name undefined (type USB has no field or method name)
usb.input()
}
go 空介面
- 所有結構體都實現類空介面個,空介面可以儲存任何型別
- interface {} == any
package main
import "fmt"
// 定義空介面,實現包容萬物
type EmptyInterface interface {
}
type DogEmptyStruct struct {
name string
}
// 定義空介面實現方法
func emptyInterfaceFunc(ei EmptyInterface) {
fmt.Printf("空介面實現函式。【引數:%v ---- 型別:%T】\n", ei, ei) // main.DogEmptyStruct
}
// 萬能介面. 空介面作為函式的引數// main.DogEmptyStruct
func emptyInterfaceFunc2(universalInterface interface{}) {
fmt.Printf("萬能介面。【引數:%v ---- 型別:%T】\n", universalInterface, universalInterface)
}
func main() {
/*空介面*/
// 所有結構體都實現類空介面個,空介面可以儲存任何型別
// interface {} == any
var dogEmpty = DogEmptyStruct{name: "小雞毛"}
emptyInterfaceFunc(dogEmpty)
fmt.Println("-----")
//
var a1 EmptyInterface = DogEmptyStruct{name: "小雞毛"}
fmt.Printf("a1 【引數:%v ---- 型別:%T】\n", a1, a1) // 【引數:{小雞毛} ---- 型別:main.DogEmptyStruct】
var a2 EmptyInterface = 1
fmt.Printf("a2 【引數:%v ---- 型別:%T】\n", a2, a2) // 【引數:1 ---- 型別:int】
var a3 EmptyInterface = "string"
fmt.Printf("a3 【引數:%v ---- 型別:%T】\n", a3, a3) // 【a3 【引數:string ---- 型別:string】
fmt.Println(a1, a2, a3)
fmt.Println("萬能引數,空介面-----")
emptyInterfaceFunc2(1)
emptyInterfaceFunc2("string")
emptyInterfaceFunc2(make([]string, 10))
fmt.Println("空介面對map和slice的使用-----")
map1 := make(map[string]interface{})
map2 := make(map[string]any)
fmt.Printf("map1 【型別:%T】\n", map1) // 【型別:map[string]interface {}】
fmt.Printf("map2 【型別:%T】\n", map2) // 【型別:map[string]interface {}】
// 空介面能 接收任何型別的引數
map1["a1"] = a1
map1["a2"] = a2
map1["a3"] = a3
fmt.Println(map1) // map[a1:{小雞毛} a2:1 a3:string]
}
介面型別
package main
import "fmt"
type MyStruct struct {
code int
}
type MyInterface interface {
myInterfaceFunc()
}
func (msc *MyStruct) myInterfaceFunc() interface{} {
return interface{}(msc.code)
}
func test(msc MyStruct) {
ret := msc.myInterfaceFunc()
fmt.Printf("型別:%T\n", ret)
fmt.Printf("記憶體地址:%p\n", &ret)
}
func main() {
ms1 := MyStruct{code: 1}
test(ms1)
ms2 := MyStruct{code: 2}
test(ms2)
var any interface{}
fmt.Printf("any型別:%T\n", any)
fmt.Printf("any記憶體地址:%p\n", &any)
any2 := any
any3 := any
fmt.Printf("any2型別:%T\n", any2)
fmt.Printf("any2記憶體地址:%p\n", &any2)
fmt.Printf("any3記憶體地址:%p\n", &any3)
any = 42
// 動態型別斷言
if val, ok := any.(int); ok {
fmt.Println("Value is an integer:", val)
} else {
fmt.Println("Value is not an integer")
}
}
介面巢狀
package main
import "fmt"
type AA interface {
test1()
}
type BB interface {
test2()
}
// 定義介面CC : 如果實現CC介面,需要實現test1()/test2()/test3() 三個方法
type CC interface {
// 巢狀 介面
AA // 匯入AA介面中的方法
BB
test3()
}
// 編寫一個結構體 , 實現CC
type Dog7 struct {
}
// 函式+結構體引數+介面中定義的函式名
func (d Dog7) test1() {
fmt.Println("test1")
}
func (d Dog7) test2() {
fmt.Println("test2")
}
func (d Dog7) test3() {
fmt.Println("test3")
}
func main() {
/* 介面的巢狀 */
// 結構體例項化物件,呼叫介面 AA / BB / CC 三個方法
var dog Dog7 = Dog7{}
dog.test1()
dog.test2()
dog.test3()
// 因為CC介面巢狀了 AA 和 BB 介面。可以定義 某個變數的型別為介面型別。將結構體物件賦值給 這個變數。這個變數就能實現 test1/test2/test3 三個方法
var c CC = Dog7{} // 向上轉型後只能呼叫自己的方法
c.test3()
c.test2()
c.test1()
// 因為CC介面巢狀了 AA 和 BB 介面。可以定義 某個變數的型別為介面型別。將結構體物件賦值給 這個變數。這個變數就能實現 test1/test2/test3 三個方法
var a AA = Dog7{}
//a.test3() // 向上轉型後只能呼叫自己的方法
//a.test2() // 向上轉型後只能呼叫自己的方法
a.test1()
}
介面斷言
- 定義:檢查一個介面的變數是不是符合預期呼叫/值
- 被斷言的物件必須是介面型。否則會報錯
- 格式: t,ok:=i.(T) 【t:就是i介面是T型別的,i:介面,T:型別】
package main
import "fmt"
func main() {
/*
介面斷言
- 定義:檢查一個介面的變數是不是符合預期呼叫/值
- 被斷言的物件必須是介面型。否則會報錯
- 格式: t,ok:=i.(T) 【t:就是i介面是T型別的,i:介面,T:型別】
*/
assertString("123") // 斷言成功,則無異常
//assertString(123) // 斷言失敗就會丟擲異常,停止程式【panic: interface conversion: interface {} is int, not string 】
assertInt("1")
assertInt(true)
assertInt(1)
}
// 判斷一個變數是不是字串型別
func assertString(i interface{}) {
s := i.(string)
fmt.Println(s)
}
// 斷言失敗不希望程式停止
func assertInt(i any) {
i, ok := i.(int)
fmt.Println(i, ok)
if ok {
fmt.Println("int型別")
} else {
fmt.Println("非int型別")
}
}