接口/类型断言
1.定义
Interface是类型可以定义一组方法,但是这些不需要实现。并且interface不能包含任何变量。
比如:
望都网站建设公司创新互联建站,望都网站设计制作,有大型网站制作公司丰富经验。已为望都成百上千家提供企业网站建设服务。企业网站搭建\成都外贸网站建设要多少钱,请找那个售后服务好的望都做网站的公司定做!
type example interface{
Method1(参数列表) 返回值列表
Method2(参数列表) 返回值列表
…
}
2.interface类型默认是一个指针
type example interface{
Method1(参数列表) 返回值列表
Method2(参数列表) 返回值列表
…
}
var a example
a.Method1()
3.接口实现
a. Golang中的接口,不需要显示的实现。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此,golang中没有implement类似的关键字
b. 如果一个变量含有了多个interface类型的方法,那么这个变量就实现了多个接口。
c. 如果一个变量只含有了1个interface的方部分方法,那么这个变量没有实现这个接口。
4.多态
一种事物的多种形态,都可以按照统一的接口进行操作
5.接口嵌套
一个接口可以嵌套在另外的接口,如下所示:
type ReadWrite interface {
Read(b Buffer) bool
Write(b Buffer) bool
}
type Lock interface {
Lock()
Unlock()
}
type File interface {
ReadWrite
Lock
Close()
}
- 类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型可以采用以下方法进行转换:
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,带检查
7.练习,写一个函数判断传入参数的类型
func classifier(items ...interface{}) {
for i, x := range items {
switch x.(type) {
case bool: fmt.Printf(“param #%d is a bool\n”, i)
case float64: fmt.Printf(“param #%d is a float64\n”, i)
case int, int64: fmt.Printf(“param #%d is an int\n”, i)
case nil: fmt.Printf(“param #%d is nil\n”, i)
case string: fmt.Printf(“param #%d is a string\n”, i)
default: fmt.Printf(“param #%d’s type is unknown\n”, i)
}
}
8.类型断言,采用type switch方式
switch t := areaIntf.(type) {case *Square: fmt.Printf(“Type Square %T with value %v\n”, t, t)
case *Circle: fmt.Printf(“Type Circle %T with value %v\n”, t, t)
case float32: fmt.Printf(“Type float32 with value %v\n”, t)case nil: fmt.Println(“nil value: nothing to check?”)
default: fmt.Printf(“Unexpected type %T”, t)}
9.空接口,Interface{}
空接口没有任何方法,所以所有类型都实现了空接口。
var a int
var b interface{}
b = a
10.判断一个变量是否实现了指定接口
判断一个变量是否实现了指定接口
type Stringer interface {
String() string
}
var v MyStruct
if sv, ok := v.(Stringer); ok {
fmt.Printf(“v implements String(): %s\n”, sv.String());
}
package main
import "fmt"
//没有方法的空接口,任何类型都可以
type Test interface {}
func main() {
var a interface{}
a = 666
fmt.Println(a)
fmt.Printf("a的类型是:%T", a)
}
输出:
666
a的类型是:int
Process finished with exit code 0
package main
import "fmt"
//接口里的方法必须全部实现!
type Carer interface {
GetName() string
Run()
DiDi()
}
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 main() {
var car Carer
//如果接口中的方法只声明不实现,则是nil
//fmt.Println(car)
//不实现Run方法而调用会报错
//car.Run()
var bmw BMW
bmw.Name = "x6"
//因为struct BMW是指针类型,所以bmw要引用传递
car = &bmw
car.Run()
}
输出:
x6 is running
Process finished with exit code 0
也可以值传递:
package main
import "fmt"
//接口里的方法必须全部实现!
type Carer interface {
GetName() string
Run()
DiDi()
}
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 main() {
var car Carer
//如果接口中的方法只声明不实现,则是nil
//fmt.Println(car)
//不实现Run方法而调用会报错
//car.Run()
var bmw BMW
bmw.Name = "x6"
//值类型传递也是可以的,上面的p *BMW也要换成p BMW
car = bmw
car.Run()
}
应用实例:
go语言的sort包是用接口方式写的,可以轻松的自定义:
package main
import (
"fmt"
"math/rand"
"sort"
)
type Student struct {
Name string
Id string
Age int
}
type Book struct {
Name string
Author string
}
//切片默认就是传地址的,所以不需要在方法中用*
type studentArray []Student
func (p studentArray) Len() int {
return len(p)
}
func (p studentArray) Less(i, j int) bool {
return p[i].Name < p[j].Name
}
func (p studentArray) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
}
func main() {
var stus studentArray
for i := 0; i < 5; i++ {
stu := Student{
Name: fmt.Sprintf("stu%d", rand.Intn(100)),
Id: fmt.Sprintf("100%d", rand.Int()),
Age: rand.Intn(100),
}
stus = append(stus, stu)
}
for _, v := range stus {
fmt.Println(v)
}
fmt.Println("")
//调用sort包进行排序(stus中用自带的方法)
sort.Sort(stus)
for _, v := range stus {
fmt.Println(v)
}
}
输出:
{stu81 1008674665223082153551 47}
{stu59 1003916589616287113937 18}
{stu25 1001443635317331776148 56}
{stu0 1004751997750760398084 11}
{stu62 1003510942875414458836 28}
{stu0 1004751997750760398084 11}
{stu25 1001443635317331776148 56}
{stu59 1003916589616287113937 18}
{stu62 1003510942875414458836 28}
{stu81 1008674665223082153551 47}
Process finished with exit code 0
类型断言实例:
package main
import "fmt"
func main() {
var a interface{}
fmt.Printf("%T\n", a)
var b int
a = b
c := a.(int)
fmt.Printf("%T\n", a)
fmt.Printf("%T\n", c)
}
输出:
int
int
Process finished with exit code 0
package main
import "fmt"
func duanYan(a interface{}) {
//int(a)是数据类型的转换,这是接口转成具体类
b, ok := a.(int)
if ok == false {
fmt.Println("转换失败")
return
}
b += 3
fmt.Println(b)
}
func main() {
//b是int型则转换成功,string型转换失败
var b int
duanYan(b)
}
输出:
3
Process finished with exit code 0
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)
}
输出:
{stu01 female}
0 params is int, value is 28
1 params is float, value is 8.2
2 params is string, value is this is a test
3 params student, value is {stu01 female}
4 params *student, value is &{stu01 female}
Process finished with exit code 0
分享名称:接口/类型断言
网页网址:http://azwzsj.com/article/jsdeie.html