go语言的函数与方法
奋斗的大橙子 人气:0在C#或者Java里面我们都知道,一个Class是要包含成员变量和方法的,对于GO语言的Struct也一样,我们也可以给Struct定义一系列方法。
一、怎么定义一个方法?
Go的方法是在函数前面加上一个接收者,这样编译器就知道这个方法属于哪个类型了。例如:
package demo1 import ( "fmt" ) type Student struct { Name string Age int Class string } func (stu Student) GetUserInfo(student Student) { fmt.Printf("学生姓名:%v 年龄: %v 班级:%v ",student.Name,student.Age,student.Class) }
上面的代码就是定义了一个Student的结构体,然后针对这个结构体,创建了三个方法。我们可以通过【实例名.方法名】的方式来访问这个结构体内的方法。
package main import "Function/demo1" func main(){ student:=demo1.Student{ Name:"XiaoMing", Age:20, Class:"3-2", } student.GetUserInfo(student) }
二、接收者的类型问题
上面的GetUserInfo的接收者是一个Student类型,这里就会出现一个问题,如果我是设定类的操作,那么不会改变对应实例的值,它只是一个拷贝。下面的例子将说明这个问题,下面这个Set方法接收者是Student
type Student struct { Name string Age int Class string } func (stu Student) SetStudentName(name string) { stu.Name = name }
main函数中使用这个类
func main(){ student:=demo2.Student{ Name:"XiaoMing", Age:20, Class:"3-2", } student.SetStudentName("LiLie") fmt.Printf("Name: %v",student.Name ) }
结果:
Name: XiaoMing
可以看到,这里并没把Name进行修改。
如果我们使用Student指针类型作为接收者,则会修改这个值。例子如下:
func (stu *Student) SetStudentName(name string) { stu.Name = name //这里为什么能stu直接.出Name,是Go的语法糖相当于 (*stu).Name }
再次运营结果为:
Name: LiLie
三、何时使用值类型接收者,何时使用指针类型接收者。
粗暴的结论:如果你不知道怎么选择,那就使用指针。但有时候,使用值接收者会更合理,尤其是效率考虑,比如:不需要修改的小 struct、基础数据类型。以下是一些有用的指导方针:
- - 如果接收者是 map、func 或 chan,不用使用指针。如果是 slice,并且方法不会 reslice 或 从分配 slice,不要使用指针;
- - 如果方法需要修改接收者,必须使用指针; - 如果接收者是包含了 sync.Mutex 或类似的同步字段的结构体(struct),接收者必须使用指针,避免拷贝;
- - 如果接收者是一个大的结构体或数组,使用指针会更高效。但多大是大?如果所有元素(struct 的字段或数组元素)作为方法的参数传递认为太大,那么作为接收者也是太大。(粗暴一些,所有元素内存超过指针大小,可以考虑使用指针);
- - 如果接收者是结构体、数组或 slice,同时,它们的元素是指针,且指向的数据要改变,那么使用指针接收者会更合理;(有点绕,那就总原则:用指针没错);
- - 如果接收者是小的数组,或小的没有可变字段或指针的结构体,或者结构体字段只是简单的基础类型,值接收者会更合理;值接收者能减少垃圾回收的压力,一般会优先分配在栈上(记住是一般,因为有可能逃逸);但除非有性能测试验证,否则别因为可以介绍垃圾回收压力,就选择值接收者;
最后再强调一下,如果你拿不定主意,那就用指针接收者。
到此这篇关于go语言中函数与方法的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持。
加载全部内容