go基础-方法
概述
方法是面向对象编程 (OOP) 的一个特性,在 C++/Java 语言中方法是类函数,go做为函数式编程语言,通过特有技能支持相似的功能,所以说go也支持面向对象编程特性。
go 方法本质也是函数,相比普通函数稍有区别,方法必须与具体类型绑定,且无法独立运行,只能通过类型实例执行,函数是一等公民,方法是二等公民。方法很像面向对象的类方法,但又有区别,方法更加松散,耦合性更低。类方法是定义在对象内部,go方法更像是一种属性扩展,在不修改类型定义的情况下可扩展方法,比如可为外部引入的结构体增加方法,这在Java、C#等面向对象语言是不允许的。
基本使用
方法可以绑定到任意类型,但是实际情况总是与结构体绑定,两者结合可以模拟面向对象特性,当然仅是模拟,文章主要使用结构体演示。
定义类型
type Person struct {
Age int
Name string
}
为结构体定义方法
func (p *Person) sayHi() { // 为结构体定义了一个方法
fmt.Println("hi, I'm ", p.Name)
}
相比普通函数定义稍有区别,在func关键字和函数名之间增加一个接收器,或称为接收者、连接器等,如上接收器是Person类型指针。与接收器参数匹配的类型,就增加了一个新方法,目前观察这是go的独创。
方法方必须依实例,无法独立执行。与面型对象中方法一样,先有对象,才能调用方法。
sayHi() // error undefined: sayHi
必须通过结构体实例调用,会自动把实例传递给方法的接收器,类似Java的this、Python的self,隐式传递第一个参数。
p1 := Person{Name: "tom"}
p1.sayHi() // hi, I'm tom
为简单理解,编译后伪代码如下
func sayHi(self) { // self是体结构体指针
fmt.Println("hi, I'm ", self.Name)
}
接收器参数类型,除非有明确需求,否则都应该使用指针。同样的问题,使用值类型本质是每次调用,都传入复制的新实例。
func (p Person) sayHi() {
p.name = "tony"
fmt.Println("hi, I'm ", p.Name) // tony
}
func main() {
p1 := Person{Name: "tom"}
p1.sayHi() // 复制新结构体传递给sayHi
fmt.Println(p1.Name) // tom
}
语法层面没有限制,允许为任何类型创建方法,包括基础数据类型。但是有一个限制,方法和类型定义必须在同一个包,为基础数据类型、或引入第三方类型定义方法需要一些变通,先使用type定义类型,在扩展方法。
为基本数据类型扩展方法
type Integer int
func (m *Integer) Value() {
fmt.Println(*m)
}
使用方法
var m Integer = 10
m.Value() // 10
假如Person是从第三方引入的类型,为其扩展新方法
type MyPerson Person
func (m *MyPerson) getName() {
return Person(*m).Name // 先强制转为Person类型,再读取Name属性
}
使用方法
p1 := MyPerson{Name: "tom"}
p1.getName()
p1.sayHi // err
sayHi是Person结构体的方法,无法通过MyPerson类型访问,也不支持常规的继承
更优雅是使用组合的方式(继承模式),Go 语言不支持传统面向对象中的继承特性,而是以自己特有的组合方式支持了方法的继承,通过在结构体内置匿名的成员来实现继承
type MyPerson struct {
City string
Person // 匿名属性
}
func (m *MyPerson) getCity() {
return m.City
}
使用方法
p1 := MyPerson{City: "shanghai"}
p1.getCity() // shanghai
p1.sayHi() // ok,调用继承方法
被继承的对象称为基础类型,属性、方法都可以被继承,注意继承方法在调用时连接器接收的对象是原始对象,如上案例中sayHi接收的是Person对象,而非MyPerson对象,这种展开是编译期完成的, 并没有运行时代价。这与C++、C#、Java主流面向对象语言不同,子类方法在运行时动态绑定到对象,因此基类某些方法看到的 this 可能不是基类类型对应的对象,这个特性会导致基类方法运行的不确定性。
方法是由函数演变而来,只是将函数第一个参数移动到函数名前面而已,方法是特殊的函数。两者特性几乎一样,比如都是值传递、都不支持重载,甚至通过方法表达式可以将方法还原为普通函数
sayHi := (*Person).sayHi // 方法转换为函数
p := &Person{Age: 1, Name: "xk"} // 创建结构体
sayHi(p) // 调用转换后的函数
转换为普通函数后,将接收器转换为函数的第一个参数,调用时候需要显示传递参数。
go基础-方法的更多相关文章
- 在同一个Apache服务器软件上部署多个站点的基础方法
这篇文章主要介绍了Apache中Virtual Host虚拟主机配置及rewrite模块中的重要参数说明,是在同一个Apache服务器软件上部署多个站点的基础方法,需要的朋友可以参考下(http:// ...
- CodeBlocks(17.12) 代码调试基础方法&快捷方式
转载:CodeBlocks(17.12) 代码调试基础方法&快捷方式: https://www.cnblogs.com/DCD112358/p/8998053.html
- Python_Mix*re模块基础方法,进阶,正则表达式的使用
re模块import re 基础方法 findall:匹配所有 ,每一项都是列表中的一个元素,返回的是列表 search只匹配从左到右的第一个,得到的不是直接的结果,而是一个变量,通过这个变量的gro ...
- RF实现多次失败重跑结果合并的基础方法和优化方法
实现思路:通过分次执行失败案例重跑,然后通过结果文件合并命令实现多次失败重跑结果文件的合并,并输出合并后的log和report文件: 说明:具体失败案例重跑命令和结果文件合并命令请参考本博客其他相关章 ...
- Java基础-方法(method)的应用
Java基础-方法(method)的应用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 方法就是定义在类中,具有特定功能的一段小程序,方法也称为函数(function),方法可以接 ...
- 实现同时提交多个form(基础方法) 收集
实现同时提交多个form(基础方法) 收集 分类: 1.2-JSP 1.3-J2EE 1.1J2se 1.0-Java相关2011-12-01 20:59 1644人阅读 评论(0) 收藏 举报 bu ...
- java发送邮件基础方法(另附部分主流邮箱服务器地址、端口及设置方法)
java发送邮件基础方法,可通过重载简化参数 import java.io.File; import java.io.UnsupportedEncodingException; import java ...
- 【JavaScript】数组方法之基础方法
数组方法之基础方法 Array 对象属性 属性 描述 constructor 返回对创建此对象的数组函数的引用. length 设置或返回数组中元素的数目. prototype 使您有能力向对象添加属 ...
- Java基础——方法的调用
Java基础--方法的调用 总结: 1. 在同一个类中-- 对于静态方法,其他的静态和非静态方法都可以直接通过"方法名"或者"类名.方法名"调用它. 对 ...
- 《Java基础——方法的调用》
Java基础--方法的调用 总结: 1. 在同一个类中-- 对于静态方法,其它的静态和非静态方法都可以直接通过"方法名"或者"类名.方法名"调用它. 对 ...
随机推荐
- TypeScript: 类型别名
类型别名 在 TYPESCRIPT 中,类型别名可以使用 TYPE 关键字来定义.类型别名可以方便地定义一个类型,并为其起一个易于理解的名称,以便在其他地方引用该类型时使用. 示例 type MySt ...
- 解决:vue-loader was used without the corresponding plugin.
原因 webpack经常出现版本不兼容问题,vue-loader在15以前的版本打包时候会自动生成VueLoaderPlugin,但是现在需要手动去wepack.config.js文件中去加入,如下图 ...
- Linux文件管理知识查找文件
Linux文件管理知识:查找文件 前几篇文章一一介绍了LINUX进程管理控制命令及网络层面的知识体系,综所周知,一个linux系统是由很多文件组成的,那么既然有那么多文件,那我们该如何管理这些文件呢? ...
- @ControllerAdvice 注解使用及原理探究
最近在新项目的开发过程中,遇到了个问题,需要将一些异常的业务流程返回给前端,需要提供给前端不同的响应码,前端再在次基础上做提示语言的国际化适配.这些异常流程涉及业务层和控制层的各个地方,如果每个地方都 ...
- 【go笔记】使用sqlx操作MySQL
前言 go在操作MySQL时,可以使用ORM(比如gorm.xorm),也可以使用原生sql.本文以使用sqlx为例,简单记录步骤. go version: 1.16 安装相关库 # mysql驱动 ...
- 介绍 SafeCoder 解决方案服务
今天这篇推文,我们打算给自己打一波"广告",向大家隆重介绍 SafeCoder-- 一款专为企业打造的代码助手解决方案. SafeCoder 旨在成为你完全合规且自托管的结对编程工 ...
- Java爬虫实战系列——常用的Java网络爬虫库
常用的Java网络爬虫库 Java 开发语言是业界使用最广泛的开发语言之一,在互联网从业者中具有广泛的使用者,Java 网络爬虫可以帮助 Java 开发人员以快速.简单但广泛的方式为各种目的抓取数据. ...
- API接口开发管理平台--多领域企业数字化管理解决方案
随着数字化时代的到来,企业需要进行数字化转型才能更好地适应市场需求和用户需求.而API接口则是数字化转型中的重要组成部分,可以帮助企业更好地管理信息,提高效率.本文将介绍挖数据解决方案--API接口开 ...
- SQL Server更改表字段顺序和表结构
1.首先打开SqlServer,SSMS可视化工具.点击工具,再点选项. 2.在弹出的选项窗口中,点击Desinners,点击表设计和数据库设计器,将阻止保护勾去掉.点"确定" 3 ...
- 5.0 CRC32校验技术概述
CRC校验技术是用于检测数据传输或存储过程中是否出现了错误的一种方法,校验算法可以通过计算应用与数据的循环冗余校验(CRC)检验值来检测任何数据损坏.通过运用本校验技术我们可以实现对特定内存区域以及磁 ...