为了账号安全,请及时绑定邮箱和手机立即绑定

Go 快速入门指南 - 接口和方法

标签:
Go

接口

Go 接口是隐式实现。 对于一个数据类型,无需声明它实现了哪些接口,只需要实现接口必需的方法即可。当然了,存在一个小问题就是: 我们可能无意间实现了某个接口:) ,所以 命名 是多么重要的一件事情。

语法规则

type 接口名称 interface {
    方法1名称(参数列表 ...) 返回值列表...
    方法2名称(参数列表 ...) 返回值列表...
    方法3名称(参数列表 ...) 返回值列表...
    ...
    ...
}

例子

求矩形和圆的周长, 面积

package main

import (
    "fmt"
    "math"
)

// 声明一个图形接口
type geometry interface {
    area() float64
    perimeter() float64
}

// 多个字段类型相同时,可以并列声明
type rectangle struct {
    width, height float64
}

type circle struct {
    radius float64
}

// rectangle 隐式实现了 geometry 接口的 area 方法
func (r *rectangle) area() float64 {
    return r.width * r.height
}

// rectangle 隐式实现了 geometry 接口的 perimeter 方法
func (r *rectangle) perimeter() float64 {
    return (r.width + r.height) * 2
}

// circle 隐式实现了 geometry 接口的 area 方法
func (c *circle) area() float64 {
    return math.Pi * c.radius * c.radius
}

// circle 隐式实现了 geometry 接口的 perimeter 方法
func (c *circle) perimeter() float64 {
    return 2 * math.Pi * c.radius
}

func main() {
    r := &rectangle{
        width:  10,
        height: 5,
    }
    fmt.Printf("Rectangle area = %.2f, perimeter = %.2f \n", r.area(), r.perimeter())

    c := &circle{
        radius: 10,
    }
    fmt.Printf("Circle area = %.2f, perimeter = %.2f \n", c.area(), c.perimeter())
}

// $ go run main.go
// 输出如下 
/**
  Rectangle area = 50.00, perimeter = 30.00
  Circle area = 314.16, perimeter = 62.83
*/

方法

方法的声明和普通函数的声明类似,只是在函数名字前面多了一个 接收者参数 (接收者参数将方法绑定到其对应的数据类型上)。方法可以绑定到任何数据类型上,但是大多数情况下,绑定的都是 结构体。

语法规则

func (接收者参数) 方法名称(参数列表 ...) 返回值列表... {
    // do something
}

例子

结构体方法

package main

import "fmt"

type person struct {
    name string
    age  int16
}

func (p person) sayName() {
    fmt.Printf("Hi, my name is %s\n", p.name)
}

func (p person) sayAge() {
    fmt.Printf("Hi, my age is %d\n", p.age)
}

func main() {
    tom := &person{
        name: "Tom",
        age:  6,
    }
    tom.sayName()
    tom.sayAge()
}

// $ go run main.go
// 输出如下 
/**
  Hi, my name is Tom
  Hi, my age is 6
*/

结构体指针方法

相比结构体方法,指针结构体方法除了将方法参数变为指针外,在引用对应的字段时,无需加 * 标识符, 这一点和普通指针变量引用时有所区别,需要注意。

package main

import "fmt"

type person struct {
    name string
    age  int16
}

func (p *person) sayName() { // 结构体为指针类型
    fmt.Printf("Hi, my name is %s\n", p.name)
}

func (p *person) sayAge() { // 结构体为指针类型
    fmt.Printf("Hi, my age is %d\n", p.age)
}

func main() {
    tom := &person{
        name: "Tom",
        age:  6,
    }
    tom.sayName()
    tom.sayAge()
}

// $ go run main.go
// 输出如下 
/**
  Hi, my name is Tom
  Hi, my age is 6
*/

编译检测

编译器会对方法的 接收者参数 进行检查,具体来说:

  • • 接收者形参为普通变量类型

    • • 实参为普通变量类型,编译正常

    • • 实参为指针变量类型,编译正常

  • • 接收者形参为指针变量类型

    • 实参为普通变量类型,编译报错

    • • 实参为指针变量类型,编译正常

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
全栈工程师
手记
粉丝
0
获赞与收藏
0

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消