Golang方法和接口

简介: 在编程语言中,方法和函数的概念需要搞清楚。函数指的是一个封装的代码块,我们可以直接调用它,并返回结果。而方法其实也是一种函数,只不过方法需要和某个对象绑定。

在编程语言中,方法和函数的概念需要搞清楚。函数指的是一个封装的代码块,我们可以直接调用它,并返回结果。而方法其实也是一种函数,只不过方法需要和某个对象绑定。Golang并没有类的概念,不过仍然有方法和接口这些概念。

方法

方法接收者

方法接收者是一个特殊参数,给函数指定了这个参数之后,函数就成为方法了。这个特性有点像Kotlin和C#中的扩展方法,定义了带有接收者的方法之后,接收者这个类型就好像定义了这个方法一样,我们可以直接在该类型上调用方法。这在功能上,和面向对象的概念是很类似的。

例如下面这样,定义了一个汽车结构,然后定义了一个接受者方法。然后就可以用面向对象的方式来调用这个方法了。

func Method() {
    //方法接收者
    car := Car{id: 1}
    car.beep()
}

type Car struct {
    id int
}

func (car Car) beep() {
    fmt.Printf("Car %v beeps", car.id)
}

接收者方法也有一些限制,这也是它和扩展方法之间的区别。接收者方法的接受者类型,必须和接收者方法定义在同一个包中。所以很多非自定义的类型,以及基本类型都不能当做接收者的类型。当然也可以投机取巧,在自己的包中重新为这些类型取个名字即可。

//把基本类型重新定义一下,就可以当做接收者类型了
type MyString string

func (str MyString) hello() {
    fmt.Println("hello" + str)
}

指针接收者

接收者的类型可以是指针,如果希望在接收者方法中修改接收者的属性,就需要指针类型了。下面的代码对Car结构体添加了两个方法,第一个由于没有指针类型,所以不会修改原始结构体中的值;而第二个方法会修改汽车的id。

func (car Car) beep() {
    fmt.Printf("Car %v beeps", car.id)
}

func (car Car) changeId() {
    car.id += 1
}
func (car *Car) changeRealId() {
    car.id += 1
}

接口

听起来很奇怪,如果Golang没有类型,为什么会有接口的概念?让我们来看看Golang如何解决这些问题。

定义接口

在Golang中,接口就是一组方法签名的集合。下面就定义了一个接口。

type ICar interface {
    beep()
    drive(driver string)
}

实现接口

在Golang中,其实并没有“实现接口”这一说法。在Golang中接口是隐式实现的,也就是说我们不需要implements这些关键字。只要一个类型的接收者方法和接口中定义的方法一致,Golang就认为这个类型实现了该接口。下面是一个简单的例子。

func Interface() {
    car := MyCar{id: 1}
    var icar ICar = car
    icar.beep()
    icar.drive("yitian")
}

type ICar interface {
    beep()
    drive(driver string)
}

type MyCar struct {
    id int
}

func (car MyCar) beep() {
    fmt.Printf("car %v beeps\n", car.id)
}
func (car MyCar) drive(driver string) {
    fmt.Printf("%v drives car %v\n", driver, car.id)
}

空接口

什么方法都没定义的接口就是空接口。根据Golang的概念,空接口被任何类型隐式实现,所以空接口可以容纳任何类型。

//空接口可以作为任何类型使用
type Everything interface {
}

var e Everything = "123"
fmt.Println(e)

类型细化

定义和实现接口是一个类型泛化的过程,在这个过程中,我们抹消掉了类型特有的部分,让类型公有的部分能够统一利用。不过有时候需要反过来,将一个接口对象转换为原始的具体类,让我们能够获取更具体的行为。

现在来看看在Golang中,这件事情应该怎么做。再次使用上面定义的类型。可以看到和C系语言的括号强转方式不同,在Golang中是.(T)类型的语法。

//特化类型
myCar := icar.(MyCar)
//myCar是MyCar类型变量
myCar.beep()

这个语法还有一个携带一个成功标志的版本 t, ok := i.(T)。当成功标志为真时,表示成功将接口转换为具体类型,否则表示该接口不是具体类型的实例。

如果要进行多次判断,可以利用switch语句。下面是一个例子。

func testType(i interface{}) {
    switch i.(type) {
    case string:
        fmt.Printf("%v is string\n", i)
    case int:
        fmt.Printf("%v is int\n", i)
    default:
        fmt.Printf("%v is interface{}\n", i)
    }
}

对这个方法调用多次,可以看到针对不同的类型,方法会返回不同结果。

//类型检测
testType("abc")
testType(123)
testType(nil)
相关文章
|
1月前
|
Go
|
3月前
|
存储 设计模式 Cloud Native
云原生系列Go语言篇-类型、方法和接口 Part 1
通过前面章节的学习,我们知道Go是一种静态类型语言,包含有内置类型和用户定义类型。和大部分现代编程语言一样,Go允许我们对类型关联方法。它也具备类型抽象,可以编写没有显式实现的方法。
50 0
|
4月前
|
Go
Go string bytes、strings、strconv和unicode包相关方法
Go string bytes、strings、strconv和unicode包相关方法
26 0
|
23天前
|
存储 安全 Go
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
|
1月前
|
设计模式 缓存 安全
一篇文章带你吃透Go语言的Atomic和Channel--实战方法
一篇文章带你吃透Go语言的Atomic和Channel--实战方法
29 0
|
1月前
|
安全 Go
接口在Go语言中的实现与应用
【2月更文挑战第19天】接口是Go语言中一种重要的抽象机制,它定义了一组方法的集合,而不关注具体的实现。本文将深入探讨Go语言中接口的实现方式、接口的应用场景以及接口在Go语言设计中的优势,帮助读者更好地理解和应用接口。
|
2月前
|
Cloud Native Go 数据库
一文搞懂Go搭建Restful接口
一文搞懂Go搭建Restful接口
18 0
|
3月前
|
Go Java C++
Golang每日一练(leetDay0031) 解码方法、复原 IP 地址
Golang每日一练(leetDay0031) 解码方法、复原 IP 地址
34 0
Golang每日一练(leetDay0031) 解码方法、复原 IP 地址
|
3月前
|
编译器 Go
go语言第六章(结构体与方法)
go语言第六章(结构体与方法)
22 0
|
3月前
|
编译器 Go
浅谈Golang T和*T方法集的关系
浅谈Golang T和*T方法集的关系
22 0