• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Go语言_神通路五耀篇(2)

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

1、Stringer接口

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

type Stringer interface {
    String() string
}

fmt包中有很多方法使用Stringer接口,如下:

package main

import (
"fmt"
)

type Person3 struct {
   Name string
   Age  int
}

func (p Person3) String() string {
   return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}

func main() {
   a := Person3{"Mujiutian", 89}
   z := Person3{"Clearlove7", 001}
   fmt.Println(a, z)
}

结果:

Mujiutian (89 years) Clearlove7 (1 years)

进入Sprintf方法中:

上面注释的含义是:根据格式说明符来格式化并返回结果字符串

然后点击进入打印方法doPrintf方法中:

因为这个方法代码行数太多,不能截图,所以把方法代码拷贝过来,之后截图最关键的地方:

func (p *pp) doPrintf(format string, a []interface{}) {
   end := len(format)
   argNum := 0         // we process one argument per non-trivial format
   afterIndex := false // previous item in format was an index like [3].
   p.reordered = false
formatLoop:
   for i := 0; i < end; {
      p.goodArgNum = true
      lasti := i
      for i < end && format[i] != '%' {
         i++
      }
      if i > lasti {
         p.buf.WriteString(format[lasti:i])
      }
      if i >= end {
         // done processing format string
         break
      }

      // Process one verb
      i++

      // Do we have flags?
      p.fmt.clearflags()
   simpleFormat:
      for ; i < end; i++ {
         c := format[i]
         switch c {
         case '#':
            p.fmt.sharp = true
         case '0':
            p.fmt.zero = !p.fmt.minus // Only allow zero padding to the left.
         case '+':
            p.fmt.plus = true
         case '-':
            p.fmt.minus = true
            p.fmt.zero = false // Do not pad with zeros to the right.
         case ' ':
            p.fmt.space = true
         default:
            // Fast path for common case of ascii lower case simple verbs
            // without precision or width or argument indices.
            if 'a' <= c && c <= 'z' && argNum < len(a) {
               if c == 'v' {
                  // Go syntax
                  p.fmt.sharpV = p.fmt.sharp
                  p.fmt.sharp = false
                  // Struct-field syntax
                  p.fmt.plusV = p.fmt.plus
                  p.fmt.plus = false
               }
               p.printArg(a[argNum], rune(c))
               argNum++
               i++
               continue formatLoop
            }
            // Format is more complex than simple flags and a verb or is malformed.
            break simpleFormat
         }
      }

      // Do we have an explicit argument index?
      argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))

      // Do we have width?
      if i < end && format[i] == '*' {
         i++
         p.fmt.wid, p.fmt.widPresent, argNum = intFromArg(a, argNum)

         if !p.fmt.widPresent {
            p.buf.WriteString(badWidthString)
         }

         // We have a negative width, so take its value and ensure
         // that the minus flag is set
         if p.fmt.wid < 0 {
            p.fmt.wid = -p.fmt.wid
            p.fmt.minus = true
            p.fmt.zero = false // Do not pad with zeros to the right.
         }
         afterIndex = false
      } else {
         p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end)
         if afterIndex && p.fmt.widPresent { // "%[3]2d"
            p.goodArgNum = false
         }
      }

      // Do we have precision?
      if i+1 < end && format[i] == '.' {
         i++
         if afterIndex { // "%[3].2d"
            p.goodArgNum = false
         }
         argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
         if i < end && format[i] == '*' {
            i++
            p.fmt.prec, p.fmt.precPresent, argNum = intFromArg(a, argNum)
            // Negative precision arguments don't make sense
            if p.fmt.prec < 0 {
               p.fmt.prec = 0
               p.fmt.precPresent = false
            }
            if !p.fmt.precPresent {
               p.buf.WriteString(badPrecString)
            }
            afterIndex = false
         } else {
            p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i, end)
            if !p.fmt.precPresent {
               p.fmt.prec = 0
               p.fmt.precPresent = true
            }
         }
      }

      if !afterIndex {
         argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
      }

      if i >= end {
         p.buf.WriteString(noVerbString)
         break
      }

      verb, size := rune(format[i]), 1
      if verb >= utf8.RuneSelf {
         verb, size = utf8.DecodeRuneInString(format[i:])
      }
      i += size

      switch {
      case verb == '%': // Percent does not absorb operands and ignores f.wid and f.prec.
         p.buf.WriteByte('%')
      case !p.goodArgNum:
         p.badArgNum(verb)
      case argNum >= len(a): // No argument left over to print for the current verb.
         p.missingArg(verb)
      case verb == 'v':
         // Go syntax
         p.fmt.sharpV = p.fmt.sharp
         p.fmt.sharp = false
         // Struct-field syntax
         p.fmt.plusV = p.fmt.plus
         p.fmt.plus = false
         fallthrough
      default:
         p.printArg(a[argNum], verb)
         argNum++
      }
   }

   // Check for extra arguments unless the call accessed the arguments
   // out of order, in which case it's too expensive to detect if they've all
   // been used and arguably OK if they're not.
   if !p.reordered && argNum < len(a) {
      p.fmt.clearflags()
      p.buf.WriteString(extraString)
      for i, arg := range a[argNum:] {
         if i > 0 {
            p.buf.WriteString(commaSpaceString)
         }
         if arg == nil {
            p.buf.WriteString(nilAngleString)
         } else {
            p.buf.WriteString(reflect.TypeOf(arg).String())
            p.buf.WriteByte('=')
            p.printArg(arg, 'v')
         }
      }
      p.buf.WriteByte(')')
   }
}

所以说Sprintf中实现了Stringer接口,其实fmt包下还有很多类似方法实现该接口。其实我们这一小节的目的就是看下底层源码实现Stringer接口了,封装到了fmt包中。

那么接下来,我们说Stringer主要是引入我们将要学习的error接口,这个很重要!

2、error接口

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

type error interface {
    Error() string
}

通常函数会返回一个 error 值,调用的它的代码应当判断这个错误是否等于 nil 来进行错误处理。当返回值等于nil时候,表示执行成功,为true,在java中用true表示,只不过go中用nil表示,否则,为false,就是出现错误!

package main

import (
   "strconv"
   "fmt"
)

func main()  {
   i, err := strconv.Atoi("42")
   if err != nil {
      fmt.Printf("couldn't convert number: %v\n", err)
      return
   }

   fmt.Print(i,err)
}

看上面的函数,strconv.Atoi 是数据转换类型,转换成整型,这个函数有没有执行成功取决于err返回值是否为nil,i就是函数执行结果,看上面结果1就是执行成功了。在几乎所有的开发中,都会有这种套路,利用error这个接口,大家可以搜一下,我这里只是基本简单介绍,不过之后的项目中会重新深入讲解的。

3、strconv包使用方法

这个strconv包下由多个go文件,这些go文件中包含了所有的函数和方法。当然还有对应的测试类!

3.1 atob.go

ParseBool 将字符串转换为布尔值

FormatBool 将布尔值转换为字符串 "true" 或 "false"

AppendBool 将布尔值 b 转换为字符串 "true" 或 "false"

3.2  atof.go

 ParseFloat 将字符串转换为浮点数

3.3 atoi.go

ErrRange 表示值超出范围

ErrSyntax 表示语法不正确

NumError 记录转换失败

ParseInt 将字符串转换为 int 类型

ParseUint 功能同 ParseInt 一样,只不过返回 uint 类型整数

Atoi 相当于 ParseInt(s, 10, 0)

3.4 itoa.go

FormatUint 将 int 型整数 i 转换为字符串形式

FormatUint 将 uint 型整数 i 转换为字符串形式

Itoa 相当于 FormatInt(i, 10)

AppendInt 将 int 型整数 i 转换为字符串形式,并追加到 dst 的尾部

AppendUint 将 uint 型整数 i 转换为字符串形式,并追加到 dst 的尾部

3.5 ftoa.go

FormatFloat 将浮点数 f 转换为字符串值

AppendFloat 将浮点数 f 转换为字符串值,并将转换结果追加到 dst 的尾部

3.6 quote.go

Quote 将字符串 s 转换为“双引号”引起来的字符串

AppendQuote 将字符串 s 转换为“双引号”引起来的字符串,并将结果追加到 dst 的尾部,返回追加后的 []byte

QuoteToASCII 将字符串 s 转换为“双引号”引起来的 ASCII 字符串,“非 ASCII 字符”和“特殊字符”将被转换为“转义字符”

AppendQuoteToASCII 将字符串 s 转换为“双引号”引起来的 ASCII 字符串,并将结果追加到 dst 的尾部,返回追加后的 []byte

QuoteRune 将 Unicode 字符转换为“单引号”引起来的字符串,“特殊字符”将被转换为“转义字符”

AppendQuoteRune 将 Unicode 字符转换为“单引号”引起来的字符串,并将结果追加到 dst 的尾部,返回追加后的 []byte

QuoteRuneToASCII 将 Unicode 字符转换为“单引号”引起来的 ASCII 字符串,“非 ASCII 字符”和“特殊字符”将被转换为“转义字符”

AppendQuoteRune 将 Unicode 字符转换为“单引号”引起来的 ASCII 字符串,并将结果追加到 dst 的尾部,返回追加后的 []byte

CanBackquote 判断字符串 s 是否可以表示为一个单行的“反引号”字符串,字符串中不能含有控制字符(除了 \t)和“反引号”字符,否则返回 false

关于第三节来源于博客:golang 中strconv包用法

 

....自己去实践理解吧,到时候用到哪里就查那里就好了。

 

 

 

 

转载于:https://my.oschina.net/mdxlcj/blog/1932766


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Go使用纯真IP数据库获取地理位置发布时间:2022-07-10
下一篇:
go get 加 -u 和不加 -u 参数的区别发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap