Golang中的方法
- 方法的介绍和使用
- 方法的声明和调用
- 方法的调用和传参机制原理
- 方法的声明(定义)
- 方法注意事项和细节讨论
- 方法和函数的区别
方法的介绍和使用
在某些情况下,我们需要声明(定义)方法。比如person结构体,除了有一些字段外(年龄,姓名…),person结构体还有一些行为比如:可以说话、跑步…这时就要用方法才能完成。
golang中的方法是作用在指定的数据类型上的(即:和指定的数据类型绑定),因此自定义类型,都可以有方法,而不仅仅是struct
方法的声明和调用
type A struct{
Num int
}
func (a A) test() {
fmt.Println(a,Num)
}
说明:
1.func (a A) test { }b表示A结构体有一种方法,方法名为test
2.(a A)体现test方法是和A类型绑定的
package main
import (
"fmt"
)
type Person struct{
Name string
}
//给person类型绑定一份方法
func (p Person) test() {
fmt.Println("test() name=", p.Name)
}
func main(){
var p Person
p.Name = "tom"
p.test()//调用方法
fmt.Println("main() p.name=", p.Name)
}
//test() name= tom
//main() p.name= tom
总结
1.test方法和person类型绑定
2.test方法只能通过person类型的变量来调用,而不能直接调用,也不能使用其他类型调用
3.func (p Person) test() {} 中的p,表示哪个person变量调用,这个p就是它的副本,这点和函数传参非常相似
4.p这个名字,由程序员指定,不是固定
方法的调用和传参机制原理
方法的调用和传参机制和函数基本一样,不一样的地方是方法调用时,会将调用方法的变量,当做实参也传递给方法。
说明:
1.在通过一个变量去调用方法时,其调用机制和函数一样
2.不一样的地方是,变量调用方法时,该变量本身也会作为一个参数传递到方法(如果变量是值类型,则进行值拷贝,如果变量是引用类型,则进行地址拷贝)
package main
import (
"fmt"
)
type Circle struct{
radius float64
}
func (c Circle) area() float64{
return 3.14 * c.radius * c.radius
}
func main() {
var c Circle
c.radius = 4.0
res := c.area()
fmt.Println("面积是=",res)
}
//面积是= 50.24
方法的声明(定义)
func (recevier type) methodName (参数列表)(返回值列表){
方法体
return返回值
}
- 1.参数列表:表示方法输入
- 2.recevier type:表示这个方法和type这个类型进行绑定,或者说该方法作用于type类型
- 3.receiver type:type可以是结构体,也可以其他的自定义类型
- 4.receiver:就是type类型的一个变量(实例),比如:person结构体的一个变量(实例)
- 5.参数列表:表示方法输入
- 6.返回值列表:表示返回的值,可以多个
- 7.方法主体:表示为了实现某一个功能代码块
- 8.return语句不是必须的,但是有返回值列表就必须要有
方法注意事项和细节讨论
- 1.结构体类型是值类型,在方法调用中,遵守值类型的传递机制,是值拷贝传递方式
- 2.如果程序员希望在方法中,修改结构体变量的值,可以通过结构体指针的方式来处理
-
3.Goalng中的方法作用在指定的数据类型上的(即:和指定的数据类型绑定),因此自定义类型,都可以有方法,而不仅仅是struct,比如int,float32等都可以有方法
-
4.方法的访问范围控制的规则,和函数一样。方法名首字母小写,只能在本包访问,方法首字母大写,可以在本包和其他包访问
-
5.如果一个类型实现了string()这个方法,那么fmt.Println默认会调用这个变量的String()进行输出
方法和函数的区别
- 1.调用方式不一样
- 函数的调用方式:函数名(实参列表)
- 方法的调用方式:变量.方法名(实参列表)
- 2.对于普通函数,接受者为值类型时,不能将指针类型的数据直接传递,反之亦然
- 3.对于方法(如struct的方法),接受者为值类型时,可以直接用指针类型的变量调用方法,反过来同样可以
package main
import (
"fmt"
)
type Person struct{
Name string
}
func (p Person) test() {
p.Name = "jack"
fmt.Println("test()=", p.Name)
}
func (p *Person)test2() {
p.Name = "marry"
fmt.Println("test2()=", p.Name)
}
func main(){
p := Person{"tom"}
p.test()
fmt.Println("main() p.name", p.Name)//tom
(&p).test() //**从形式上时传入地址,但本质仍然是值拷贝**
fmt.Println("main() p.name", p.Name)//tom
(&p).test2()
fmt.Println("main() p.name=", p.Name)
p.test2() //等价于(&p).test2,**从形式上时传入值类型,但是本质仍然是地址拷贝**
}
/*
test()= jack
main() p.name tom
test()= jack
main() p.name tom
test2()= marry
main() p.name= marry
*/