go interface接口
interface接口
定义:Interface类型可以定义一组方法,但是这些不需要实现。并且interface不能 包含任何变量。
type example interface{ Method1(参数列表) 返回值列表 Method2(参数列表) 返回值列表 … }
interface类型默认是一个指针
样例一:
package main import "fmt" type People struct { name string age int } type Test interface { Print() Sleep() } type Student struct { name string age int score int } func (p Student) Print() { fmt.Println("name:", p.name) fmt.Println("age:", p.age) fmt.Println("score:", p.score) } func (p Student) Sleep() { fmt.Println("student sleep") } func (people People) Print() { fmt.Println("name:", people.name) fmt.Println("age:", people.age) } func (p People) Sleep() { fmt.Println("people sleep") } func main() { var t Test fmt.Println(t) //t.Print() var stu Student = Student{ name: "stu1", age: 20, score: 200, } t = stu t.Print() t.Sleep() var people People = People{ name: "people", age: 100, } t = people t.Print() t.Sleep() fmt.Println("t:", t) }
样例二:
package main import "fmt" type Carer interface { GetName() string Run() DiDi() } type Test interface { Hello() } type BMW struct { Name string } func (p *BMW) GetName() string { return p.Name } func (p *BMW) Run() { fmt.Printf("%s is running\n", p.Name) } func (p *BMW) DiDi() { fmt.Printf("%s is didi\n", p.Name) } func (p *BMW) Hello() { fmt.Printf("hello, i'm %s \n", p.Name) } type BYD struct { Name string } func (p *BYD) GetName() string { return p.Name } func (p *BYD) Run() { fmt.Printf("%s is running\n", p.Name) } func (p *BYD) DiDi() { fmt.Printf("%s is didi\n", p.Name) } func main() { var car Carer var test Test fmt.Println(car) bmw := &BMW{ Name: "BMW", } car = bmw car.Run() test = bmw test.Hello() byd := &BYD{ Name: "BYD", } car = byd car.Run() }
接口实现
Golang中的接口,不需要显示的实现。只要一个变量,含有接口类型中 的所有方法,那么这个变量就实现这个接口。因此,golang中没有implement 类似的关键字。
如果一个变量含有了多个interface类型的方法,那么这个变量就实现了多个 接口。
如果一个变量只含有了1个interface的方部分方法,那么这个变量没有实现 这个接口。
多态
一种事物的多种形态,都可以按照统一的接口进行操作
接口嵌套
一个接口
可以嵌套在另外的接口
type ReadWrite interface { Read(b Buffer) bool Write(b Buffer) bool } type Lock interface { Lock() Unlock() } type File interface { ReadWrite Lock Close() }
样例一:
package main import "fmt" type Reader interface { Read() } type Writer interface { Write() } type ReadWriter interface { Reader Writer } type File struct { } func (f *File) Read() { fmt.Println("read data") } func (f *File) Write() { fmt.Println("write data") } func Test(rw ReadWriter) { rw.Read() rw.Write() } func main() { var f File Test(&f) }
判断一个变量是否实现了指定接口
package main import "fmt" type Reader interface { Read() } type Writer interface { Write() } type ReadWriter interface { Reader Writer } type File struct { } func (f *File) Read() { fmt.Println("read data") } func (f *File) Write() { fmt.Println("write data") } func main() { var f *File var b interface{} b = f v, ok := b.(ReadWriter) fmt.Println(v, ok) }
类型断言
由于接口是一般类型,不知道具体类型,如果要转成具体类型,可以采用以下方法进行转换:
var t int var x interface{} x = t y = x.(int) //转成int 或者 var t int var x interface{} x = t y, ok = x.(int) //转成int,带检查
样例:
package main import "fmt" type Student struct { Name string Sex string } func Test(a interface{}) { b, ok := a.(Student) if ok == false { fmt.Println("convert failed") return } //b += 3 fmt.Println(b) } func just(items ...interface{}) { for index, v := range items { switch v.(type) { case bool: fmt.Printf("%d params is bool, value is %v\n", index, v) case int, int64, int32: fmt.Printf("%d params is int, value is %v\n", index, v) case float32, float64: fmt.Printf("%d params is float, value is %v\n", index, v) case string: fmt.Printf("%d params is string, value is %v\n", index, v) case Student: fmt.Printf("%d params student, value is %v\n", index, v) case *Student: fmt.Printf("%d params *student, value is %v\n", index, v) } } } func main() { var b Student = Student{ Name: "stu01", Sex: "female", } Test(b) just(28, 8.2, "this is a test", b, &b) }
空接口
空接口没有任何方法,所以所有类型都实现了空接口,也就是任何变量都可以赋值给空接口。
var a int var b interface{} b = a
备注:变量slice和接口slice之间赋值操作,for range
通用的链表类
link.go
package main import "fmt" type LinkNode struct { data interface{} next *LinkNode } type Link struct { head *LinkNode tail *LinkNode } func (p *Link) InsertHead(data interface{}) { node := &LinkNode{ data: data, next: nil, } if p.tail == nil && p.head == nil { p.tail = node p.head = node return } node.next = p.head p.head = node } func (p *Link) InsertTail(data interface{}) { node := &LinkNode{ data: data, next: nil, } if p.tail == nil && p.head == nil { p.tail = node p.head = node return } p.tail.next = node p.tail = node } func (p *Link) Trans() { q := p.head for q != nil { fmt.Println(q.data) q = q.next } }
main.go
package main import "fmt" func main() { var link Link for i := 0; i < 10; i++ { //intLink.InsertHead(i) link.InsertTail(fmt.Sprintf("str %d", i)) } link.Trans() }