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
", p.Name)
}
func (p *BMW) DiDi() {
fmt.Printf("%s is didi
", p.Name)
}
func (p *BMW) Hello() {
fmt.Printf("hello, i'm %s
", p.Name)
}
type BYD struct {
Name string
}
func (p *BYD) GetName() string {
return p.Name
}
func (p *BYD) Run() {
fmt.Printf("%s is running
", p.Name)
}
func (p *BYD) DiDi() {
fmt.Printf("%s is didi
", 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
", index, v)
case int, int64, int32:
fmt.Printf("%d params is int, value is %v
", index, v)
case float32, float64:
fmt.Printf("%d params is float, value is %v
", index, v)
case string:
fmt.Printf("%d params is string, value is %v
", index, v)
case Student:
fmt.Printf("%d params student, value is %v
", index, v)
case *Student:
fmt.Printf("%d params *student, value is %v
", 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()
}