设为首页 加入收藏

TOP

Go指南 - 笔记(三)
2019-03-26 16:13:28 】 浏览:322
Tags:指南 笔记
t { X, Y float64 } func (v Vertex) Abs() float64 { reutrn 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) } func main() { v := Vertex{3, 4} fmt.Println(v.Abs()) // 5 fmt.Println(AbsFunc(v)) // 5 p := &Vertex{4, 3} fmt.Println(p.Abs()) // 5 fmt.Println(AbsFunc(*p)) // 5 }

2.接口

type I interface {
    [funcs]()
}

接口类型interface是由一组方法签名定义的集合。
接口类型的变量可以保存任何实现了这些方法的值。

type I interface {
    M()
}

type T struct {
    S string
}

// 此方法表示类型T实现了接口I,但我们无需显式声明此事
func (t T) M() {
    fmt.Println(t.S)
}

func main() {
    var i I = T{"Hello"}
    i.M() // Result: Hello
}

接口也是值。
接口可以像其它值一样传递。
接口值也可以用作函数的参数或返回值。

在内部,接口值可以看做包含值和具体类型的元组:

(value, type)

接口值保存了一个具体底层类型的具体值。
接口值调用方法时会执行其底层类型的同名方法。

type I interface {
    M()
}

type T struct {
    S string
}

func (t *T) M() {
    fmt.Println(t.S)
}

type F float64

func (f F) M() {
    fmt.Println(f)
}

func describe(i I) {
    fmt.Printf("(%v, %T)\n", i, i)
}

func main() {
    var i I
    
    i = &T{"Hello"}
    describe(i) // (&{Hello}, *main.T)
    i.M()       // Hello
    
    i = F(math.Pi)
    describe(i) // (3.141592653589793, main.F)
    i.M()       // 3.141592653589793
}

底层值为nil的接口值。
即便接口内的具体值为nil,方法仍然会被nil接收者调用。
保存了nil具体值的接口其自身并不为nil

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 describe(i I) {
    fmt.Printf("(%v, %T)\n", i, i)
}

func main() {
    var i I
    
    // nil接口值既不保存值也不保存具体类型。
    // 为nil接口调用方法会产生运行时错误,因为接口的元组内并未包含能够指明该调用哪个具体方法的类型。
    describe(i) // (<nil>, <nil>)
    i.M()       // 编译错误!
    
    var t *T
    i = t
    describe(i) // (<nil>, *main.T)
    i.M()       // <nil>
    
    i = &T{"Hello"}
    describe(i) // (&{hello}, *main.T)
    i.M()       // hello
}

指定了零个方法的接口值被称为空接口

interface {}

空接口可以保存任何类型的值(因为每个类型都至少实现了零个方法)。
空接口被用来处理未知类型的值。
例如fmt.Print可接受类型为interface {}的任意数量的参数。

3.类型断言

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

t := i.(T)

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

t, ok := i.(T)

如果i保存了一个T,那么t将会是其底层值,而oktrue;否则ok将为false,而t为类型T的零值。

4.类型选择

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

switch语句相似,case为类型。

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

5.Stringer

fmt包中定义的Stringer是最普遍的接口之一。

fmt.Sprintf()
package main

import "fmt"

type IPAddr [4]byte

// TODO: 给 IPAddr 添加一个 "String() string" 方法
func (ip IPAddr) String() string {
    return fmt.Sprintf("%v.%v.%v.%v", ip[0], ip[1], ip[2], ip[3])
}

func main() {
    hosts := map[string]IPAddr{
        "loopback":  {127, 0, 0, 1},
        "googleDNS": {8, 8, 8, 8},
    }
    for name, ip := range hosts {
        fmt.Printf("%v: %v\n", name, ip)
    }
}

6.错误

Go程序使用error值来表示错误状态。

error类型是一个内建接口:

type error interface {
    Error() string
}

errornil时表示成功,否则是失败。

7. Reader

io包指定了io.Reader接口,它表示从数据流的末尾进行读取。
在遇到数据流的结尾时,它会返回一个io.EOF错误。

func (T) Read(b []byte) (n int, err error)

8. 图像

image包定义了Image接口。

package image

type Image interface {
    ColorModel() color.Model
    Bounds() Rectangle
    At(x, y int) color.Color
}
package main

import (
    "golang.org/x/tour/pic"
    "image"
    "image/color"
)

type Image struct{}

func (i Image) ColorModel() color.Model {
    return color.RGBAModel
}

func (i Image) Bounds() image.Rectangle {
    return image.Rect(0
首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Go语言数组和切片的原理 下一篇Go基础(2)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目