概述
接触到go之前,我认为函数和方法只是同一个东西的两个名字而已。但是在go中是两个不同的东西。
官方解释:一个方法就是一个包含了接收者的函数。接收者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。
区别:
- 对于普通函数:接收者(函数参数)为值类型时,不能将指针类型的数据直接传递,反之亦然。
func function_name([parameter list]) [return_types] { 函数体 }
- 对于方法(如struct方法): 接收者为值类型时,可以直接用指针类型的变量调用方法,反之亦然。
func (variable_name variable_data_type) function_name() [return_type]{ /* 函数体*/ }
可以看到方法和函数的区别,方法在func关键字后是接收者而不是函数名,接收者可以是自己定义的一个类型,这个类型可以是struct,interface,甚至我们可以重定义基本数据类型。
Go函数
函数是基本的代码块,用于执行一个任务。
Go 语言最少有个 main() 函数。
你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。
函数声明告诉了编译器函数的名称,返回类型,和参数。
Go 函数可以返回多个值。
Go 语言标准库提供了多种可动用的内置的函数。例如,len() 函数可以接受不同类型参数并返回该类型的长度。如果我们传入 的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。
- 值传递:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
- 引用传递:引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
Go方法
Go 语言中同时有函数和方法。一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。
下面定义一个结构体类型和该类型的一个方法:
package main
import (
"fmt"
)
/* 定义结构体 */
type Circle struct {
radius float64
}
func main() {
var c1 Circle
c1.radius = 10.00
fmt.Println("Area of Circle(c1) = ", c1.getArea())
}
//该 method 属于 Circle 类型对象中的方法
func (c Circle) getArea() float64 {
//c.radius 即为 Circle 类型对象中的属性
return 3.14 * c.radius * c.radius
}
以上代码执行结果为:
Area of Circle(c1) = 314
例子
package structTest
//普通函数与方法的区别(在接收者分别为值类型和指针类型的时候)
//Date:2014-4-3 10:00:07
import (
"fmt"
)
func StructTest06Base() {
structTest0601()
structTest0602()
}
//1.普通函数
//接收值类型参数的函数
func valueIntTest(a int) int {
return a + 10
}
//接收指针类型参数的函数
func pointerIntTest(a *int) int {
return *a + 10
}
func structTest0601() {
a := 2
fmt.Println("valueIntTest:", valueIntTest(a))
//函数的参数为值类型,则不能直接将指针作为参数传递
//fmt.Println("valueIntTest:", valueIntTest(&a))
//compile error: cannot use &a (type *int) as type int in function argument
b := 5
fmt.Println("pointerIntTest:", pointerIntTest(&b))
//同样,当函数的参数为指针类型时,也不能直接将值类型作为参数传递
//fmt.Println("pointerIntTest:", pointerIntTest(b))
//compile error:cannot use b (type int) as type *int in function argument
}
//2.方法
type PersonD struct {
id int
name string
}
//接收者为值类型
func (p PersonD) valueShowName() {
fmt.Println(p.name)
}
//接收者为指针类型
func (p *PersonD) pointShowName() {
fmt.Println(p.name)
}
func structTest0602() {
//值类型调用方法
personValue := PersonD{101, "Will Smith"}
personValue.valueShowName()
personValue.pointShowName()
//指针类型调用方法
personPointer := &PersonD{102, "Paul Tony"}
personPointer.valueShowName()
personPointer.pointShowName()
//与普通函数不同,接收者为指针类型和值类型的方法,指针类型和值类型的变量均可相互调用
}
End