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 ...
随机推荐
- Appium移动自动化测试(三)之元素定位
实验简介 做过UI自动化(web自动化, 移动自动化)的同学都会知道, 除去框架的选型和搭建以外, 落到实处的对元素进行定位就成了最重要的技能. 做过UI自动化的同学会知道, 对页面元素的定位方式有8 ...
- LoadRunner脚本编写之一
LoadRunner脚本编写之一 性能测试工程师要懂代码么?答案是必须的.好多测试员认为在loadrunner中编写脚本很难很牛X ,主要是大多测试人员并未做过开发工作,大学的那点程序基础也忘记的差不 ...
- koa cookie使用
1 .Koa 中设置 Cookie 的值 ctx.cookies.set(name, value, [options]) 通过 options 置 设置 cookie name 的 value : ...
- iOS实现渐变颜色
下面是我的两种实现: 1.直接图片展示,注意图片的变形问题; 2.用CAGradientLayer渐变颜色实现; 代码如下: // // ViewController.m // ImageStrenc ...
- [LeetCode] 697. Degree of an Array 数组的度
Given a non-empty array of non-negative integers nums, the degree of this array is defined as the ma ...
- Debian系统软件安装
查看已安装软件 dpkg -l | grep -i name apt-get remove name 建议用root安装,有一些工具,使用非root用户安装后,仍然不识别命令,可能跟权限有关. net ...
- SQLite扫描
SQLite的扫盲 SQLite的是一种嵌入式数据库,它的数据库就是一个文件.由于SQLite的本身是Ç写的,而且体积很小,所以经常被集成到各种应用程序中,主要在手机的应用中使用. 之前没有遇到过关于 ...
- Spring MVC (二)注解式开发使用详解
MVC注解式开发即处理器基于注解的类开发, 对于每一个定义的处理器, 无需在xml中注册. 只需在代码中通过对类与方法的注解, 即可完成注册. 定义处理器 @Controller: 当前类为处理器 @ ...
- Java内存模型(二)volatile底层实现(CPU的缓存一致性协议MESI)
CPU的缓存一致性协议MESI 在多核CPU中,内存中的数据会在多个核心中存在数据副本,某一个核心发生修改操作,就产生了数据不一致的问题,而一致性协议正是用于保证多个CPU cache之间缓存共享数据 ...
- Apache Zookeeper 集群环境搭建
Zookeeper 是 一个分布式.开放源码的分布式应用程序协调服务,是Google Chubby的一个开源实现,大多数的分布式应用都需要Zookeeper的支持,这篇文章先简单的和大家分享如何搭建一 ...