前言
数十年以来, 传统的面向对象语言总是说方法属于类, 但 Go 不是这样做的: 它提供了方法, 但是并没有提供类和对象。 乍一看, 这种做法似乎有些奇怪, 甚至可以说有点儿疯狂, 但实际上 Go 的方法比以往其他语言的方法都要灵活。
使用 kelvinToCelsius 、 celsiusToFahrenheit 、 fahrenheitToCelsius 、 celsiusToKelvin 这样的函数虽然也能够完成温度转换工作, 但是通过声明相应的方法并把它们放置到属于自己的地方, 能够让温度转换代码变得更加简洁明了。
我们可以将方法与同一个包中声明的任何类型相关联, 但是不能为 int 和 float64 之类的预声明类型关联方法。 其中, 声明类型的方法在前面已经介绍过了:
type kelvin float64
kelvin 类型跟它的底层类型 float64 具有相同的行为, 我们可以像处理浮点数那样, 对 kelvin 类型的值执行加法运算、乘法运算以及其他操作。 此外, 声明一个将 kelvin 转换为 celsius 的方法就跟声明一个具有同等作用的函数一样简单——它们都以关键字 func 开头, 并且函数体跟方法体完全一样:
func kelvinToCelsius(k kelvin) celsius { // kelvinToCelsius 函数 return celsius(k - 273.15) } func (k kelvin) celsius() celsius { // kelvin 类型的 celsius 方法 return celsius(k - 273.15) }
如图 13-1 所示, celsius 方法虽然没有接受任何形参, 但它的名字前面却有一个类似形参的接收者。 每个方法和函数都可以接受多个形参, 但一个方法必须并且只能有一个接收者。 在 celsius 方法体中, 接收者的行为就跟其他形参一样。
图 13-1 方法声明
除声明语法有些许不同之外, 调用方法的语法与调用函数的语法也不一样:
var k kelvin = 294.0 var c celsius c = kelvinToCelsius(k) // 调用 kelvinToCelsius 函数 c = k.celsius() // 调用celsius方法
跟调用其他包中的函数一样, 调用方法也需要用到点记号。 以上面的代码为例, 在调用方法的时候, 程序首先需要给出正确类型的变量, 接着是一个点号, 最后才是被调用方法的名字。
既然温度转换操作现在已经是 kelvin 类型的方法, 那么继续使用 kelvinToCelsius 这样的名字就没有必要了。 在同一个包里面, 如果一个名字已经被函数占用了, 那么这个包就无法再定义同名的类型, 因此在使用函数的情况下, 我们将无法使用 celsius 函数返回 celsius 类型的值。 然而, 如果我们使用的是方法, 那么每种温度类型都可以具有自己的 celsius 方法, 就像以下展示的 fahrenheit 类型一样:
type fahrenheit float64 // celsius方法会将华氏度转换为摄氏度 func (f fahrenheit) celsius() celsius { return celsius((f - 32.0) * 5.0 / 9.0) }
通过让每种温度类型都具有相应的 celsius 方法以转换为摄氏温度, 我们可以创造出一种完美的对称。
总结
到此这篇关于Go语言中如何通过方法为类型添加行为的文章就介绍到这了,更多相关Go语言通过方法为类型添加行为内容请搜索小牛知识库以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库!
问题内容: 我想在Route和Router类型上添加一个便捷的util方法: 但是编译器告诉我 无法在非本地类型mux.Router上定义新方法 那么我将如何实现呢?是否创建具有匿名mux.Route和mux.Router字段的新结构类型?或者是其他东西? 问题答案: 正如编译器所提到的,您不能在另一个包中扩展现有类型。您可以定义自己的别名或子包,如下所示: 或嵌入原始路由器:
是否可以在中的class中添加一个新的静态方法?通常,由于Kotlin Extensions,这样的事情在Kotlin中是可能的。 我已经尝试在一个名为的文件中执行以下操作: 但<code>数学。无法解析同伴。。。
类型断言(Type Assertion)是一个使用在接口值上的操作,用于检查接口类型变量所持有的值是否实现了期望的接口或者具体的类型。 在Go语言中类型断言的语法格式如下: value, ok := x.(T) 其中,x 表示一个接口的类型,T 表示一个具体的类型(也可为接口类型)。 该断言表达式会返回 x 的值(也就是 value)和一个布尔值(也就是 ok),可根据该布尔值判断 x 是否为 T
最近,我尝试了一些语法来修改文件的小部分。在这些测试用例中,我会保持大部分文件的原样,只是在这里和那里修改一些小的部分,请参见这个回顾问题的示例。 因此,我需要一个(或几个)动作方法(即语法的action类中的方法),在这里我将使用make方法将文件的修改部分附加到match对象。问题是语法本身会有更多的标记/规则/正则表达式,并且嵌套复杂。因此,需要(通过依次调用)将小更改(当前附加到令牌的匹配
本文向大家介绍go语言通过zlib压缩数据的方法,包括了go语言通过zlib压缩数据的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了go语言通过zlib压缩数据的方法。分享给大家供大家参考。具体实现方法如下: 希望本文所述对大家的Go语言程序设计有所帮助。
本文向大家介绍Go语言通过http抓取网页的方法,包括了Go语言通过http抓取网页的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Go语言通过http抓取网页的方法。分享给大家供大家参考。具体实现方法如下: 希望本文所述对大家的Go语言程序设计有所帮助。
主要内容:类型断言的书写格式,使用类型分支判断基本类型,使用类型分支判断接口类型type-switch 流程控制的语法或许是Go语言中最古怪的语法。 它可以被看作是类型断言的增强版。它和 switch-case 流程控制代码块有些相似。 一个 type-switch 流程控制代码块的语法如下所示: 输出结构如下: Type Square *main.Square with value &{5} 变量 t 得到了 areaIntf 的值和类型, 所有 case 语句中列举的类型
主要内容:区分类型别名与类型定义,非本地类型不能定义方法,在结构体成员嵌入时使用别名注意:本节内容涉及Go语言新版本的功能,内容上会涉及后续章节讲解的类型定义及结构体嵌入等特性。另外,本节内容适用于对Go语言很熟悉且正在关注工程升级、代码重构等问题的读者阅读。 类型别名是 Go 1.9 版本添加的新功能,主要用于解决代码升级、迁移中存在的类型兼容性问题。在 C/ C++ 语言中,代码重构升级可以使用宏快速定义一段新的代码,Go语言中没有选择加入宏,而是解决了重构中最麻烦的类型名变