Go的方法

方法

什么是方法?

方法其实就是一个函数,在 func 这个关键字和方法名中间加入了一个特殊的接收器类型。接收器可以是结构体类型或者是非结构体类型。接收器是可以在方法的内部访问的。

下面就是创建一个方法的语法。

package main

import "fmt"

type Person2 struct {
   Id int
   Name string
   Sex string
}


//定义一个方法
//     接收器     方法名
func (p Person2)PrintName()  {
   // 在方法内可以使用p
   fmt.Println(p.Name)
   
}

func main()  {
   per:=Person2{}  // 相当于实例化对象
   per.Name = "哎咿呀"  // 对象的改值
   per.PrintName()  // 调用方法
    
    per1 := Person2{22,"李逵","男"}
	per1.PrintName()  // 谁调用打印谁的
}

-------------------------------------------
哎咿呀
李逵

方法的使用二

package main

import "fmt"

type Person2 struct {
   Id   int
   Name string
   Sex  string
}

//定义一个方法
//     接收器     方法名
func (p Person2) PrintName() {
   // 在方法内可以使用p
   fmt.Println(p.Name)

}

// 定义一个有参方法
func (p Person2) ChangeName(name string) {
   p.Name = name
   fmt.Println(p)
}

func main() {
   per := Person2{} // 相当于实例化对象
   per.Name = "哎咿呀" // 对象的改值
   per.PrintName()  // 调用方法

   per1 := Person2{22, "李逵", "男"}
   per1.ChangeName("李二狗") // 谁调用打印谁的
   fmt.Println(per1)   

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZyOb9nje-1614135406446)(https://gitee.com/A1L19/PicGO/raw/master/PicGo/image-20210223220526436.png)]

值接收器和指针接收器

package main

import "fmt"

type Person2 struct {
	Id   int
	Name string
	Sex  string
}


// 定义一个有参方法
func (p *Person2) ChangeSex(sex string) {
	p.Sex = sex
	fmt.Println("指针已处理",p.Sex)  // 推荐使用这种自动帮你处理了
	fmt.Println("指针未处理",(*p).Sex)  // 两种方法都可以
}

func main() {
	per1 := Person2{22, "李逵", "男"}
	per1.ChangeSex("狗") // 谁调用打印谁的
	fmt.Println(per1)

}
--------------------------------------------------------------------
指针已处理 狗
指针未处理 狗
{22 李逵 狗}  //z指针传递的时候原来的结构体也发生了修改
那么什么时候使用指针接收器,什么时候使用值接收器?

一般来说,指针接收器可以使用在:对方法内部的接收器所做的改变应该对调用者可见时。

指针接收器也可以被使用在如下场景:当拷贝一个结构体的代价过于昂贵时(占用内存过多时)。考虑下一个结构体有很多的字段。在方法内使用这个结构体做为值接收器需要拷贝整个结构体,这是很昂贵的。在这种情况下使用指针接收器,结构体不会被拷贝,只会传递一个指针到方法内部使用。

在其他的所有情况,值接收器都可以被使用。

简单来说就是,想改原来的值就用指针,不想改就用值,指针用的多

匿名字段方法

属于结构体的匿名字段的方法可以被直接调用,就好像这些方法是属于定义了匿名字段的结构体一样。

package main

import "fmt"

// 匿名字段的方法
type Hobby struct {
	Id int
	Name string
}


type Person struct {
	Id int
	Name string
	Sex string
	Hobby //匿名字段
}


func (p Person) PrintName(){
	fmt.Println(p.Name)
}

func (h Hobby) HobbyName(){
	fmt.Println(h.Name)
}
func (h Hobby) PrintName(){
	fmt.Println(h.Name)
}
func main() {
	pe := Person{Name: "孙悟空",Hobby:Hobby{1,"棒子"}}
	pe.HobbyName() //由于Hobby是个匿名字段,所以方法也提升了,如果方法名重了,优先用结构体自己的
	pe.PrintName()
}
---------------------------------------------------------------------
棒子
孙悟空

在方法中使用值接收器 与 在函数中使用值参数

和值参数相类似,函数使用指针参数只接受指针,而使用指针接收器的方法可以使用值接收器和指针接收器。

package main

import "fmt"

// 在方法中使用指针接收器 与 在函数中使用指针参数

type Name struct {
	Id   int
	Name string
	Sex  string
}

//  在方法中使用值接收器
func (n Name) PrintName() {
	fmt.Println(n.Name)
}

//  在函数中使用值参数,只能传值
func FPrintName(p Name) {
	fmt.Println(p.Name)
}

func main() {
	n1 := &Name{Name: "孙悟空"}
	n2 := Name{Name: "猪八戒"}
	n1.PrintName()
	n2.PrintName()
	FPrintName(*n1)
	FPrintName(n2)
}
// 值接收器:可以用值来调用也可以用指针来调用
// 函数的值参数,只能传值
----------------------------------------------------------
孙悟空
猪八戒
孙悟空
猪八戒

改值

func (n Name)ChangeName(name string)  {
	n.Name=name
	fmt.Println(n.Name)
}

func main() {
	n1 := &Name{Name: "孙悟空"}
	n2 := Name{Name: "猪八戒"}
	n1.ChangeName("噢哈哈")
	fmt.Println(n1)
	n2.ChangeName("嘿哈哈")
	fmt.Println(n2)
}
-------------------------------------------------
噢哈哈
&{0 孙悟空 }  // 虽然是指针类型但是复制了一份
嘿哈哈
{0 猪八戒 }

在方法中使用指针接收器 与 在函数中使用指针参数

总结:不管是值类型接收器还是指针类型接收器,都可以用值来调用,或者指针来调用
指针类型接收器修改的就是原值,值类型都会拷贝一份,他只和接收器类型有关,也就是接收器类型是指针改的就是原值
接收器是值类型改的就是新的

package main

import "fmt"

// 在方法中使用指针接收器 与 在函数中使用指针参数

type Name struct {
   Id   int
   Name string
   Sex  string
}

//  在方法中使用值接收器
func (n *Name) PrintName() {
   fmt.Println(n.Name)
}

func (n *Name)ChangeName(name string)  {
   n.Name=name
   fmt.Println(n.Name)
}

//  在函数中使用指针,只能传指针
func FPrintName(p *Name) {
   fmt.Println(p.Name)
}

func main() {
   n1 := &Name{Name: "孙悟空"}
   n2 := Name{Name: "猪八戒"}
   n1.PrintName()
   n2.PrintName()
   FPrintName(n1)
   FPrintName(&n2)
   n1.ChangeName("噢哈哈")
   fmt.Println(n1)
   n2.ChangeName("嘿哈哈")
   fmt.Println(n2)
}
// 总结:不管是值类型接收器还是指针类型接收器,都可以用值来调用,或者指针来调用
// 指针类型接收器修改的就是原值,值类型都会拷贝一份,他只和接收器类型有关,也就是接收器类型是指针改的就是原值
// 接收器是值类型改的就是新的

非构体方法

package main

import "fmt"

// 在int上绑定一个add方法(不允许)

//func (i int)add()  {
//	i = i+1
//	i ++
//	i+=1
//}
//

//但是可以在自定义的类型上绑定方法

type sint int

func (i *sint) add() {
	*i++
	*i += 1
	*i = *i + 1
}

func main() {
	var a sint = 10
	fmt.Println(a)
	a.add()
	fmt.Println(a)
}
---------------------------------------------
10
13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值