Golang极简入门教程(二):方法和接口

方法

在 Golang 中没有类,不过我们可以为结构体定义方法。我们看一个例子:

代码如下:

package main
 
import (
    "fmt"
    "math"
)
 
type Vertex struct {
    X, Y float64
}
 
// 结构体 Vertex 的方法
// 这里的方法接收者(method receiver)v 的类型为 *Vertex
func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
 
func main() {
    v := &Vertex{3, 4}
    fmt.Println(v.Abs())
}

在这里方法的接收者使用指针类型而非值类型主要出于以下几点考虑(类似 C/C++ 等语言):

1.避免方法每次调用时,对接收者的不必要的拷贝
2.在方法内可以修改接收者的值

我们可以为任意类型定义方法,但以下情况除外:

1.如果类型定义在其他包中,不能为其定义方法
2.如果类型是基础类型,不能为其定义方法

代码如下:

package main
 
import (
    "fmt"
    "math"
)
 
// 定义一个类型 MyFloat
type MyFloat float64
 
// 注意此方法关联的类型是 MyFloat 而不是 *MyFloat
func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}
 
func main() {
    f := MyFloat(-math.Sqrt2)
    fmt.Println(f.Abs())
}

接口(interface)

接口也是一种类型(就像结构体一样)。一个接口类型包含了一组方法,一个接口类型能够持有那些实现了这些方法的值。范例:

代码如下:

// 定义接口 Abser
type Abser interface {
    Abs() float64
}
 
// 定义结构体 Vertex
type Vertex struct {
    X, Y float64
}
 
// 实现方法 Abs
func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
 
func main() {
    v := Vertex{3, 4}
    // 成功,能够持有 *Vertex 类型的值
    var a Abser = &v
    // 出错,不能持有 Vertex 类型的值
    // 因为在 *Vertex 上定义了方法 Abs,而未在 Vertex 上定义
    var b Abser = v
}

错误

Golang 提供了一个 error 接口:

代码如下:

type error interface {
    Error() string
}

我们通过 os.Open 函数来了解一下 error 的用法:

代码如下:

// 此函数用于打开一个文件
// 返回的第二个值为 error 类型
func Open(name string) (file *File, err error)

简单的例子:

代码如下:

package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    _, err := os.Open("test.txt")
    // 如果 err 不为 nil 表示存在错误
    if err != nil {
        fmt.Println(err)
    }
}

创建一个 error 值的最简单方式是使用 errors.New 函数:

代码如下:

func Sqrt(f float64) (float64, error) {
    if f < 0 {
        // 出错时返回一个错误
        return 0, errors.New("math: square root of negative number")
    }
    // ...
}

我们也可以定义一个新的 error 的实现(也就是实现接口 error):

代码如下:

type NegativeSqrtError float64
 
func (f NegativeSqrtError) Error() string {
    return fmt.Sprintf("math: square root of negative number %g", float64(f))
}

匿名域

结构体中可以存在只有类型而没有名字的域,它们被叫做匿名域。例如:

代码如下:

struct {
    T1
    *T2
}

一个结构体的匿名域中的域或者方法可以被此结构体实例直接访问:

代码如下:

package main
 
import "fmt"
 
type Car struct {
    wheelCount int
}
 
func (car *Car) numberOfWheels() int {
    return car.wheelCount
}
 
type Ferrari struct {
    Car
}
 
func main() {
    f := Ferrari{Car{4}}
    fmt.Println("A Ferrari has this many wheels: ", f.numberOfWheels())
}

(0)

相关推荐

  • Go语言中io.Reader和io.Writer的详解与实现

    一.前言 也许对这两个接口和相关的一些接口很熟悉了,但是你脑海里确很难形成一个对io接口的继承关系整天的概貌,原因在于godoc缺省并没有像javadoc一样显示官方库继承关系,这导致了我们对io接口的继承关系记忆不深,在使用的时候还经常需要翻文档加深记忆. 本文试图梳理清楚Go io接口的继承关系,提供一个io接口的全貌. 二.io接口回顾 首先我们回顾一下几个常用的io接口.标准库的实现是将功能细分,每个最小粒度的功能定义成一个接口,然后接口可以组成成更多功能的接口. 最小粒度的接口 typ

  • Go语言服务器开发实现最简单HTTP的GET与POST接口

    本文实例讲述了Go语言服务器开发实现最简单HTTP的GET与POST接口.分享给大家供大家参考.具体分析如下: Go语言提供了http包,可以很轻松的开发http接口.以下为示例代码: 复制代码 代码如下: package webserver    import (      "encoding/json"      "fmt"      "net/http"      "time"  )    func WebServerB

  • Go语言中接口组合的实现方法

    本文实例讲述了Go语言中接口组合的实现方法.分享给大家供大家参考.具体实现方法如下: 在Go语言中,可以在接口A中组合其它的一个或多个接口(如接口B.C),这种方式等价于在接口A中添加接口B.C中声明的方法. 复制代码 代码如下: //接口中可以组合其它接口,这种方式等效于在接口中添加其它接口的方法  type Reader interface {      read()  }  type Writer interface {      write()  }    //定义上述两个接口的实现类 

  • GO语io包的常用接口

    本文实例分析了GO语io包的常用接口.分享给大家供大家参考.具体分析如下: 我没有 C/C++ 基础,没有接口的概念,且从 Python 投奔而来,Python 的极简主义(一个结果往往只提供一个方法),让我在 Golang 中非常迷糊,特别是文件的读写操作,因为 Go 的文件读写操作有很多的方法,让我不知道怎么选择.直到我学习了 interface 的概念,然后由看了 package io 后才慢慢理解,也渐渐的喜欢上了 Golang 的灵活性.以我的经验来说,接口是一个很重要的知识点,是一系

  • 利用google提供的API(JavaScript接口)获取网站访问者IP地理位置的代码详解

    首先引入JavaScript API文件 <script type="text/javascript" src="http://j.maxmind.com/app/geoip.js"></script> 此API提供的接口共有6个,geoip_country_code(){国家代码},geoip_country_ name(){国家名称},geoip_city() {城市名称},geoip_region(){地区代码},geoip_latit

  • php调用google接口生成二维码示例

    复制代码 代码如下: <?php $data = isset($_GET['t']) ? $_GET['t'] : 'http://www.XXX.com'; $size = isset($_GET['size']) ? $_GET['size'] : '150x150'; $logo = isset($_GET['logo']) ? $_GET['logo'] :"./image/logo.jpg"; $chl = urlencode($logo); $png = "

  • Go语言接口用法实例

    本文实例讲述了Go语言接口用法.分享给大家供大家参考.具体分析如下: 接口类型是由一组方法定义的集合. 接口类型的值可以存放实现这些方法的任何值. 复制代码 代码如下: package main import (     "fmt"     "math" ) type Abser interface {     Abs() float64 } func main() {     var a Abser     f := MyFloat(-math.Sqrt2)   

  • Google Voice 短信发送接口PHP开源版(2010.5更新)

    1,支持群发 2,中文转成拼音发送 如果需要群发多帐号用英文逗号(,)分隔(86159..,86159..),消息内容不支持中文,当您输入中文的时候系统会自动转换为拼音(为了区分是拼音,拼音首字母大写),保证消息能正常发送(输入"我是旋风"短信内容为"Wo Shi Xuan Feng"). 复制代码 代码如下: <?php /* 提示:如果需要群发多帐号用英文逗号(,)分隔(86159..,86159..),消息内容不支持中文, 当您输入中文的时候系统会自动转

  • Google PR查询接口checksum新算法第1/2页

    取而代之的是一大段"In your email, please send us the entire code displayed below"之类的Google terms_of_service错误提示信息.看来是原先的接口已经失效了. 但我装在Firefox工具栏的扩展插件SearchStatus仍然能够正常解析出每个受访页的PR值,找到 SearchStatus 的插件包解开来看源码,果然是使用了不一样的验证码生成算法,在原先的 checksum 生成之后,还需要再进行一次计算,

  • Golang极简入门教程(二):方法和接口

    方法 在 Golang 中没有类,不过我们可以为结构体定义方法.我们看一个例子: 复制代码 代码如下: package main   import (     "fmt"     "math" )   type Vertex struct {     X, Y float64 }   // 结构体 Vertex 的方法 // 这里的方法接收者(method receiver)v 的类型为 *Vertex func (v *Vertex) Abs() float64

  • Golang极简入门教程(四):编写第一个项目

    workspace Golang 的代码必须放置在一个 workspace 中.一个 workspace 是一个目录,此目录中包含几个子目录: 1.src 目录.包含源文件,源文件被组织为包(一个目录一个包) 2.pkg 目录.包含包对象(package objects) 3.bin 目录.包含可执行的命令 包源文件(package source)被编译为包对象(package object),命令源文件(command source)被编译为可执行命令(command executable).

  • Golang极简入门教程(一):基本概念

    安装 Golang 在 http://golang.org/dl/ 可以下载到 Golang.安装文档:http://golang.org/doc/install. Hello Go 我们先创建一个文件 hello.go: 复制代码 代码如下: package main   import "fmt"   func main() {     fmt.Printf("hello Golang\n"); } 执行此程序: 复制代码 代码如下: go run hello.g

  • Golang极简入门教程(三):并发支持

    Golang 运行时(runtime)管理了一种轻量级线程,被叫做 goroutine.创建数十万级的 goroutine 是没有问题的.范例: 复制代码 代码如下: package main   import (     "fmt"     "time" )   func say(s string) {     for i := 0; i < 5; i++ {         time.Sleep(100 * time.Millisecond)       

  • Pytorch学习笔记DCGAN极简入门教程

    目录 1.图片分类网络 2.图片生成网络 首先是图片分类网络: 重点是生成网络 每一个step分为三个步骤: 1.图片分类网络 这是一个二分类网络,可以是alxnet ,vgg,resnet任何一个,负责对图片进行二分类,区分图片是真实图片还是生成的图片 2.图片生成网络 输入是一个随机噪声,输出是一张图片,使用的是反卷积层 相信学过深度学习的都能写出这两个网络,当然如果你写不出来,没关系,有人替你写好了 首先是图片分类网络: 简单来说就是cnn+relu+sogmid,可以换成任何一个分类网络

  • Go语言七篇入门教程三函数方法及接口

    目录 1. 函数 2. 方法 3. 接口 如何学习Go 参考书籍: <go语言程序设计> 1. 函数 每个函数声明都包含一个名字,一个形参列表,一个可选的返回列表以及函数体: func name(parameter-list)(result-list){ body } 形参列表:指定另一组变量的参数名和参数类型,这些局部变量都由调用者提供的提供的实参传递而来的. 返回列表:指定了函数返回值的类型.当函数返回一个未命名的返回值或者没有返回值的时候,返回列表的圆括号可以忽略. func FanOn

  • JavaScript极简入门教程(二):对象和函数

    阅读本文需要有其他语言的编程经验. JavaScript 中的简单类型包括: 1.数字 2.字符串 3.布尔(true 和 false) 4.null 5.undefined 此外的其他类型均是对象(我们不要被 typeof 操作符的返回值所迷惑),例如: 1.函数 2.数组 3.正则表达式 4.对象(对象自然也是对象) 对象基础 在 JavaScript 中,对象是属性的集合(对象为关联数组),每个属性包括: 1.属性名,必须为字符串 2.属性值,可以为除了 undefined 之外的任何值

  • Nodejs极简入门教程(二):定时器

    setTimeout 和 clearTimeout 复制代码 代码如下: var obj = setTimeout(cb, ms); setTimeout 用于设置一个回调函数 cb,其在最少 ms 毫秒后被执行(并非在 ms 毫秒后马上执行).setTimeout 返回值可以作为 clearTimeout 的参数,clearTimeout 用于停止定时器,这样回调函数就不会被执行了. setInterval 和 clearInterval 复制代码 代码如下: var obj = setInt

  • Nodejs极简入门教程(三):进程

    Node 虽然自身存在多个线程,但是运行在 v8 上的 JavaScript 是单线程的.Node 的 child_process 模块用于创建子进程,我们可以通过子进程充分利用 CPU.范例: 复制代码 代码如下: var fork = require('child_process').fork; // 获取当前机器的 CPU 数量 var cpus = require('os').cpus(); for (var i = 0; i < cpus.length; i++) {     // 生

  • Nodejs极简入门教程(一):模块机制

    JavaScript 规范(ECMAScript)没有定义一套完善的能适用于大多数程序的标准库.CommonJS 提供了一套 JavaScript 标准库规范.Node 实现了 CommonJS 规范. 模块基础 在 Node 中,模块和文件是一一对应的.我们定义一个模块: 复制代码 代码如下: // circle.js var PI = Math.PI;   // 导出函数 area exports.area = function(r) {     return PI * r * r; }  

随机推荐