目录:
方法
什么是方法
方法其实就是一个函数,在 func 这个关键字和方法名中间加入了一个特殊的接收器类型。接收器可以使结构体类型或者是非结构体类型。接收器是可以在方法的内部访问的。
方法定义
package main
import "fmt"
type Person struct {
name string
age int
}
// 定义方法
func (p Person) print() {
fmt.Println(p.name)
}
// 定义Print函数
func Print(p Person){
fmt.Println(p.name)
}
func main() {
p := Person{"jeff", 18}
p.print()
//使用函数
//Print(p)
}
这里又有个疑问了,函数和方法作用相同,为什么还要有方法定义
- Go 不是纯粹的面向对象编程语言,而且Go不支持类。因此,基于类型的方法是一种实现和类相似行为的途径
- 相同名字的方法可以定义在不同的类型上,而相同名字的函数时不被允许的。
指针接收器与值接收器
示例:
package main
import "fmt"
type Person struct {
name string
age int
}
// 定义方法
func (p Person) print() {
fmt.Println(p.name)
}
func (p Person) changename(name string){
p.name = name
}
func main() {
p:= Person{"jeff",18}
p.changename("nb")
p.print()
}
因为结构体是值类型,此时输出为:
jeff
修改为指针接收器
func (p *Person) changename(name string){
p.name = name
// 相当于
// (*p).name = name
}
func main() {
p:= &Person{"jeff",18}
p.changename("nb")
p.print()
}
方法使用指针接收器,此时输出结果为:
nb
通俗点说,当想要操作对象本身时,可以使用指针接收器方法
还有一种情况,可以使用指针接收器,当拷贝一个结构体成本过于昂贵时,可以使用指针接收器
匿名字段方法
示例:
type Person struct {
name string
age int
// 此时Information是匿名字段
Information
}
type Information struct {
city, address string
}
// 绑定information方法
func (i Information) print_city() {
fmt.Println(i.city)
}
func main() {
p := &Person{name: "jeff", age: 18, Information: Information{
city: "shanghai",
address: "xuhui",
}}
// 字段提升
p.print_city()
}
在方法中使用值接收器,在函数中使用值参数
总结:
- 当一个函数有一个值参数,它只能接受一个值类型,不能接受地址
- 当一个方法有一个值接收器,他可以接受对象调用,也可以接受地址调用
示例:
package main
import "fmt"
type Person struct {
name string
age int
}
func (p Person) test() {
fmt.Println(p.name)
}
func test(p Person){
fmt.Println(p.name)
}
func main() {
p:= Person{"jeff",19}
//test(&p)
(&p).test()
}
总结:为了方便Go语言把p.test()解释为(*p).test(),所以值接收器可以接受地址
在方法中使用指针接收器, 在函数中使用指针参数
总结:
- 当一个函数有一个指针参数,它只能接受一个指针
- 当一个方法有一个指针接收器,他可以接受对象调用,也可以接受地址调用
type Person struct {
name string
age int
}
func (p *Person) test() {
fmt.Println(p.name)
}
func test(p *Person){
fmt.Println(p.name)
}
func main() {
p:= Person{"jeff",19}
// 方法
//(&p).test()
//p.test()
// 函数
test(&p)
// 传结构体报错
//test(p)
}
通常做法:在取结构体时,直接用&取地址,在方法中使用指针接收器,来使用结构体
非结构体上的方法
前提:需要对内置数据类型起别名
示例:
type myInt int
func (i myInt) add(y myInt) (myInt) {
return i + y
}
func main() {
var a myInt = 10
b := a.add(20)
fmt.Println(b)
}
结果为:30