golang 方法
方法:
在函数声明时,在其名字之前放上一个变量,即是一个方法。这个附加的参数会将该函数附 加到这种类型上,即相当于为这种类型定义了一个独占的方法。
package main
import "math"
type Point struct {
X,Y float64
}
func Distance(p, q Point) float64 {
return math.Hypot(q.X - p.X, q.Y - p.Y)
}
//Point 类型的方法
func(p Point) Distance(p, q Point) float64 {
return math.Hypot(q.X - p.X, q.Y - p.Y)
}
上面的代码里那个附加的参数p,叫做方法的接收器(receiver),早期的面向对象语言留下的遗 产将调用一个方法称为“向一个对象发送消息”。
在能够给任意类型定义方法这一点上,Go和很多其它的面向对象的语言不太一样。因此 在Go语言里,我们为一些简单的数值、字符串、slice、map来定义一些附加行为很方便。方 法可以被声明到任意类型,只要不是一个指针或者一个interface。
基于指针对象的方法
当调用一个函数时,会对其每一个参数值进行拷贝,如果一个函数需要更新一个变量,或者 函数的其中一个参数实在太大我们希望能够避免进行这种默认的拷贝,这种情况下我们就需 要用到指针了。对应到我们这里用来更新接收器的对象的方法,当这个接受者变量本身比较 大时,我们就可以用其指针而不是对象来声明方法,如下:
func (p *Point) ScaleBy(factor float64){
p.X *= factor
p.Y *= factor
}
这个方法的名字是 (*Point).ScaleBy 。这里的括号是必须的;没有括号的话这个表达式可能 会被理解为 *(Point.ScaleBy) 。
在现实的程序里,一般会约定如果Point这个类有一个指针作为接收器的方法,那么所有Point 的方法都必须有一个指针接收器,即使是那些并不需要这个指针接收器的函数。
只有类型(Point)和指向他们的指针(*Point),才是可能会出现在接收器声明里的两种接收器。 此外,为了避免歧义,在声明方法时,如果一个类型名本身是一个指针的话,是不允许其出 现在接收器中的,比如下面这个例子:
type P *int
func(P) f() { /* */ } //compile err
想要调用指针类型方法 (*Point).ScaleBy ,只要提供一个Point类型的指针即可,像下面这样:
r := &Point{, }
r.ScaleBy()
fmt.Println(*r) // "{2, 4}"
如果接收器p是 一个Point类型的变量,并且其方法需要一个Point指针作为接收器,我们可以用下面这种简短 的写法:
p.ScaleBy()
编译器会隐式地帮我们用&p去调用ScaleBy这个方法。这种简写方法只适用于“变量”,包括 struct里的字段比如p.X,以及array和slice内的元素比如perim[0]。我们不能通过一个无法取到 地址的接收器来调用指针方法,比如临时变量的内存地址就无法获取得到:
Point{, }.ScaleBy() // compile error: can't take address of Point literal
总结一下:
1. 不管你的method的receiver是指针类型还是非指针类型,都是可以通过指针/非指针类型 进行调用的,编译器会帮你做类型转换。 2. 在声明一个method的receiver该是指针还是非指针类型时,你需要考虑两方面的内部,第 一方面是这个对象本身是不是特别大,如果声明为非指针变量时,调用会产生一次拷 贝;第二方面是如果你用指针类型作为receiver,那么你一定要注意,这种指针类型指向 的始终是一块内存地址,就算你对其进行了拷贝。熟悉C或者C艹的人这里应该很快能明 白。
golang 方法的更多相关文章
- golang 方法接收者
[定义]: golang的方法(Method)是一个带有receiver的函数Function,Receiver是一个特定的struct类型,当你将函数Function附加到该receiver, 这个 ...
- golang方法和接口
一. go方法 go方法:在函数的func和函数名间增加一个特殊的接收器类型,接收器可以是结构体类型或非结构体类型.接收器可以在方法内部访问.创建一个接收器类型为Type的methodName方法. ...
- Golang 方法method
方法method Go中虽没有class,但依旧有method 通过显示说明receiver来实现与某个类型的结合 只能为同一个包中的类型定义方法 receiver可以是类型的值或者指针 不存在方法重 ...
- golang 方法内部定义子方法及调用
package main import ( "fmt" "reflect" ) func out(ch chan int) { <-ch fmt.Prin ...
- Golang 方法接收者是值还是指针问题
对于普通结构体作为接收者,值和指针并没有区别. (以下代码摘抄自Go In Action 中文版) type defaultMatcher struct{} // 方法声明为使用 defaultMat ...
- golang方法详解
Go 语言 类型方法是一种对类型行为的封装 .Go 语言的方法非常纯粹, 可以看作特殊类型的函数,其显式地将对象实例或指针作为函数的第一个参数,并且参数可以自己指定,而不强制要求一定是 this或se ...
- golang方法
1.方法声明 在函数声明时,在其名字之前放上一个变量,即是一个方法.这个附加的参数会将该函数附加到这种类型上,即相当于为这种类型定义了一个独占的方法. package main import &quo ...
- golang方法和函数的区别
- 从OOP的角度看Golang
资料来源 https://github.com/luciotato/golang-notes/blob/master/OOP.md?hmsr=toutiao.io&utm_medium=tou ...
随机推荐
- 必会SQL笔试题
()表名:购物信息 购物人 商品名称 数量 A 甲 B 乙 C 丙 A 丁 B 丙 …… 给出所有购入商品为两种或两种以上的购物人记录 答:); ()表名:成绩表 姓名 课程 分数 张三 语文 张三 ...
- MySQL 按照数据库表字段动态排序 查询列表信息
MySQL 按照数据库表字段动态排序 查询列表信息 背景描述 项目中数据列表分页展示的时候,前端使用的Table组件,每列自带对当前页的数据进行升序或者降序的排序. 但是客户期望:随机点击某一列的时候 ...
- 解决gradle项目每次编译都下载gradle-x.x-all.zip gradle-x.x-bin.zip
想必有一些热爱技术的看官或者android开发人员都会接触gradle项目.中国用户每次下载都很慢,甚至狂躁(CTMD的什么人做的这种设计,每次下载都狗日慢的想死). 哦,不好意思,骂人了.不管你高不 ...
- [笔记] 使用v2r访问外网
介绍 首先,你需要有一台能上外网的服务器,如AWS,GCP等. 其次,请自行复制全文,然后将FXXK替换为v2r的全称(5个小写字符). 服务器上Docker镜像配置流程 拉取镜像 $ sudo do ...
- EUREKA 删除 or 强制下线/上线 实例
开发环境,EUREKA 注册中心 某服务被注册了多个实例,feign 调用时 服务请求到其他实例上,请求收不到,使用一下命令删除 或者强制下线实例: 1 .DELETE 删除注册实例,但是如果被删除 ...
- Using NodeLists
Understanding a NodeList object and its relatives, NamedNodeMap and HTMLCollection, is critical to a ...
- .net代码混淆 .NET Reactor 研究 脚本一键混淆一键发布
.net代码混淆 .NET Reactor 研究 为什么要混淆? .net比较适合快速开发桌面型应用,但缺点是发布出来的文件是可以反编译的,有时候为了客户的安全,我们的代码或者我们的逻辑不想让别人知道 ...
- 04 npm 命令大全
一.npm简介 npm(Node Package Manager)是随同node.js 一起安装的包管理工具,为了解决nodejs代码部署上的很多问题,常用以下场景: 允许用户从npm服务器下载别 ...
- Windows 10 搭建 Django 环境(详细教程)
Windows 10 搭建 Django 环境(详细教程) https://blog.csdn.net/HappyLittleMouse/article/details/81360272#1.%20P ...
- C++学习笔记-const
const在C++中有着大量的运用,深刻理解const有助于进一步理解C++. const基础知识 int main() { const int a;//C++中必须初始化 int const b;/ ...