- Go中的interface也是型別type,定義了方法規范,其內只有方法的宣告沒有實作,定義格式為:
type interface_Name interface{ f1()....} - 需要注意的一點是go中的interface是非侵入式的,也就是不需要利用某個關鍵字(比如Java中的implements)顯示的宣告某個型別是否實作了某個interface,只需要某個型別的物件的某個方法是某個介面的方法的實作(go中不允許方法的多載),就表明該物件(其實是其指標型別!!!)實作了該介面,其是該介面的一個實體
- go中的介面不要求其內的方法均為匯出的,可以定義私有,或者匯出的方法宣告(跟Java中介面很不一樣)
- 介面中所有的方法都必須被實作
- Go語言的介面在命名時,一般會在單詞后面添加er,如寫操作的介面叫做Writer
- 一個型別可以實作多個介面,介面間是彼此獨立的,互相不知道對方的實作多個型別也可以實作相同的介面
- 介面之間也可以相互嵌套
- 空介面是介面的特殊形式,沒有任何方法,因此任何具體的型別都可以認為其默認實作了空介面!!!
interface{}//空介面型別,所以一旦一個方法的引數是一個空介面型別,表明該方法可以接受任何具體的型別作為其引數,也可以利用空介面,可以實作任意型別的存盤
//空介面作為函式引數:
func Test(i interface{}) {
fmt.Printf("%T\n", i)
}
func main() {
Test(3) // int
Test("hello") // sting
}
// 利用空介面,可以實作任意型別的存盤:
m := make(map[string]interface{})
m["name"] = "李四"
m["age"] = 30
【補充:空介面相關操作】:
1、從空介面型別中獲取值:
保存到空介面的值,如果直接取出指定型別的值時,會發生編譯錯誤:
var a int = 1
var i interface{} = a
var b int = i //這里編譯報錯(型別不一致),可以這樣做:b := i
2、空介面型別物件或變數值的比較
2.1型別不同的空介面比較:
var a interface{} = 100
var b interface{} = "hi"
fmt.Println(a == b) //false
2.2 不能比較空介面中的動態值:
var c interface{} = []int{10}
var d interface{} = []int{20}
fmt.Println(c == d) //運行報錯
2.3 空介面的型別和可比較性總結:
| 型別 | 說明 |
|---|---|
| map | 不可比較,會發生宕機錯誤 |
| 切片 | 不可比較,會發生宕機錯誤 |
| 通道 | 可以比較,必須由同一個make生成,即同一個通道才是true |
| 陣列 | 可比較,編譯期即可知道是否一致 |
| 結構體 | 可比較,可逐個比較結構體的各成員 |
| 函式 | 可比較 |
package demo
import "fmt"
/*
@Author:David Ma
@Content:介面相關定義
@Date:2020-12-03 15:24
*/
type EatService interface {
Eat()
Sleep()
}
type Cat struct {
Name string
}
func (cat *Cat)Eat() {
fmt.Printf("%s eatting \n", cat.Name)
}
func (cat *Cat) Sleep() {
fmt.Printf("%s sleeping\n", cat.Name)
}
type Dog struct {
Name string
}
func (dog *Dog) Sleep() {
fmt.Printf("%s sleeping\n", dog.Name)
}
func (dog *Dog)Eat() {
fmt.Printf("%s eatting \n", dog.Name)
}
func MyEat(es EatService) {
es.Eat()
}
func MySleep(es EatService) {
es.Sleep()
}
package test
import (
"../demo"
"testing"
)
/*
@Author:David Ma
@Content:介面相關定義
@Date:2020-12-03 15:24
*/
func TestMyInterface(t *testing.T) {
t.Helper()
t.Run("", func(t *testing.T) {
cat := demo.Cat{"Tom"}
dog := demo.Dog{"Jerry"}
// 注意這里要傳一個指標型別,因為是指標型別(* Dog以及* Cat)實作了EatService介面,而不是Dog和Cat,也就是只有*Dog或者*Cat型別才可以看作是EatService型別)
//否則compile error:Cannot use 'cat' (type Cat) as type EatService Type does not implement 'EatService' as 'Eat' method has a pointer receiver
demo.MyEat(&cat)
demo.MySleep(&cat)
//如果物件實作了介面的某個方法,則其必須實作該介面的其他方法,否則報錯:
//Cannot use '&dog' (type *Dog) as type EatService Type does not implement 'EatService' as some methods are missing: Sleep()
demo.MyEat(&dog)
demo.MySleep(&dog)
})
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/229923.html
標籤:區塊鏈
上一篇:如何用js給老婆每天發情話
