go入门(五) 2018-07-19

方法和接口

方法

Go语言中没有类,但是可以在结构类型上定义方法,实际上可以对包中的任意类型定义任意方法,但是不能对来自其他包的类型或基础数据类型来定义方法

方法的接收者

方法的接收者可以是指针类型,也可以是值类型

为什么要使用指针作为方法的接收者?

- 避免在每个方法调用中拷贝值
- 方法可以修改接收者指向的值

两种实现方式的对比

package main

import (
    "fmt"
    "math"
)

type Vertex struct {
    X, Y float64
}

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

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

func main() {
    v := &Vertex{3, 4}
    v.Scale(5)
    fmt.Println(v, v.Abs())    // &{15 20} 25
}


import (
    "fmt"
    "math"
)

type Vertex struct {
    X, Y float64
}

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

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

func main() {
    v := &Vertex{3, 4}
    v.Scale(5)
    fmt.Println(v, v.Abs())    // &{3 4} 5
}

对比传值和传地址的结果,可以发现传值的方式读入的v是v的副本,因而无法修改原始值,经过scale之后v的原始值并没有发生变化

接口

接口类型是由一组方法构成的集合,任何实现了接口中所有的方法的值都可以用接口的值来接收

package main

import (
    "fmt"
    "math"
)

type Abser interface {
    Abs() float64
}

type MyFloat float64

func (f MyFloat) Abs() float64 {
    if (f < 0) {
        return float64(-f)
    }
    return float64(f)
}

type Vertex struct {
    X, Y float64
}

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

func main() {
    var a Abser
    f := MyFloat(math.Sqrt2)
    v := Vertex{3, 4}

    a = f
    fmt.Println(a.Abs())
    a = &v
    fmt.Println(a.Abs())
}

接口的实现是隐式的,隐式接口解耦了实现接口的包和定义接口的包,互不依赖

空接口

interface{}空接口是指不包含任何方法的接口,空接口可以接收任何类型。常用来处理类型未知的值

空接口结合switch进行类型匹配

package main

import (
    "fmt"
)

func identifyType(i interface{}) {
    switch v := i.(type) {
    case int:
        fmt.Println("An int:", v)
    case float64:
        fmt.Println("A float64:", v)
    case string:
        fmt.Println("A string:", v, "length =", len(v))
    case bool:
        fmt.Println("A bool:", v)
    case rune:
        fmt.Println("A rune:", string(v))
    default:
        fmt.Printf("Unknown type: %T(%v)\n", v, v)
    }
}

type Vertex struct {
    X, Y float64
}

var pt Vertex = Vertex{1, 2}

var i interface{} = map[int]string{1: "hello", 2: "bye"}

func main() {
    identifyType(1200)
    identifyType(12.21)
    identifyType("hello")
    identifyType(true)
    identifyType('p')
    identifyType(func()int{return 1})
    identifyType([]int{1, 2, 3})
    identifyType(map[string]int{"hello": 100, "world": 200})
    identifyType(pt)
    identifyType(i)
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 8,075评论 2 9
  • 方法和接口 第四篇包含了方法和接口,可以用它们来定义对象和其行为;以及如何将所有内容贯通起来。 方法 Go 没有类...
    张洋铭Ocean阅读 5,357评论 2 0
  • 从小到大一直都有写作文,但在之前的学习中一直没有十分系统的、专业的去好好学习作文。直到大学学习了半个学期的...
    一只毛豆xm阅读 1,774评论 2 1
  • 离2017年还剩下30天。 朋友圈里有个有趣的段子说最恐怖的故事是还剩下30天,就是新的一年了。 昨晚和几个小伙伴...
    车马正简阅读 1,648评论 7 2
  • 一、概述 当子类需要父类的功能,而子类有新的内容,可以重写父类中的方法。在实际开发过程中,随着代码量的逐渐增加,维...
    丛鹏阅读 1,220评论 0 0

友情链接更多精彩内容