golang的struct里面嵌入interface
先通過幾個例子來說明這樣用法。
例子1
定義一個Interface II包含兩個函數(shù)聲明
- F1()
- F2()
然后定義一個struct SS酵紫,它實現(xiàn)了函數(shù)F1和F2亡鼠,這樣SS其實就是II的一個實現(xiàn)旭从。
package main
import (
"fmt"
)
type II interface {
F1()
F2()
}
type SS struct {
vv int
}
func (ss *SS) F1() {
}
func (ss *SS) F2() {
}
func main() {
var ss SS = SS{}
var ii II = &ss
fmt.Printf("ss:value=[%v]\n", ss)
fmt.Printf("ii:value=[%v]\n", ii)
}
編譯運行稳强,輸出如下
$ go build && ./main
ss:value=[{0}]
ii:value=[&{0}]
例子2
如果在struct SS中不實現(xiàn)F1和F2,或者只實現(xiàn)F1或者F2和悦,還能不能繼續(xù)使用呢退疫。
還是前面的代碼,我們注釋掉F2的定義鸽素。
package main
import (
"fmt"
)
type II interface {
F1()
F2()
}
type SS struct {
vv int
}
func (ss *SS) F1() {
}
//func (ss *SS) F2() {
//}
func main() {
var ss SS = SS{}
var ii II = &ss
fmt.Printf("ss:value=[%v]\n", ss)
fmt.Printf("ii:value=[%v]\n", ii)
}
編譯運行
$ go build && ./main
# testinterfacestruct
./main.go:25: cannot use &ss (type *SS) as type II in assignment:
*SS does not implement II (missing F2 method)
編譯器報錯褒繁,不能把ss賦值給ii,因為SS不是II的實現(xiàn)馍忽。
例子3
那么如何解決上述問題呢棒坏,嵌入interface的作用就出來了。我們把interface作為struct的一個匿名成員遭笋,就可以假設struct就是此成員interface的一個實現(xiàn)俊抵,而不管struct是否已經(jīng)實現(xiàn)interface所定義的函數(shù)。
package main
import (
"fmt"
)
type II interface {
F1()
F2()
}
type SS struct {
vv int
II
}
//func (ss *SS) F1() {
//}
//func (ss *SS) F2() {
//}
func main() {
var ss SS = SS{}
var ii II = &ss
fmt.Printf("ss:value=[%v]\n", ss)
fmt.Printf("ii:value=[%v]\n", ii)
}
這個例子中坐梯,struct SS沒有實現(xiàn)interface II的任何一個函數(shù),只是在聲明struct的時候把II作為一個匿名成員刹帕,此時 var ii II = &ss
賦值語句沒有任何錯誤吵血,可見ss已經(jīng)被認為是interface II的實現(xiàn)。
所以嵌入interface可以使得一個struct具有interface的接口偷溺,而不需要實現(xiàn)interface中的有聲明的函數(shù)蹋辅。
例子4
既然沒有實現(xiàn)函數(shù),那么如何調(diào)用接口的呢挫掏?答案是侦另,沒有實現(xiàn)肯定是不能調(diào)用啊,直接crash了尉共;只能調(diào)用已經(jīng)實現(xiàn)的函數(shù)褒傅。
還是在上述例子中,我們定義F1袄友,沒有實現(xiàn)F2殿托,那么可以正常調(diào)用F1,但是不能調(diào)用F2
package main
import (
"fmt"
)
type II interface {
F1()
F2()
}
type SS struct {
vv int
II
}
func (ss *SS) F1() {
fmt.Printf("in SS::F1()\n")
}
//func (ss *SS) F2() {
//}
func main() {
var ss SS = SS{}
var ii II = &ss
fmt.Printf("ss:value=[%v]\n", ss)
fmt.Printf("ii:value=[%v]\n", ii)
ii.F1()
}
運行結(jié)果
ss:value=[{0 <nil>}]
ii:value=[&{0 <nil>}]
in SS::F1()
如果我們運行F2呢剧蚣,會出什么結(jié)果支竹?
把main函數(shù)改成試試:
func main() {
var ss SS = SS{}
var ii II = &ss
fmt.Printf("ss:value=[%v]\n", ss)
fmt.Printf("ii:value=[%v]\n", ii)
// ii.F1()
ii.F2()
}
編譯運行:
$ go build && ./main
ss:value=[{0 <nil>}]
ii:value=[&{0 <nil>}]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x28 pc=0x47d680]
goroutine 1 [running]:
main.(*SS).F2(0xc42000a300)
<autogenerated>:3 +0x40
main.main()
/home/.../go/src/main/main.go:33 +0x185
可見編譯器成功完成了編譯旋廷,但是在運行的時候出錯了,因為F2函數(shù)根本找不到礼搁。
例子5
我們分析一個嵌入Interface的實現(xiàn)饶碘;在前面我們已經(jīng)看到struct和interface的內(nèi)容了。
ss:value=[{0 <nil>}]
ii:value=[&{0 <nil>}]
ss的內(nèi)容包含一個0值和一個nil值馒吴,0值vv的值扎运,那么<nil>推測就是II的值了;增強一下代碼:
package main
import (
"fmt"
"unsafe"
)
type II interface {
F1()
F2()
}
type SS struct {
vv int
II
ww int
}
func (ss *SS) F1() {
fmt.Printf("in SS::F1()\n")
}
func (ss *SS) F2() {
fmt.Printf("in SS::F2()\n")
}
func main() {
var ss SS = SS{vv:1,ww:2}
var ii II = &ss
fmt.Printf("ss:size=[%d],value=[%v]\n", unsafe.Sizeof(ss), ss)
fmt.Printf("ii:size=[%d],value=[%v]\n", unsafe.Sizeof(ii), ii)
}
運行結(jié)果:
$ go build && ./main
ss:size=[32],value=[{1 <nil> 2}]
ii:size=[16],value=[&{1 <nil> 2}]
可見ss占用32字節(jié)募书,前8字節(jié)和后8字節(jié)分別是變量vv和ww绪囱,中間的16字節(jié)必須是給II的;這是一個占位符莹捡,沒有具體的值鬼吵,其值為nil。
這個地方有疑問篮赢,為什么是一個nil的占位符齿椅。