golang 方法
1.方法的定义:
golang中的方法是作用在指定的数据类型上的(即:和指定的数据类型绑定),因此自定义类型,都可以有方法,而不仅仅是struct
1)func (p Person) test()表示P结构体有一方法,方法名为test
2)(p Person)体现test方法是和Person类型是绑定的
3)test方法只能通过Person类型的变量来调用,而不能直接调用,也不能使用其他类型变量来调用
type Person struct { Name string } func (p Person) test() { fmt.Println("test()", p.Name) } func main() { var p Person p.Name = "Tom" p.test() }
2.方法的细节
1)结构体在方法的调用中是值拷贝
给Person结构体添加计算方法,可以接收参数n,计算从1+...+n的结果,并返回结果
//给Person结构体添加计算方法,可以接收参数n,计算从1+...+n的结果,并返回结果 func (person Person) cal(n int) int { sum := 0 for i := 1; i <= n; i++ { sum += i } return sum } func main() { var person Person person.Name = "Tom" n1 := person.cal(100) fmt.Println(n1) }
给出半径求面基
type Circle struct { Radius float64 } func (c Circle) area() float64 { return c.Radius * c.Radius * 3.14 } func main() { var c Circle c.Radius = 4.0 a1 := c.area() fmt.Println(a1) }
2)为了提供效率,通常跟结构体指针绑定
//为了提供效率,通常跟结构体指针绑定 func (c *Circle) area2() float64 { //return (*c).Radius * (*c).Radius * 3.14 底层为了简单等价于下面 return c.Radius * c.Radius * 3.14 } func main() { var c Circle c.Radius = 4.0 //a2 := (&c).area2() 底层为了简单等价于下面 a2 := c.area2() fmt.Println(a2) }
3)方法是作用在指定的数据类型上的(即:和指定的数据类型绑定),因此自定义类型,都可以有方法,而不仅仅是struct,比如int, float32都可以有方法
func (i integer) print() { i = 20 fmt.Println("i=", i) } func (i *integer) print1() { *i = 20 fmt.Println("i=", *i) } func main() { var i integer = 10 i.print() fmt.Println(i) i.print1() fmt.Println(i) }
4)方法的访问范围控制的规则,和函数一样。方法名首字母小写,只能在本包访问,方法首字母大写,可以在本包和其他包访问。
5)如果一个类型实现了String()这个方法,那么fmt.Println默认会调用这个变量的String()进行输出。
//给*Student实现方法String()
type Student struct { Name string Age int } func (stu *Student) String() string { str := fmt.Sprintf("Name=[%v],Age=[%v]\n", stu.Name, stu.Age) return str } func main() { stu := Student{ "tom", 20, } fmt.Println(stu)
//如果实现了*Student 类型是String方法,就会自动调用
fmt.Println(&stu)
}
3.方法和函数的区别
1)调用方式不一样
函数的调用方式: 函数名(实参列表)
方法的调用方式: 变量.方法名(实参列表)
2)对于普通函数,接收者为值类型时,不能将指针类型的数据直接传递,反之亦然
3)对于方法(如struct的方法),接收者为值类型时,可以直接用指针类型的变量调用方法,反过来同样也可以
总结:
1)不管调用形式如何,真正决定是值拷贝还是地址拷贝的是看这个方法是和哪个类型绑定的
2)如果是和值类型,比如(p Person),则是值拷贝,如果是和指针类型,比如(p *Person)则是地址拷贝。
func (p Person) test03() { p.Name = "jack" fmt.Println("test03()", p.Name) } func main() { p1 := Person{"TOM"} p1.test03() fmt.Println(p1.Name) //从形式上看是地址拷贝,但是实际上仍然是值拷贝,因为在test03是(p Person)是值拷贝。编译器把(&p1).test03()底层改为p1.test03()而不会报错 (&p1).test03() fmt.Println(p1.Name)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
2022-03-01 ecs健康检查问题