Golang基础笔记九之方法与接口
本文首发于公众号:Hunter后端
原文链接:Golang基础笔记九之方法与接口
本篇笔记介绍 Golang 里方法和接口,以下是本篇笔记目录:
- 方法
- 接口
- 用结构体实现类的功能
1、方法
首先介绍一下方法。
方法是与特定类型关联的函数,我们在实现一个函数前,绑定一个类型,就实现了这个类型的方法。
比如我们想实现一个结构体的方法,可以如下操作:
type Person struct {
Name string
Age int
}
func (person Person) fmtPersonInfo() {
fmt.Printf("person name is %s, age is %d\n", person.Name, person.Age)
}
在上面的操作中,我们就为 Person 这个结构体绑定了一个方法,而其调用也很简单,就是实例化一个 Person 结构体后,就可以对其进行调用:
person := Person{Name: "Hunter", Age: 28}
person.fmtPersonInfo()
方法支持的类型
方法支持绑定的类型有结构体、指针类型、接口类型以及自定义类型,但是不支持绑定 Golang 内置的类型包括 int、slice、map 等。
方法绑定到指针类型
前面介绍了方法绑定到结构体上,这里再介绍一个绑定到指针类型上,还是前面的 Person 结构体,绑定到其指针上,来实现更改 Age 字段的操作:
func (person *Person) ChangeAge(age int) {
person.Age = age
}
person := Person{Name: "Hunter", Age: 28}
person.fmtPersonInfo()
person.ChangeAge(18)
person.fmtPersonInfo()
第二次打印信息就可以看到 person 的 age 已经发生了变化。
这里需要注意一点,Person 结构体是值类型,如果绑定的是其结构体本身,而非其指针类型,在方法中对其更改后,并不会影响结构体本身,比如下面的操作:
func (person Person) NewChangeAge(age int) {
person.Age = age
}
person := Person{Name: "Hunter", Age: 28}
person.fmtPersonInfo()
person.NewChangeAge(18)
person.fmtPersonInfo()
可以看到,这里调用 NewChangeAge() 方法后,没有对 person 这个结构体本身进行更改。
方法绑定到自定义类型
而如果想要绑定 int、slice、map 等内置类型,可以通过方法支持的自定义类型来绑定。
比如我们想要实现使用 slice 绑定一个打印其长度的方法,可以通过自定义类型设置一个别名,通过别名来绑定一个方法:
type MySlce []int
func (mySlice MySlce) printSliceLength() {
fmt.Printf("mySliceLength is %d\n", len(mySlice))
}
slice := MySlce{1, 2, 3}
slice.printSliceLength()
2、接口
1. 接口的定义和实现
接口是一组方法签名的集合,任何类型只要实现了接口中的所有方法,就被认为实现了该接口。
比如下面我们定义了一个形状的接口,内部有面积和周长两个空方法:
type Shape interface {
Area() float64
Perimeter() float64
}
这样我们就定义了一个接口。
而如果我们要实现这个接口,只需要实现这个接口里的两个方法 Area() 和 Perimeter() 就是实现了这个接口,这个过程是隐式的,不需要显式声明或者绑定。
接下来我们定义 Rectangle 和 Circle 两个结构体,并且实现 Area() 和 Perimeter() 两个方法:
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
type Circle struct {
radius float64
}
func (c Circle) Area() float64 {
return 3.14 * c.radius * c.radius
}
func (c Circle) Perimeter() float64 {
return 2 * 3.14 * c.radius
}
我们已经分别用 Rectangle 和 Circle 这两个结构体实现了 Shape 接口。
那么这个接口在这里有什么作用呢,我们可以实现一个函数,接收接口类型的参数,那么实现了这个接口的结构体都可以作为传入:
func PrintShapeInfo(s Shape) {
fmt.Println("Area: ", s.Area())
fmt.Println("Perimeter: ", s.Perimeter())
}
func main() {
r := Rectangle{Width: 2, Height: 3}
PrintShapeInfo(r)
c := Circle{Radius: 5}
PrintShapeInfo(c)
}
2. 类型断言
类型断言用于检查接口值的底层具体类型,并提取该类型的值,其用法示例如下:
value, ok := interfaceValue.(ConcreteType)
- value 是转换后的具体类型值
- ok 是一个布尔值,表示是否断言成功
- interfaceValue 是接口类型的变量
- ConcreteType 是目标具体类型。
比如我们可以修改 PrintShapeInfo 函数,在内部对其进行类型断言:
func PrintShapeInfo(s Shape) {
circle, ok := s.(Circle)
if ok {
fmt.Println("ths shape is circle, the area is: ", circle.Area())
} else {
fmt.Println("this shape is not circle")
}
fmt.Println("Area: ", s.Area())
fmt.Println("Perimeter: ", s.Perimeter())
}
3. 空接口
空接口(interface{}) 可以表示任何类型的值,常用于处理不确定类型的数据。
比如我们想打印一个输入的变量,但是这个变量的类型不确定,我们可以使用空接口来处理这种情况。
func PrintType(a interface{}) {
switch v := a.(type) {
case int:
fmt.Println("this is int: ", v)
case float64:
fmt.Println("this is float64: ", v)
case string:
fmt.Println("this is string: ", v)
default:
fmt.Println("this is other type: ", v)
}
}
func main() {
PrintType(1)
PrintType(3.4)
PrintType("abc")
}
3、用结构体实现类的功能
在 Golang 里没有类的相关定义,但是我们可以使用结构体和方法的组合来实现类的相关特性。
1. 封装
我们可以通过结构体字段的首字母大小写控制访问权限,然后提供公共方法来操作私有字段。
在结构体中,大写开头的字段为公开字段,小写开头的字段为私有字段。
我们用下面的示例来展示一下用结构体和方法来实现封装功能。
文件目录如下:
.
├── main.go
├── service
│ └── person_operation.go
其中 person_operation.go 的内容如下:
package service
type Person struct {
Name string
Age int
gender string
}
func (p *Person) SetGender(gender string) {
p.gender = gender
}
func (p *Person) GetGender() string {
return p.gender
}
其中,Person 这个结构体的 Name 和 Age 字段首字母都为大写,为公共字段,而 gender 首字母为小写,在 main.go 里不能直接引用,所以下面定义了两个公有接口提供设置和访问。
以下是 main.go 里的内容:
package main
import (
"fmt"
"go_proj/service"
)
func main() {
person := service.Person{
Name: "张三",
Age: 18,
// gender: "男", // gender是私有属性,不能直接访问
}
// fmt.Println(person.gender) // gender是私有属性,不能直接访问
fmt.Println(person.GetGender())
person.SetGender("男")
fmt.Println(person.GetGender())
}
在这里,gender 字段在 Person 定义和访问的时候都不能直接操作,需要通过设置的方法来进行定义以及访问。
2. 继承
我们可以通过结构体的嵌套来实现继承,比如下面新建一个 Chinese 结构体:
type Chinese struct {
Person
}
然后我们定义的 Chinese 实例可以调用 Person 结构体的方法:
chinese := service.Chinese{
Person: service.Person{
Name: "张三",
Age: 18,
},
}
chinese.SetGender("男")
fmt.Println(chinese.GetGender())
3. 多态
多态则是同一方法名在不同的类型中有不同的实现,这个操作在前面介绍接口的就已经实现过了,这里不再做赘述。
Golang基础笔记九之方法与接口的更多相关文章
- golang学习笔记---函数、方法和接口
函数:对应操作序列,是程序的基本组成元素. 函数有具名和匿名之分:具名函数一般对应于包级的函数,是匿名函数的一种特例,当匿名函数引用了外部作用域中的变量时就成了闭包函数,闭包函数是函数式编程语言的核心 ...
- Golang基础笔记
<基础> Go语言中的3个关键字用于标准的错误处理流程: defer,panic,recover. 定义一个名为f 的匿名函数: Go 不支持继承和重载. Go的goroutine概念:使 ...
- golang学习笔记--函数和方法
在go中,函数类型是一等类型,这意味着可以吧函数当做一个值来传递和使用. func divide(dividend int,divisor int)(int,error){ //省略部分代码 } 参数 ...
- Golang 中的 面向对象: 方法, 类, 方法继承, 接口, 多态的简单描述与实现
前言: Golang 相似与C语言, 基础语法与C基本一致,除了广受争议的 左花括号 必须与代码同行的问题, 别的基本差不多; 学会了C, 基本上万变不离其宗, 现在的高级语言身上都能看到C的影子; ...
- 带你学够浪:Go语言基础系列 - 10分钟学方法和接口
文章每周持续更新,原创不易,「三连」让更多人看到是对我最大的肯定.可以微信搜索公众号「 后端技术学堂 」第一时间阅读(一般比博客早更新一到两篇) 对于一般的语言使用者来说 ,20% 的语言特性就能够满 ...
- GoLang之方法与接口
GoLang之方法与接口 Go语言没有沿袭传统面向对象编程中的诸多概念,比如继承.虚函数.构造函数和析构函数.隐藏的this指针等. 方法 Go 语言中同时有函数和方法.方法就是一个包含了接受者的函数 ...
- golang方法和接口
一. go方法 go方法:在函数的func和函数名间增加一个特殊的接收器类型,接收器可以是结构体类型或非结构体类型.接收器可以在方法内部访问.创建一个接收器类型为Type的methodName方法. ...
- Java 多线程基础(九)join() 方法
Java 多线程基础(九)join 方法 一.join() 方法介绍 join() 定义 Thread 类中的,作用是:把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.如:线 ...
- Java基础语法<九> 接口与内部类
1 接口 interface implement 接口的所有方法自动地属于public.因此,在接口中声明方法时,不必提供关键字public. 接口可以包含多个方法,接口中可以定义常量.接口中的 ...
- golang基础--Interface接口
接口是一个或多个方法签名名的集合,定义方式如下 type Interface_Name interface { method_a() string method_b() int .... } 只要某个 ...
随机推荐
- 【Ubuntu】安装Eclipse
[Ubuntu]安装Eclipse 零.前言 Eclipse是一个使用很广泛的代码编辑软件,最近换了Ubuntu系统,需要安装一下,故记录. 壹.下载 Eclipse到官网下载,或者到镜像源下载,官网 ...
- 使用Nginx反向代理本地服务(无固定公网IP通过端口映射公开的服务)的坑
使用Nginx反向代理本地服务(无固定公网IP通过端口映射公开的服务)的坑 前言:之前公司的服务器都是云服务器,性能比较差,而我们有一些内部使用的系统和极少数外部用户使用的系统,对资源有一定的要求,也 ...
- 快戳进来!PostgreSQL实战型系列文章来了!
快戳进来!PostgreSQL实战型系列文章来了! Whoami:6年+金融.政府.医疗领域工作经验的DBA Certificate:PGCM.OCP.YCP Skill:Oracle.Mysql.P ...
- CountDownLatch的countDown()方法的底层源码
一.CountDownLatch的构造方法 // 创建倒数闩,设置倒数的总数State的值 CountDownLatch doneSignal = new CountDownLatch(N); 二.c ...
- 从零实现富文本编辑器#2-基于MVC模式的编辑器架构设计
在先前的规划中我们是需要实现MVC架构的编辑器,将应用程序分为控制器.模型.视图三个核心组件,通过控制器执行命令时会修改当前的数据模型,进而表现到视图的渲染上.简单来说就是构建一个描述文档结构与内容的 ...
- eolinker响应预处理:返回结果内循环读取同类数据,设置为变量
特别注意:需要使用全局变量或者预处理前务必阅读本链接https://www.cnblogs.com/becks/p/13713278.html 场景描述: 删除(清空)购物车接口,需要传入获取的每一项 ...
- SpringBoot3整合SpringSecurity6(二)SpringSecurity默默的干了些啥
写在前面 第一节中,我们基本上就引入SpringSecurity依赖,其他什么都没做就完成了认证功能. 之所以我们不用做什么,是因为SpringSecurity默认实现了很多功能. 当然了,这里默认实 ...
- Java单例模式:从实战到面试的深度解析
结论先行 饿汉式:线程安全但可能造成资源浪费,推荐在初始化成本低的场景使用 懒汉式:需要解决线程安全问题,推荐使用双重检查锁+volatile优化 静态内部类:最佳实践方案,完美平衡延迟加载与线程安全 ...
- 【记录】PDF|中英文PDF扫描版目录提取(一、QQ+GPT)
需求: 1)从PDF里快速提取目录: 2)不想下载任何软件. 文章目录 一.用现有常用软件直接导出目录 1 (推荐指数☆)QQ OCR文字识别 2 (推荐指数0星)GPT4 图像识别 3 (推荐指数0 ...
- 一站式搭建交友平台-交友系统源码-支持H5小程序+带安装说明+可封装APP-交友网站系统平台搭建
诺诺婚恋交友系统 1.系统基于TP6+Uni-app框架开发:客户移动端采用uni-app开发,管理后台TH6开发. 2.系统支持微信公众号端.微信小程序端.H5端.PC端多端账号同步,可快速打包生成 ...