• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Go语言_通神路之五耀篇(1)

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

1、Go方法

灵胎篇博客中讲到函数,函数就是类似与java中的方法,然而go中还有一些升级版的函数,叫方法。

只不过这种方法在方法名前还有一个括号加参数,只不过被称呼为接收者,方法名后面的括号没有参数,方法接收者在它自己的参数列表内,位于 func 关键字和方法名之间。

如下:这个就被称之为方法,因为方法名前面有接收者

package main

import (
   "math"
   "fmt"
)

type Person struct {
   x,y float64
}

func (p Person) Test() float64 {
   return math.Sqrt(p.x*p.x+p.y*p.y)
}

func main()  {
   value := Person{3,4}
   fmt.Print(value.Test())
}

反而,方法名后有参数,一般被称呼为函数,只不过是参数顺序不同而已,调用的方式也不同罢了

package main

import (
   "math"
   "fmt"
)

type Person struct {
   x,y float64
}

func Test(p Person) float64 {
   return math.Sqrt(p.x*p.x+p.y*p.y)
}

func main()  {
   value := Person{3,4}
   fmt.Print(Test(value))
}

不过这个接受者有一定的限制,对struct结构体类型没有限制要求,但是非结构体类型声明方法,必须是本包内!!!

举例说明:

所以方法的接收者对结构体没有要求,非结构体如数据类型等都要求在同一个package下面才可以作为接收者。

2、指针接收者

    2.1 概念

在灵胎篇第五篇中讲到指针,& 操作符会生成一个指向其操作数的指针,* 操作符表示指针指向的底层值,所一当你运行下面的函数的时候,结果是50,

package main

import (
   "math"
   "fmt"
)

type Person struct {
   x,y float64
}

func (v *Person) Scale(f float64) {
   v.x = v.y * f
   v.y = v.y * f
}

func (p Person)Test() float64 {
   return math.Sqrt(p.x*p.x+p.y*p.y)
}

func main()  {
   value := Person{3,4}
   value.Scale(10)
   fmt.Print(value.Test())
}

当你去掉 Scale方法中接收者的指针的时候,结果会发生变化,因为去掉指针的话,执行那个函数的接收者将是Person结构体的一个副本,并不是真正意义上的Person结构体,所以我们需要用指针‘*’来更改

    2.2 方法与指针重定向

注意点:

当函数的参数中有指针的情况下,

func ScaleFunc(v *Vertex, f float64) {
    v.X = v.X * f
    v.Y = v.Y * f
}

这个情况下,函数中指针作为参数,必须用 类型前加&

ScaleFunc(v, 5)  // 编译错误!
ScaleFunc(&v, 5) // OK

而对于方法,可以忽略,如下:

func (v *Vertex) Scale(f float64) {
    v.X = v.X * f
    v.Y = v.Y * f
}
var v Vertex
v.Scale(5)  // OK
p := &v
p.Scale(10) // OK

因为方法中的接收者v.Scale(5)自动转换(&v).Scale(5)操作

    2.3 方法与指针重定向(反向)

那说一下什么是反向,就是方法中的接收者和函数的参数不是指针了,而是正常类型,我们接下来如何操作。也有要求

func (v Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func AbsFunc(v Vertex) float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

函数情况下:

var v Vertex
fmt.Println(AbsFunc(v))  // OK
fmt.Println(AbsFunc(&v)) // 编译错误!

方法情况下:

var v Vertex
fmt.Println(v.Abs()) // OK
p := &v
fmt.Println(p.Abs()) // OK

这种情况下,方法调用 p.Abs() 会被自动转换为(*p).ABs(),像极了java的自动装箱功能和int long的自动转换功能

所以我们在开发中,为什么方法用的非常多,函数用的很少的原因,其次,这样可以避免在每次调用方法时复制该值。若值的类型为大型结构体时,这样做会更加高效。

3、接口

    3.1 概念理解

接口就是方法的集合,和java中的接口一样,都需要实现接口

package main

import (
   "math"
   "fmt"
)

type myFloat float64

type Base interface {
   test() float64
}

func (f myFloat)test() float64 {
   return math.Sqrt(float64(f))
}

func main()  {

   var base Base

   f := myFloat(25) 

   base = f  //f实现接口base

   fmt.Print(base.test())
}

接下来用指针的接收者操作下

package main

import (
   "math"
   "fmt"
)

type myFloat float64

type Base interface {
   test() float64
}

func (f *myFloat)test() float64 {
   return math.Sqrt(25)
}

func main()  {

   var base Base

   f := myFloat(25)

   base = &f

   fmt.Print(base.test())
}

同样是结果5,不过我们上面不应该用数据类型作为指针接收者,因为需要用结构体,这样才方便在方法中使用操作业务逻辑。

接口接收者会实现接口!

    3.2 底层值为 nil 的接口值

package main

import "fmt"

type I interface {
    M()
}

type T struct {
    S string
}

func (t *T) M() {
    if t == nil {
        fmt.Println("<nil>")
        return
    }
    fmt.Println(t.S)
}

结果为:

(<nil>, *main.T)
<nil>
(&{hello}, *main.T)
hello

即便接口内的具体值为 nil,方法仍然会被 nil 接收者调用,在java中会触发一个空指针异常,但在 Go 中通常会写一些方法来优雅地处理它

*注意:* 保存了 nil 具体值的接口其自身并不为 nil。

    3.3 空接口

package main

import "fmt"

func main() {
    var i interface{}
    describe(i)

    i = 42
    describe(i)

    i = "hello"
    describe(i)
}

func describe(i interface{}) {
    fmt.Printf("(%v, %T)\n", i, i)
}

结果为:

(<nil>, <nil>)
(42, int)
(hello, string)

%V 意思是value %T是Type

 

转载于:https://my.oschina.net/mdxlcj/blog/1932270


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
go make切片中len() 和 cap() 的差别发布时间:2022-07-10
下一篇:
Howtokillgoroutine?发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap