方法和接口

方法的接受者

Go中没有类,取而代之的是在结构体上定义的方法

为了将方法(函数)绑定在某一类结构体上,我们在定义函数(方法)时引入“接受者”的概念。

方法接受者在它自己的参数列表内,位于func关键字和方法名之间

package main

import (
"fmt"
"math"
) type Vertex struct {
X, Y float64
} func (v Vertex) Abs() float64 { //说明该方法绑定给特殊的函数
return math.Sqrt(v.X*v.X + v.Y*v.Y)
} func Abs(v Vertex) float64 { //正常的函数也可以这样写,并且不会和上一个函数重载
return math.Sqrt(v.X*v.X + v.Y*v.Y)
} func main() {
v := Vertex{3, 4}
fmt.Println(v.Abs()) // output 5
fmt.Println(Abs(v)) // output 5
}

注意,接受者只能是同一包内定义的类型,不能使其他包内定义的类型或者内建类型。如果想要为float64声明一个接受者,那也只能重新定义一个类型type MyFloat float64

指针接受者

接受者可以是指向某类结构体的指针。如果是指针,那么在就可以修改结构体内部的变量。

当指针为接受者的方法被调用时,接受者既能为值也能为指针。同样,当以值为接受者的方法被调用的时候,接受者技能为值又能为指针。在这个一一下,接受者是值还是指针本质上区别是方法是否可以修改结构体的变量。

接口

接口定义了一个方法的集合。不同的结构体通过至少实现这些方法可以生成不同类型的接口。接口值可以看做包含值和具体类型的元组。

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)
} func main() {
var i I var t *T
i = t // 类型赋予接口,需要注意的是 nil值的接口的方法也会被调用
describe(i)
i.M() i = &T{"hello"}
describe(i)
i.M()
} func describe(i I) {
fmt.Printf("(%v, %T)\n", i, i)
}

指定了零个方法的接口被称为空接口interface{}是空接口的类型,写在函数的参数表里面也是这样写的

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)
}

类型断言

类型断言 提供了访问接口值底层具体值的方式。

t := i.(T)

该语句断言接口值 i 保存了具体类型 T,并将其底层类型为 T 的值赋予变量 t

i 并未保存 T 类型的值,该语句就会触发一个恐慌。

为了 判断 一个接口值是否保存了一个特定的类型,类型断言可返回两个值:其底层值以及一个报告断言是否成功的布尔值。

t, ok := i.(T)

i 保存了一个 T,那么 t 将会是其底层值,而 oktrue

否则,ok 将为 falset 将为 T 类型的零值,程序并不会产生恐慌。

请注意这种语法和读取一个映射时的相同之处。

package main

import "fmt"

func main() {
var i interface{} = "hello" s := i.(string)
fmt.Println(s) s, ok := i.(string)
fmt.Println(s, ok) f, ok := i.(float64)
fmt.Println(f, ok) f = i.(float64) // panic
fmt.Println(f)
}

类型选择

类型选择 是一种按顺序从几个类型断言中选择分支的结构。

类型选择与一般的 switch 语句相似,不过类型选择中的 case 为类型(而非值), 它们针对给定接口值所存储的值的类型进行比较。

switch v := i.(type) {
case T:
// v 的类型为 T
case S:
// v 的类型为 S
default:
// 没有匹配,v 与 i 的类型相同
}

类型选择中的声明与类型断言 i.(T) 的语法相同,只是具体类型 T 被替换成了关键字 type

此选择语句判断接口值 i 保存的值类型是 T 还是 S。在 TS 的情况下,变量 v 会分别按 TS 类型保存 i 拥有的值。在默认(即没有匹配)的情况下,变量 vi 的接口类型和值相同。

package main

import "fmt"

func do(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("Twice %v is %v\n", v, v*2)
case string:
fmt.Printf("%q is %v bytes long\n", v, len(v))
default:
fmt.Printf("I don't know about type %T!\n", v)
}
} func main() {
do(21)
do("hello")
do(true)
}

Go 入门 - 方法和接口的更多相关文章

  1. JAVAEE——Mybatis第一天:入门、jdbc存在的问题、架构介绍、入门程序、Dao的开发方法、接口的动态代理方式、SqlMapConfig.xml文件说明

    1. 学习计划 第一天: 1.Mybatis的介绍 2.Mybatis的入门 a) 使用jdbc操作数据库存在的问题 b) Mybatis的架构 c) Mybatis的入门程序 3.Dao的开发方法 ...

  2. Go 语言入门(二)方法和接口

    写在前面 在学习 Go 语言之前,我自己是有一定的 Java 和 C++ 基础的,这篇文章主要是基于A tour of Go编写的,主要是希望记录一下自己的学习历程,加深自己的理解 Go 语言入门(二 ...

  3. 结合个人经历总结的前端入门方法 (转自https://github.com/qiu-deqing/FE-learning)

    结合个人经历总结的前端入门方法 (https://github.com/qiu-deqing/FE-learning),里面有很详细的介绍. 之前一直想学习前端的,都不知道怎么下手都一年了啥也没学到, ...

  4. Mock Server 实现post方法的接口(三)

    Mock Server 实现post方法的接口(三) 1.mock server实现的接口,当request中未设置"method"时,会自动将所有method试一次,所以一定要指 ...

  5. mock server 实现get方法的接口(二)

    mock server 实现get方法的接口(二) 下面是实现查询品牌的接口demo: 1.当response数据量小的时候,可以直接使用json, mock会自动设置headers为applicat ...

  6. C#属性-索引器-里氏替换-多态-虚方法-抽象-接口-泛型-

    1.属性 //属性的2种写法 public class person { private string _name; public string Name { get { return _name; ...

  7. GoLang之方法与接口

    GoLang之方法与接口 Go语言没有沿袭传统面向对象编程中的诸多概念,比如继承.虚函数.构造函数和析构函数.隐藏的this指针等. 方法 Go 语言中同时有函数和方法.方法就是一个包含了接受者的函数 ...

  8. jbuilder的set!方法重构接口

    https://github.com/rails/jbuilder  的set!方法重构接口, 因为grape没法使用 jBuilder 的缓存,所以直接用 Rails 写 API (1)多个图片 i ...

  9. 使用 highchart 绘制柱状图的通用方法与接口

    本文给出使用 highchart 绘制柱状图的通用方法与接口, 只要指定相应的数据结构和配置, 就可以直接拿来使用. 一.  数据结构与基本接口   一般绘制图形, 会涉及到较复杂的数据结构, 比如使 ...

随机推荐

  1. CVE-2016-3231

    摘要:重现了下韩国小哥Lokihardt在pwn2own上的过沙箱提权漏洞. 1 #include <windows.h> 2 #include <atlbase.h> 3 # ...

  2. Python 编码为什么那么蛋疼?

    据说,每个做 Python 开发的都被字符编码的问题搞晕过,最常见的错误就是 UnicodeEncodeError.UnicodeDecodeError,你好像知道怎么解决,遗憾的是,错误又出现在其它 ...

  3. 删除datatable的行后,出现“不能通过已删除的行访问该行的信息”的错误,即DeletedRowInaccessibleException

    删除datatable的行后,出现“不能通过已删除的行访问该行的信息”的错误 =========================================================== 采 ...

  4. ERROR Review:Unsupported major.minor version 52.0

    最近将AS从2.1.2升级至2.2版本后,项目编译报出了如下错误: java.lang.UnsupportedClassVersionError: com/android/build/gradle/L ...

  5. SAP S/4HANA生产订单的BAdI增强点之Initialize方法

    在S/4HANA里创建生产订单时,有一个增强点WORKORDER_UPDATE: 这个CAUFVDB里存放的是生产订单抬头级别的数据: 我们来观察下运行时这个结构里存放的数据. 请大家用我github ...

  6. 如何给Docker hub用户上传头像

    我第一次使用Docker hub时,觉得很奇怪,这个网站上面没有允许用户上传头像的地方. 后来经过研究才发现,需要用在Docker hub上注册用户的同一个邮箱到Gravatar这个网站上再注册一个账 ...

  7. 入职日志——Solomon

    心情 今天是所有培训结束后入职的第二天,紧张且期待. 紧张是因为昨天董经理有句话点醒了我. 你默默不再是个学生了.没有人会像你的老师父母一样担待你,原谅你. 职场是残酷无情的,是以结果为导向的.不论对 ...

  8. JAVA JAVA面试题和项目面试核心要点精华总结(想进大公司必看)

    http://blog.csdn.net/ourpush/article/details/53706524 1.常问数据库查询.修改(SQL查询包含筛选查询.聚合查询和链接查询和优化问题,手写SQL语 ...

  9. 关于使用eclipse maven UpdateProject时报错,无法更新本地仓库的问题解决方案

    在做项目中,需要从同事电脑中把Maven项目copy过来,但是copy的过程中只copy了代码,setting.xml文件和pom.xml,使用eclipse把项目导入,有红色的感叹号提示,由于我没有 ...

  10. Spring Boot Web Error Page处理

    spring Boot默认是whitelabel error page. 其实我们可以自己处理,由于时间有限,所以就简单说明一下方法. 首先配置 @Configuration public class ...