先看下面的代码:
package main
import "fmt"
// 首先定义两个接口 TestInt1 和 TestInt2
// TestInt1 is an interface
type TestInt1 interface {
func1()
func2()
func3()
}
// TestInt2 is an interface
type TestInt2 interface {
func4()
func5()
func6()
}
// TestStruct1 is a struct
type TestStruct1 struct {
TestInt1
str string
}
// TestStruct2 is a struct
type TestStruct2 struct {
TestInt2
str string
}
// TestStruct3 is a struct
type TestStruct3 struct {
TestInt1
TestInt2
str string
}
// 定义一个结构体,并实现TestInt1和TestInt2接口
type emptyCtx struct {
a string
b string
}
func (e *emptyCtx) func1() {
fmt.Println("func1: " + e.a)
}
func (e *emptyCtx) func2() {
fmt.Println("func2: " + e.b)
}
func (e *emptyCtx) func3() {
fmt.Println("func3: " + e.a + " " + e.b)
}
func (e *emptyCtx) func4() {
fmt.Println("func4: " + e.a)
}
func (e *emptyCtx) func5() {
fmt.Println("func5: " + e.b)
}
func (e *emptyCtx) func6() {
fmt.Println("func6: " + e.a + " " + e.b)
}
func newStruct1(i1 TestInt1) *TestStruct1 {
return &TestStruct1{
TestInt1: i1,
str: "newStruct1",
}
}
func newStruct2(i2 TestInt2) *TestStruct2 {
return &TestStruct2{
TestInt2: i2,
str: "newStruct2",
}
}
func newStruct3(i1 TestInt1, i2 TestInt2) *TestStruct3 {
return &TestStruct3{
TestInt1: i1,
TestInt2: i2,
str: "newStruct3",
}
}
func newStruct1ReturnTestInt1(i1 TestInt1) TestInt1 {
return &TestStruct1{
TestInt1: i1,
str: "newStruct1ReturnTestInt1",
}
}
func newStruct2ReturnTestInt2(i2 TestInt2) TestInt2 {
return &TestStruct2{
TestInt2: i2,
str: "newStruct2ReturnTestInt2",
}
}
func newStruct3ReturnTestInt1(i1 TestInt1, i2 TestInt2) TestInt1 {
return &TestStruct3{
TestInt1: i1,
TestInt2: i2,
str: "newStruct3ReturnTestInt1",
}
}
func newStruct3ReturnTestInt2(i1 TestInt1, i2 TestInt2) TestInt2 {
return &TestStruct3{
TestInt1: i1,
TestInt2: i2,
str: "newStruct3ReturnTestInt2",
}
}
func newStruct3ReturnEmptyInterface(i1 TestInt1, i2 TestInt2) interface{} {
return &TestStruct3{
TestInt1: i1,
TestInt2: i2,
str: "newStruct3ReturnTestInt2",
}
}
func main() {
ex := &emptyCtx{
a: "aaa",
b: "bbb",
}
fmt.Printf("ex: %v, address: %p\n", ex, ex)
ns1 := newStruct1(ex)
ns2 := newStruct2(ex)
ns3 := newStruct3(ex, ex)
fmt.Printf("ns1: %v, address: %p\n", ns1, ns1)
fmt.Printf("ns2: %v, address: %p\n", ns2, ns2)
fmt.Printf("ns3: %v, address: %p\n", ns3, ns3)
s1ri1 := newStruct1ReturnTestInt1(ex)
s2ri2 := newStruct2ReturnTestInt2(ex)
fmt.Printf("s1ri1: %v, address: %p\n", s1ri1, s1ri1)
fmt.Printf("s2ri2: %v, address: %p\n", s2ri2, s2ri2)
s3ri1 := newStruct3ReturnTestInt1(ex, ex)
s3ri2 := newStruct3ReturnTestInt2(ex, ex)
fmt.Printf("s3ri1: %v, address: %p\n", s3ri1, s3ri1)
fmt.Printf("s3ri2: %v, address: %p\n", s3ri2, s3ri2)
s3rei := newStruct3ReturnEmptyInterface(ex, ex)
// 将空接口转换成TestInt1接口
if intf, ok := s3rei.(TestInt1); ok {
intf.func1()
intf.func2()
intf.func3()
}
// 将空接口转换成TestInt2接口
if intf, ok := s3rei.(TestInt2); ok {
intf.func4()
intf.func5()
intf.func6()
}
}
上面代码中emptyCtx实现了两个接口。其他的每个结构体内都包含了接口类型的属性,所以实例化结构体的时候可以返回对应的接口类型,具体参看上面几个返回接口类型的函数。但是这个地方需要注意,结构体中的接口类型属性不能有具体的变量名称,否则编译器会提示该变量没有实现接口的方法,导致返回接口类型的函数产生语法错误。
TestStruct3包含了两个接口类型的属性,所以实际上可以返回两个接口类型。这里返回了一个空接口,在后面的处理中可以根据具体需求转换成不同的接口类型。
这种返回接口类型实例的做法,实际上屏蔽了结构体的其他属性和方法,只能调用接口方法。