函数与方法有什么区别?编程中的函数与数学中的函数定义是一致的,函数就是对给定的输入到输出的一个隐射变化,在面向过程的语言中,例如c语言,通常我们写的每个功能代码段称之为函数,在golang中也是一样。方法与函数的主要区别是,方法与对象绑定的,方法有属于它的一个对象,在go中,通常都是与一个struct关联在一起的。在下面的demo2中,say()是属于cat的方法,在调用的时候,需要(obejct cat).say()形式调用。
func add(a, b int) int{
return a+b
}
type cat struct{}
func (d *dog) say() {
fmt.Println("i am a dog")
}
func (c cat) say() {
fmt.Println("i am a cat")
}
golang中定义一个方法形式为 func (receiver) fname(){} ,函数(fname)+属于对象(recevier), 属于的对象一般称作接收者。接收者有两种形式,一种是值类型,一种是指针类型。下面的dog say为指针类型,cat say为值类型。
type dog struct{}
type cat struct{}
// say()方法的全名为(*dog).say()
// 即只有指针类型的*dog才有say()方法
// 值类型的dog是没有say()方法的
func (d *dog) say() {
fmt.Println("i am a dog")
}
// say()方法的全名是(cat).say()
// 即只有值类型的cat才有say()方法
// 指针类型的*cat是没有say()方法的
func (c cat) say() {
fmt.Println("i am a cat")
}
上面的say()方法是不一样的,虽然他们都叫say方法,因为他们的接受者类型是不一样的,对于dog,它的say全名为(dog).say(), 对于cat,它的say全名为(cat).say()。结合下面的代码,dp是dog类型,所以执行dp.say()肯定是没有问题的,cv是cat类型,执行cv.say()也是没有问题的。那dv.say()和cp.say()有没有问题呢?「没有问题」,编译能够正常通过并运行出正确的结果。
func main() {
dv := dog{}
dp := &dog{}
cv := cat{}
cp := &cat{}
dv.say()
dp.say()
cv.say()
cp.say()
}
为什么会这样呢?是编译器帮我们做了隐式转换。即将dv.say()自动帮我转换成了(&dv).say(),也就是对dv进行了取地址操作。同理对cp.say()自动转为(*cp).say()。那定义了func (d *dog) say()还能定义func (d dog) say()吗,「不可用」,编译器会直接报错。也不能定义func (c cat) say()再定义func (c *cat) say()。


我们定义一个接口类型sayer,里面有个say方法。
type sayer interface {
say()
}
按照前面的理解,*dog和dog都可以调用say()方法,所以他们都实现了sayer。「不是这样」,对于接口类型,编译器并不会自动为我们做转换,所以要严格区分开,dog say的全名为(*dog).say()。所以只有指针类型的dog实现了sayer方法。将dog类型的dv赋值给say直接编译不通过。
var say sayer
say = dp
say = dv //编译器直接报错

那要怎么赋值呢?
var say sayer
say = &dv //这样赋值
看完这篇文章,再也不用担心我搞不清楚指针类型和值类型接收者的区别了!^^^