• 从零开始学Go之接口(三):常用内置接口


    Stringers:

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

    type Stringer interface {
     String() string
    }

    Stringer 是一个可以用字符串描述自己的类型。fmt 包(还有很多包)都通过此接口来打印值。

    type Person struct {
     Name string
     Age int
    }
    ​
    func (p Person) String() string {
     return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
    }
    ​
    func main() {
     a := Person{"Arthur Dent", 42}
     z := Person{"Zaphod Beeblebrox", 9001}
     fmt.Println(a, z)
    }

    运行结果:

    Arthur Dent (42 years)

    Zaphod Beeblebrox (9001 years)

    练习:https://tour.go-zh.org/methods/18

    通过让 IPAddr 类型实现 fmt.Stringer 来打印点号分隔的地址。

    例如,IPAddr{1, 2, 3, 4} 应当打印为 "1.2.3.4"

    type IPAddr [4]byte// TODO: 给 IPAddr 添加一个 "String() string" 方法
    func (i IPAddr) String(ipaddr [4]byte) string {
     return fmt.Sprintf("%v.%v.%v.%v", ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[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
    ", name, ip.String(ip))
     }
    }

    运行结果:

    loopback: 127.0.0.1

    googleDNS: 8.8.8.8

    错误:

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

    与 fmt.Stringer 类似,error 类型是一个内建接口:

    type error interface {
     Error() string
    }

    (与 fmt.Stringer 类似,fmt 包在打印值时也会满足 error。)

    通常函数会返回一个 error 值,调用的它的代码应当判断这个错误是否等于 nil 来进行错误处理。

    i, err := strconv.Atoi("42")
    if err != nil {
     fmt.Printf("couldn't convert number: %v
    ", err)
     return
    }
    fmt.Println("Converted integer:", i)

    error 为 nil 时表示成功;非 nil 的 error 表示失败。

    练习:https://tour.go-zh.org/methods/20

    之前的练习中复制 Sqrt 函数,修改它使其返回 error 值。

    Sqrt 接受到一个负数时,应当返回一个非 nil 的错误值。复数同样也不被支持。

    创建一个新的类型

    type ErrNegativeSqrt float64

    并为其实现

    func (e ErrNegativeSqrt) Error() string

    方法使其拥有 error 值,通过 ErrNegativeSqrt(-2).Error() 调用该方法应返回 "cannot Sqrt negative number: -2"

    修改 Sqrt 函数,使其接受一个负数时,返回 ErrNegativeSqrt 值。

    type ErrNegativeSqrt float64
    ​
    func Sqrt(x float64) (float64,error) {
     if x>=0 {
      return x,nil
     }
     return 0,ErrNegativeSqrt(x)
    }
    ​
    func (e ErrNegativeSqrt) Error() string {
     return fmt.Sprintf("cannot Sqrt negative number: %v", float64(e))//这里要加入float64()
    }
    ​
    func main() {
     fmt.Println(Sqrt(2))
     fmt.Println(Sqrt(-2))
    }

    运行结果:

    2 <nil>

    0 cannot Sqrt negative number: -2

    注意: 在 Error 方法内调用 fmt.Sprint(e) 会让程序陷入死循环。可以通过先转换 e 来避免这个问题:fmt.Sprint(float64(e))

    func (e ErrNegativeSqrt) Error() string {
     return fmt.Sprintf("cannot Sqrt negative number: %v", e)//问题代码
    }

    产生这个问题的原因是因为fmt.Sprintf通过接口查询知道e是一个接口类型,所以会调用e.Error()来构成一个字符串并返回,但同时e.Error()又调用了fmt.Sprintf,所以就完成了死循环。

  • 相关阅读:
    转dhdhtmlxTree
    转Merge的用法
    解决SqlServer2008评估期过期
    借鉴一下对比算法
    Asp.Net异常:"由于代码已经过优化或者本机框架位于调用堆栈之上,无法计算表达式的值"的解决方法
    查看Windows下引起Oracle CPU占用率高的神器-qslice
    今日有奖活动一览
    【分享】给做技术的战友们推荐一个不错的微信公号解解闷
    Unreal Engine Plugin management
    当在ECLIPSE中import现存项目时,如遇到版本不符
  • 原文地址:https://www.cnblogs.com/VingB2by/p/11119856.html
Copyright © 2020-2023  润新知