您好,登錄后才能下訂單哦!
這篇文章主要講解了“Golang接口的定義與空接口及斷言怎么使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Golang接口的定義與空接口及斷言怎么使用”吧!
在Go語言中接口(interface)是一種類型,一種抽象的類型。
接口(interface)定義了一個對象的行為規范, 只定義規范不實現 ,由具體的對象來實現規范的細節 。
實現接口的條件:
一個對象只要全部實現了接口中的方法 ,那么就實現了這個接口。換句話說,接口就是一個需要實現的方法列表。
下面的代碼中定義了貓和狗,然后它們都會叫,你會發現main函數中明顯有重復的代碼
如果我們后續再加上豬、青蛙等動物的話,我們的代碼還會一直重復下去
那我們能不能把它們當成“能叫的動物”來處理呢?
type Cat struct { Name string } func (c Cat) Say() string { return c.Name + ":喵喵喵" } type Dog struct { Name string } func (d Dog) Say() string { return d.Name + ": 汪汪汪" } func main() { c := Cat{Name: "小白貓"} // 小白貓:喵喵喵 fmt.Println(c.Say()) d := Dog{"阿黃"} fmt.Println(d.Say()) // 阿黃: 汪汪汪 } /* 小白貓:喵喵喵 阿黃: 汪汪汪 */
定義一個 Usber 接口讓 Phone 和 Computer 結構體實現這個接口
//1.接口是一個規范 type Usber interface { getName() string } //2.如果接口里面有方法的話,必要要通過結構體或者通過自定義類型實現這個接口 type Phone struct { Name string } type Computer struct { Brand string } func (c *Computer) getName() string { return c.Brand } //3.手機要實現usb接口的話必須得實現usb接口中的所有方法 func (p *Phone) getName() string { return p.Name } func main() { p := &Phone{ Name: "華為手機", } c := &Computer{ Brand: "聯想電腦", } var p1 Usber // golang中接口就是一個數據類型 p1 = p // 表示手機實現Usb接口 fmt.Println(p1.getName()) //接口使用場景,處理相同類型的數據 newName := transData(p) newName1 := transData(c) fmt.Println(newName, newName1) } func transData(usber Usber) string { name := usber.getName() return fmt.Sprintf("%s%s", name, "處理后") }
當我們要去處理同一數據類型的時候這個數據的時候,比如貓 狗是同一類數據類型。
像k8s的deployment,pod,configmap,secretd等等這些資源的時候,它都是k8s的一個資源,在獲取列表的時候會對其做數據處理,比如要對其進行數據排序,那么只需要對這個接口進行排序就行了,不需要對每個資源都去寫一遍排序的方法,那么這樣不是很冗余嗎?
Golang中空接口也可以直接當做類型來使用,可以表示任意類型 (泛型概念,最大的特點)
Golang 中的接口可以不定義任何方法,沒有定義任何方法的接口就是空接口。
空接口表示沒有任何約束,因此任何類型變量都可以實現空接口。
空接口在實際項目中用的是非常多的,用空接口可以表示任意數據類型
//空接口作為函數的參數 func show(a interface{}) { fmt.Printf("值:%v 類型:%T\n", a, a) } func main() { show(20) // 值:20 類型:int show("你好golang") // 值:你好golang 類型:string slice := []int{1, 2, 34, 4} show(slice) // 值:[1 2 34 4] 類型:[]int }
printf println是可以接受任何參數的,func Printf(format string , a ...interface{})可以看到這里可以接受任何空接口類型,...類似于切片類型。
func test(a int, b ...interface{}) { for _, v := range b { fmt.Printf("%v,%T \n", v, v) } } func main() { test(1, "a", 22, []string{"1"}) } a,string 22,int [1],[]string
切片和map是同一類型的元素,有了空接口,在同一個切片同一個map中就可以將任何類型的數據放進去。
func main() { var slice = []interface{}{"張三", 20, true, 32.2} fmt.Println(slice) // [張三 20 true 32.2] }
func main() { // 空接口作為 map 值 var studentInfo = make(map[string]interface{}) studentInfo["name"] = "張三" studentInfo["age"] = 18 studentInfo["married"] = false fmt.Println(studentInfo) // [age:18 married:false name:張三] }
類型斷言(從上往下轉換,接口類型轉化為具體類型)
一個接口的值(簡稱接口值)是由一個具體類型和具體類型的值兩部分組成的。
這兩部分分別稱為接口的動態類型和動態值。(一個空接口,可以是結構體,指針,布爾各種類型。它其實是動態的,你傳遞什么都可以,這就叫做動態類型和動態值)
如果我們想要判斷空接口中值的類型,那么這個時候就可以使用類型斷言
其語法格式: x.(T)
x : 表示類型為 interface{}的變量
T : 表示斷言 x 可能是的類型
斷言返回兩個值,一個是斷言是否轉化成果,一個是轉化結果,注意空接口類型是空接口類型。
var str interface{} str = "hello" str = str + "sss" //這樣寫是會報錯的,因為空接口類型不是字符串類型,需要斷言轉化才可以
type test1 struct { name string age int } func main() { var t interface{} //未斷言前沒有結構體的特征,需要斷言轉化為結構體指針 t = &test1{ name: "hh", age: 12, } v, ok := t.(*test1) //這里其實就是做了一個類型轉化,這里的類型就變為來結構體指針類型 if ok { fmt.Printf("類型:%T 值:%#v\n", v, v) } else { fmt.Println("xxx") } } 類型:*main.test1 值:&main.test1{name:"hh", age:12}
轉化為具體類型之后,那么具體類型的方法是都可以去調用的,空接口是不能訪問屬性和方法的。轉化為具體的類型之后就可以訪問其屬性和方法。
值接收者和指針接收者(節省內存)
當方法作用于值類型接收者時,Go語言會在代碼運行時將接收者的值復制一份。
在值類型接收者的方法中可以獲取接收者的成員值,但修改操作只是針對副本,無法修改接收者變量本身。
type Usb interface { Start() Stop() } type Phone struct { Name string } func (p Phone) Start() { fmt.Println(p.Name, "開始工作") } func (p Phone) Stop() { fmt.Println("phone 停止") } func main() { phone1 := Phone{ // 一:實例化值類型 Name: "小米手機", } var p1 Usb = phone1 //phone1 實現了 Usb 接口 phone1 是 Phone 類型 p1.Start() phone2 := &Phone{ // 二:實例化指針類型 Name: "蘋果手機", } var p2 Usb = phone2 //phone2 實現了 Usb 接口 phone2 是 *Phone 類型 p2.Start() //蘋果手機 開始工作 }
指針類型的接收者由一個結構體的指針組成
由于指針的特性,調用方法時修改接收者指針的任意成員變量,在方法結束后,修改都是有效的。
這種方式就十分接近于其他語言中面向對象中的 this 或者 self 。
例如我們為 Person 添加一個 SetAge 方法,來修改實例變量的年齡。
使用時機
注:并不是所有情況下都希望修改數據
需要修改接收者中的值
接收者是拷貝代價比較大的大對象
保證一致性,如果有某個方法使用了指針接收者,那么其他的方法也應該使用指針接收者。
從使用場景上面來說,基本上都會使用指針,如果使用了第三方的包,第三方包的某些返回值它只是一個值類型,所以第三方類型返回什么類型我們就使用什么類型,針對第三方包。
感謝各位的閱讀,以上就是“Golang接口的定義與空接口及斷言怎么使用”的內容了,經過本文的學習后,相信大家對Golang接口的定義與空接口及斷言怎么使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。