文档章节

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

就叫程舰
 就叫程舰
发布于 2018/08/22 16:42
字数 1311
阅读 27
收藏 3

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

 

© 著作权归作者所有

共有 人打赏支持
就叫程舰

就叫程舰

粉丝 115
博文 200
码字总数 142961
作品 0
海淀
程序员
私信 提问
开篇(2017-11-27)

故事很长,不知从何说起?(主编要催稿了-_-||,前方凑字,重点最后两段) 报考长春工业大学 当时选工大的时候,完全是出于一个目的:就是它离延边大学比较近。从此,便走了一条学霸路(伪学...

TinyDolphin
2017/11/27
0
0
Silverlight/WPF 系列汇总

Silverlight 解谜游戏系列 -- Silverlight 3 · Silverlight 解谜游戏 之一 新建项目 · Silverlight 解谜游戏 之二 创建题板 · Silverlight 解谜游戏 之三 消除名单 · Silverlight 解谜游...

junwong
2012/03/09
335
0
juniper 中国区合作伙伴

1、北京世纪华风科技发展有限公司 联系地址:北京市西城区黄寺大街26号 德胜置业大厦5号楼1009室 邮  编:100011 联系电话:400-007-6660 010-57510399 传 真 : 010-6853 9248 公司网址:w...

杰1992
2017/06/15
0
0
Java 语言的几个缺陷(个人感觉)

Java 语言由于一直要保持源代码及二进制的向后兼容, 所以尽管语法上有了很大的演进, 但有些东西仍然无法触及. 不像有些新生代的语言设计时可以博采众长, 或者像 Scala 那种语言向后兼容性的要...

YanbinQ
2016/07/12
49
0
Go语言_通神路之灵胎篇(6)

1、映射 1.1 概念 go的映射在java中被叫做集合 type Vertex struct { } var m map[string]Vertex 上面是go的映射m,如果用java代替的话,Vertex就是实体类,这样用java8可以写成 Map m = ne...

木九天
2018/08/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

java框架学习日志-13(Mybatis基本概念和简单的例子)

在mybatis初次学习Mybatis的时候,遇到了很多问题,虽然阿里云的视频有教学,但是视频教学所使用的软件和我自己使用的软件不用,我自己用的数据库是oracle数据库,开发环境是idea。而且视频中...

白话
47分钟前
2
0
Java基础:String、StringBuffer和StringBuilder的区别

1 String String:字符串常量,字符串长度不可变。Java中String是immutable(不可变)的。 String类的包含如下定义: /** The value is used for character storage. */private final cha...

watermelon11
今天
2
0
mogodb服务

部署MongoDB 官网: https://www.mongodb.com/download-center/community 创建mongo数据目录 mkdir /data/mongodb 二进制部署 wget -c https://fastdl.mongodb.org/linux/mongodb-linux-x8......

以谁为师
昨天
5
0
大神教你Debian GNU/Linux 9.7 “Stretch” Live和安装镜像开放下载

Debian项目团队于昨天发布了Debian GNU/Linux 9 "Stretch" 的第7个维护版本更新,重点修复了APT软件管理器中存在的安全漏洞。在敦促每位用户尽快升级系统的同时,Debian团队还发布了Debian ...

linux-tao
昨天
4
0
PHP 相关配置

1. php-fpm的pool 编辑php-fpm配置文件php-fpm.con vim /usr/local/php/etc/php-fpm.conf //在[global]部分增加以下内容 include = etc/php-fpm.d/*.conf # 相当与Nginx的虚拟主机文件 “vho......

Yue_Chen
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部