当前位置:网站首页>【GO】go语言interface
【GO】go语言interface
2022-06-22 21:24:00 【weixin_43224306】
Go 接口实现机制很简洁,只要目标类型方法集内包含接口声明的全部方法,就被视为实现了该接口,无须做显示声明。当然,目标类型可实现多个接口。这样做的好处有:我们可以先实现类型,再抽象出所需要的接口。
同时在 Go 语言中没有继承的概念,所以结构、接口之间也没有父子关系,Go 语言提倡的是组合,利用组合达到代码复用的目的,这也更灵活。
从内部实现来看,接口自身也是一种结构类型,但是编译器会对其做出很多限制:
- 不能有字段
- 不能定义自己的方法
- 只能声明方法,不能实现
- 可嵌入其他接口类型
接口通常以er作为名称后缀。
空接口
如果接口interface{}没有声明任何方法,那么就是一个空接口,它的用途类似面向对象里的根类型Object,可被赋值为任何类型的对象。
var i interface{} = 1
fmt.Println(i)
Go 中的interface{} 常常用于参数传递,用以帮助实现其他语言中的泛型效果:比如下面的 Foo 函数中是个业务处理相关的函数,需要一个bucketId,上层传入的可能是字符串形式"1234",也可能是一个数字形式1234
func Foo(arg interface{}) (err error) {
bucketId, err := parseBucketIdParam(arg)
if err != nil {
return err
}
// 下面就是正常业务处理
fmt.Println("bucketId: ", bucketId)
return
}
func parseBucketIdParam(arg interface{}) (bucketId int64, err error) {
if bucketIdStr, ok := arg.(string); ok {
bucketId, err = strconv.ParseInt(bucketIdStr, 10, 64)
if err != nil {
return
}
} else if bucketIdInt, ok := arg.(int); ok {
bucketId = int64(bucketIdInt)
} else if bucketIdInt64, ok := arg.(int64); ok {
bucketId = bucketIdInt64
} else {
err = fmt.Errorf("not support bucketId param")
}
return
}
如果需要转换的类型过多,if else 语句冗长,那么可以使用 type-switch,更灵活
func foo(v interface{}) {
switch v.(type) {
case nil:
fmt.Println("type is nil")
case int:
fmt.Println("type is int")
case string:
fmt.Println("type is string")
default:
fmt.Println("unknown type")
}
}
foo(123)
foo("123")
但是需要注意的是 type-switch 不支持 fallthrought
匿名接口
可以在接口中嵌入其他匿名接口,那么目标类型方法集中必须拥有包含嵌入接口方法在内的全部方法才算实现了该接口。同时,不能嵌入自身或循环嵌入,那样会导致递归嵌入。
type stringer interface {
string() string
}
type tester interface {
stringer
test()
}
type data struct{}
func (*data) test() {
//...
}
// 必须实现 stringer 接口
func (data) string() string {
// ...
}
接口与多态
type Eater interface{
Eat()
}
type Cat struct {
}
func (cat Cat) Eat() {
fmt.Println("eat fish")
}
type Dog struct {
}
func (dog Dog) Eat() {
fmt.Println("eat bone")
}
func Foo(i Eater) {
i.Eat()
}
func main() {
cat := Cat{}
Foo(cat)
dog := Dog{}
Foo(dog)
}
输出:
image.png
接口可以比较吗?
interface 在某些场景下可以比较。
- 不带方法的 interface:
type Fooer interface { } type Barer interface { } func main() { var foo Fooer var bar Barer fmt.Println(foo == bar) // 输出true fooInstance := 1 barInstance := 1 fmt.Println(fooInstance == barInstance) // 输出为true fooInstance2 := 1 barInstance2 := 10 fmt.Println(fooInstance2 == barInstance2) // 输出为false } - 带有方法的 interface,且方法名相同:
type Fooer interface { value() int } type Barer interface { value() int } type Foo int func (foo Foo) value() int { return 1 } type Bar int func (bar Bar) value() int { return 1 } func main() { var foo Fooer var bar Barer fmt.Println(foo == bar) // 输出true fooInstance := Foo(10) barInstance := Bar(10) fmt.Println(fooInstance == barInstance) // invalid operation: fooInstance == barInstance (mismatched types Foo and Bar) } - 带有方法的 interface,且方法名不同:
type Fooer interface { FooerValue() int } type Barer interface { BarerValue() int } type Foo int func (foo Foo) FooerValue() int { return 1 } type Bar int func (bar Bar) BarerValue() int { return 1 } func main() { var foo Fooer var bar Barer fmt.Println(foo == bar) // invalid operation: foo == bar (mismatched types Fooer and Barer) fooInstance := Foo(10) barInstance := Bar(10) fmt.Println(fooInstance == barInstance) // invalid operation: fooInstance == barInstance (mismatched types Foo and Bar) } - interface 和 nil 比较
type Fooer interface { FooerValue() int } type Foo int func (foo Foo) FooerValue() int { return 1 } func main() { var foo Fooer fmt.Println(nil == foo) // true fooInstance := Foo(10) fmt.Println(nil == fooInstance) // invalid operation: fooInstance == barInstance (mismatched types Foo and Bar) }
边栏推荐
- 获取鼠标移动的方向
- 剑指 Offer 06. 从尾到头打印链表
- 【22暑期复建1】 Codeforces Round #791 (Div. 2)
- 事物系统的几种异常场景
- Future alternatives to IPv4! Read the advantages, features and address types of IPv6
- LeetCode_ Backtracking_ Dynamic programming_ Medium_ 131. split palindrome string
- DML:Data Manipulation Language 数据操纵语言
- 剑指 Offer 05. 替换空格
- 企业数字化不是各自发展,而是全面SaaS化推进
- Canvas generate Poster
猜你喜欢

Learning the interpretable representation of quantum entanglement, the depth generation model can be directly applied to other physical systems

Redis cache

弱电转职业网工难不难?华为售前工程师分享亲身经历

wallys/WiFi6 MiniPCIe Module 2T2R 2 × 2.4GHz 2x5GHz

Enterprise digitalization is not a separate development, but a comprehensive SaaS promotion

Freshman girls' nonsense programming is popular! Those who understand programming are tied with Q after reading

flutter外包,承接flutter项目

'dare not doubt the code, but have to doubt the code 'a network request timeout analysis

同步电路与跨时钟域电路设计2——多bit信号的跨时钟域传输(FIFO)

Leakcanary source code (2)
随机推荐
WebRTC系列-网络传输之4Connection排序
Redis cache
Optimization - linear programming
[arm] it is reported that horizontal display is set for LVDS screen of rk3568 development board
如何使用enum数据类型
JSBridge
Enterprise digitalization is not a separate development, but a comprehensive SaaS promotion
剑指 Offer 06. 从尾到头打印链表
Freshman girls' nonsense programming is popular! Those who understand programming are tied with Q after reading
SOA Service Oriented Architecture
防抖&节流 加强版
Finding the value of the nth term of Fibonacci sequence by recursion
C language greedy snake
[kubernetes series] overview of kubernetes
多种方案实现图片的懒加载
10 Super VIM plug-ins, I can't put them down
os.Args[1:]中命令行参数为空时,不执行内部语句
Uniapp modifies array properties, and the view is not updated
OJ每日一练——过滤多余的空格
flink同步mysql数据到ES