定义
接口是一组包含方法名,参数,返回值的未具体实现方法的集合
基础用法如下:
package main
import (
"fmt"
)
type Schooler interface {
Name() string
Age() int
Grade() int
}
type Student struct {
name string
age int
grade int
}
func (s Student) Name() string {
return s.name
}
func (s Student) Age() int {
return s.age
}
func (s Student) Grade() int {
return s.grade
}
func main() {
var school Schooler
student := Student{name: "Jack", age: 10, grade: 4}
// 因为student实现了Schooler接口所以直接赋值没问题
school = student
fmt.Printf("name:%v,age:%v,grade:%v\n", school.Name(), school.Age(), school.Grade()) // name:Jack,age:10,grade:4
}
空接口
空接口不包含任何方法,因此,任意类型均实现了空接口。
任意类型变量都可以赋值给空接口类型的变量,如下所示:
package main
import (
"fmt"
)
type Typer interface{}
func main() {
var tt Typer
var a int
var b float32
tt = a
fmt.Printf("%T\n", tt) // int
tt = b
fmt.Printf("%T\n", tt) // float32
}
测试接口实现
测试变量是否实现了某个接口需要使用x.(T)
的特定语法,如下所示:
package main
import (
"fmt"
)
type Schooler interface {
Name() string
Age() int
}
type Student struct {
name string
age int
}
type Teacher struct {
name string
age int
}
func (s Student) Name() string {
return s.name
}
func (s Student) Age() int {
return s.age
}
func (s Teacher) Name() string {
return s.name
}
func CheckSchoolerImpliments(v interface{}) bool {
if tmp, ok := v.(Schooler); ok {
fmt.Printf("%T, %v", tmp, tmp)
return true
}
return false
}
func main() {
student := Student{name: "Jack", age: 10}
teacher := Teacher{name: "Lucy", age: 26}
fmt.Println(CheckSchoolerImpliments(student)) // main.Student, {Jack 10}true
fmt.Println(CheckSchoolerImpliments(teacher)) // false
}
类型断言
空接口可以存储任意类型,区分不同的类型常用两种方法,Comma-ok断言 和 switch判断
package main
import (
"fmt"
)
type Student struct {
name string
}
func main() {
var params = make([]interface{}, 3)
fmt.Println(params) // [<nil> <nil> <nil>]
params[0] = 18
params[1] = "hello"
params[2] = Student{name: "Jack"}
fmt.Println(params) // [18 hello {Jack}]
for _, item := range params {
if _, ok := item.(int); ok {
fmt.Printf("%v's type is int\n", item) // 18's type is int
} else if _, ok := item.(string); ok {
fmt.Printf("%v's type is string\n", item) // hello's type is string
} else if _, ok := item.(Student); ok {
fmt.Printf("%v's type is struct\n", item) // {Jack}'s type is struct
}
}
for _, item := range params {
switch value := item.(type) {
case int:
fmt.Printf("%v's type is int\n", value) // 18's type is int
case string:
fmt.Printf("%v's type is string\n", item) // hello's type is string
case Student:
fmt.Printf("%v's type is struct\n", item) // {Jack}'s type is struct
default:
fmt.Printf("unknown type\n")
}
}
}
接口零值
未赋值的接口类型为nil
package main
import (
"fmt"
)
type Student interface {
name() string
}
func main() {
var s Student
if s == nil {
fmt.Println("s is nil") // s is nil
}
}
指针实现接口与值实现接口
package main
import (
"fmt"
)
type Schooler interface {
Name() string
Age() int
}
type Student struct {
name string
age int
}
type Teacher struct {
name string
age int
}
func (s Student) Name() string {
return s.name
}
func (s Student) Age() int {
return s.age
}
func (s *Teacher) Name() string {
return s.name
}
func (s *Teacher) Age() int {
return s.age
}
func main() {
student := Student{name: "Jack", age: 10}
teacher := Teacher{name: "Lucy", age: 26}
var s Schooler
s = student
fmt.Printf("name:%v.age:%v\n", s.Name(), s.Age()) // name:Jack.age:10
// s = teacher // Teacher does not implement Schooler, *Teacher does
s = &teacher
fmt.Printf("name:%v.age:%v\n", s.Name(), s.Age()) //name:Lucy.age:26
}
接口嵌套
package main
import (
"fmt"
)
type Peopler interface {
Name() string
Age() int
}
type Schooler interface {
Peopler
Role() string
}
type Student struct {
name string
age int
}
type Teacher struct {
name string
age int
}
func (s Student) Name() string {
return s.name
}
func (s Student) Age() int {
return s.age
}
func (s Student) Role() string {
return "Student"
}
func main() {
student := Student{name: "Jack", age: 10}
var p Peopler
var s Schooler
p = student
fmt.Printf("name:%v, age:%v\n", p.Name(), p.Age()) // name:Jack.age:10
s = student
fmt.Printf("name:%v, age:%v, role:%v\n", s.Name(), s.Age(), s.Role()) // name:Jack, age:10, role:Student
}
参考:https://studygolang.com/articles/20117
有疑问加站长微信联系(非本文作者)