Golang中的方法
方法的简介
在某些情况下,我们要需要声明(定义)方法。比如Person结构体:除了有一些字段外(年龄,姓名),Person结构体还有一些行为比如:可以说话、跑步。。。通过学习,还可以作算术题,这些行为要通过方法才能完成
Golang中的方法是作用在指定的数据类型上的,即和指定的数据类型绑定,因此自定义类型,都可以有方法,而不仅仅是struct
方法和函数很相似,但是方式是和某些数据类型绑定的函数
type A struct {
Num int
}
//下面这个就叫方法
func (a A)test() {
fmt.Println(a.Num)
}
func (a A) test(){} 表示A结构体有一种方法,且方法名为test
(a A) 体现 test 方法是和 A类型绑定的
举一个方法的例子:
package main
import "fmt"
type A struct {
Num int
}
func (a A) test() {
fmt.Println("The number is:", a.Num)
}
func main() {
alphA := A{12}
alphA.test()
}
输出的是
The number is: 12给A这一类的结构体绑定了一个test()方法,当实例对象alphA调用test方法的时候,会把自己传进去,也就是test方法中的a。 这一点和python很像,python的类里面的函数一般开头会有一个self(或者说java里面的this),就是把实例对象自身传进去,但是注意在上面的代码中,传进去的时候传的是结构体,也就是值类型,因此在方法中对结构体字段作出的改变不会影响main中的结构体变量,举例如下:
package main
import "fmt"
type A struct {
Num int
}
func (a A) test() {
a.Num = 10
fmt.Println("The number is:", a.Num)
}
func main() {
alphA := A{12}
fmt.Println("Before alphA.test(), The number in alphA is:", alphA.Num)
alphA.test()
fmt.Println("After alphA.test(), The number in alphA is:", alphA.Num)
}
上面这个代码的感觉和java或者python都会不太一样
另外注意一点:与数据类型绑定的方法只能通过响应的实例对象调用,不能通过其它方式直接调用
对于方法的传参,返回值等也和函数的使用一样,只不过声明方法的前面会多一个绑定
方法的调用和传参机制原理
方法的调用和传参机制和函数基本一样,不一样的地方是方法调用时,会将调用方法的变量,当做实参也给传递给方法,这里注意,如果变量时值类型,则进行值拷贝,如果变量时引用类型,则进行地址拷贝
做一个案例,计算园的面积:
package main
import "fmt"
type circle struct {
radius float64
}
func (c circle) forArea() float64 {
return 3.14 * c.radius * c.radius
}
func main() {
var c = circle{1}
fmt.Println("The area of circle is", c.forArea())
}
输出的结果是:
The area of circle is 3.14但是我们在时间中常用的,不是传一个完整的struct进去,而是将方法与struct指针绑定,如下:
package main
import "fmt"
type circle struct {
radius float64
}
func (c *circle) Area() float64 {
return 3.14 * c.radius * c.radius //标准写法 return 3.14 * (*c).radius * (*c).radius
}
func main() {
var c = circle{3.14}
fmt.Println("The value of area is:", c.radius)//标准写法 fmt.Println("The value of area is:", (&c).radius)
}
输出的结果是:
The value of area is: 3.14这个地方,该方法与结构体指针绑定,因此,只有结构体指针才能调用方法,就像标准写法中写的,但是,Golang语言设计者为了方便developer,他简化了这个操作,直接用结构体变量调用也行
与结构体指针绑定,这样做的另一个好处是速度快,因为没有复杂的值拷贝,而是简单的地址拷贝
方法的细节讨论
①Golang中的方法作用在指定的数据类型上的(即:和指定的数据类型绑定),因此自定义类型,都可以有方法
也就是说,int类型也可以绑定方法,但是,go语言不允许为简单的内置类型添加方法,因此如果我们要绑定,需要用type将int类型取一个别名,代码如下:
package main
import "fmt"
type myInt int
func (i *myInt) addO(adding int) {
*i = *i + myInt(adding)
}
func main() {
var number myInt = 12
number.addO(5)
fmt.Println("number adds 5 is :", number)
}
输出的结果是:
number adds 5 is : 17这样传指针进去可以改变main中的数值
②方法的访问范围控制的规则,和函数一样,方法名首字母小写,只能在本包访问,方法首字母大写,可以在本包和其它包访问
③如果实现了String()这个方法,那么fmt.Println默认会调用这个变量的String()进行输出,做一个案例如下:
这个有点像java中的 toSting()方法
package main
import "fmt"
type man struct {
Name string
Age int
}
func (littleMan *man) String() string {
return "舔狗十年一场空,练出腹肌叫老公。要做一个猛男,要猛!!!"
}
func main() {
var fzd man = man{"Zideng Feng", 22}
fmt.Println("Zideng's words are:", fzd)
fmt.Println("Zideng's words are:", &fzd)
}
这个代码就是改写String方法,当然,如果绑定对象是结构体指针类型的话,必须用指针才能用。因为我们到底改的是结构体指针类型的String方法,而不是结构体的String方法
如果想不加&的话,就不要绑定指针类型,直接绑定原结构体类型就好