『Gopher 』
首发于『Gopher 』
『Go 内置库第一季:strconv』

『Go 内置库第一季:strconv』

大家好,我叫谢伟,是一名程序员。

近期会持续更新内置库的学习内容,主要的参考文献是:godoc, 和源码

日常编写代码的过程中,字符串和数值型、布尔类型之间的转换算是很频繁了。所以有必要研究下内置的 strconv 库。

这节的主题是:字符串和其他基本数据类型之间的转换。

除此之外,还有其他类型的转换,最值得研究的就是 json , 这些内容,下期再讲。

大纲:

  • 有哪些基本的数据类型
  • 自己总结的常用的API
  • 文档给出的常用的API
  • 学到了什么

有哪些基本的数据类型

  • 既然是字符串和其他基本数据类之间的转换,那字符串可以操作的基本数据类型有哪些?
  • 字符串转换为其他数据类型的函数有什么相似点?
  • 其他数据类型转换为字符串有什么相似点?

怎么知道这些答案?

  • 看文档API
func Atoi(s string) (int, error)
func CanBackquote(s string) bool
func FormatBool(b bool) string
func FormatFloat(f float64, fmt byte, prec, bitSize int) string
func FormatInt(i int64, base int) string
func FormatUint(i uint64, base int) string
func IsGraphic(r rune) bool
func IsPrint(r rune) bool
func Itoa(i int) string
func ParseBool(str string) (bool, error)
func ParseFloat(s string, bitSize int) (float64, error)
func ParseInt(s string, base int, bitSize int) (i int64, err error)
func ParseUint(s string, base int, bitSize int) (uint64, error)

  1. 大概可以得出答案:基本的数据类型指的是:布尔类型、数值型(整型、浮点型)
  2. 其他数据类型转换为字符串的函数多以:Format 为关键字
  3. 字符串转换为其他数据类型的函数多以:Parse 为关键字

自己常用的有哪些用法

  • 字符串转整型: strconv.Atoi
func toInt(value string) (result int) {
    result, _ = strconv.Atoi(value)
    return

}

原理是:"abc" -- > a*100 + b*10 + c

  • 整型转字符串: strconv.Itoa
func toString(value int) (result string) {
    result = strconv.Itoa(value)
    return
}
  • 字符串和布尔型之间的转换
func toBool(value string) (result bool) {
    result, _ = strconv.ParseBool(value)
    return
}

func boolToString(value bool) (result string) {
    result = strconv.FormatBool(value)
    return
}
  • 字符串和浮点型数值之间的转换
func toFloat(value string) (result float64) {
    result, _ = strconv.ParseFloat(value, 32)
    return
}

func floatToString(value float64) (result string) {
    result = strconv.FormatFloat(value, 'E', -1, 32)
    return
}

浮点数需要注意精度。

因为数值存在进制的原因:所以需要熟悉这些概念:

  • base: 基准,进制 2,8,10,16
  • bitsize: 浮点类型 32,64

可以看出:

  • 字符串转其他类型容易出错,所以作者返回了 error, 关键字:Parse
  • 其他类型转字符串,没有错误处理, 关键字:Format

私以为,掌握这些能处理绝大多数场景。

文档给出的API

字符串和整型

func ParseInt(s string, base int, bitSize int) (i int64, err error)
func ParseUint(s string, base int, bitSize int) (n uint64, err error)
func Atoi(s string) (i int, err error)

func toBaseInt(value string) (result int64) {
    result, _ = strconv.ParseInt("123", 8, 32)
    return
}

表示将 8 进制的 “123” 的字符串转为整型:1*8*8+2*8+3*1=83

所以可以将任意进制的数据转换为 整型,字符串转成整型有错误处理,比如 7 进制的数“128” 出现 8, 那么肯定报错。

另外还存在无符号的数转换

func IntToString(value int64) (result string) {
    return strconv.FormatInt(value, 8)
}

func main(){
    fmt.Println(IntToString(123))
}

>> 173

8 进制的 173  10 进制的 123 相等
1*64 + 7*8 + 3 = 64 + 56 + 3 = 123

总结这种转换:

  • 注意进制
  • 注意精度

布尔和字符串

func ParseBool(str string) (value bool, err error)
func FormatBool(b bool) string

需要注意的是:

  • 布尔值不是只 true 和 false, 表达式的值,比如 0<1 也表示false
  • 字符串的 true 和 false, 下面这种情况不行:FAlse, TRue, tRUE, fALSE , 所以要么大写,要么小写,要么首字母大写,要么就单个字符,为了避免出现这种情况,最好将字符串统一小写或者大写处理

浮点型和字符串

func ParseFloat(s string, bitSize int) (f float64, err error)
func FormatFloat(f float64, fmt byte, prec, bitSize int) string

可能会对 参数 fmt 有疑问,其实很好理解,fmt 格式化对浮点型有哪些操作?

%b      无小数部分的,指数为二的幂的科学计数法,与 strconv.FormatFloat   
        的 'b' 转换格式一致。例如 -123456p-78
%e      科学计数法,例如 -1234.456e+78                                  Printf("%e", 10.2)                          1.020000e+01
%E      科学计数法,例如 -1234.456E+78                                  Printf("%e", 10.2)                          1.020000E+01
%f      有小数点而无指数,例如 123.456                                 Printf("%f", 10.2)                          10.200000
%g      根据情况选择 %e 或 %f 以产生更紧凑的(无末尾的0)输出             Printf("%g", 10.20)                         10.2
%G      根据情况选择 %E 或 %f 以产生更紧凑的(无末尾的0)输出             Printf("%G", 10.20+2i)                      (10.2+2i)

其他

func Quote(s string) string
func QuoteRune(r rune) string
func QuoteRuneToASCII(r rune) string
func QuoteRuneToGraphic(r rune) string
func QuoteToASCII(s string) string
func QuoteToGraphic(s string) string

简单来说,就是给加上引号, 适合双引号或者单引号内的内容加引号。

学到了什么

  • 错误处理

实现项目的中规范错误处理机制,比如错误码的含义,具体显示的信息之类的非常重要。

一般的项目中是如何处理的呢?

type ErrorCode struct{
    Code int
    Message string
}

func (e ErrorCode) Error()string{
    return fmt.Sprintf("Code: %d, Message: %s", e.Code, e.Message)
}


var Global strcut {
    ErrorRoute = ErrorCode{}
    ErrorDB = ErrorCode{}
    ...
}

看上去和 strconv 库的错误处理机制类似:

  • 定义一个结构体
  • 实现 error 接口
type NumError struct {
    Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat)
    Num  string // the input
    Err  error  // the reason the conversion failed (e.g. ErrRange, ErrSyntax, etc.)
}

func (e *NumError) Error() string {
    return "strconv." + e.Func + ": " + "parsing " + Quote(e.Num) + ": " + e.Err.Error()
}
  • 错误处理的两者实现方式
errors.New()
fmt.Errorf()

参考

迭代进行中

哔哩哔哩 ( ゜- ゜)つロ 乾杯~ Bilibilispace.bilibili.com
迭代进行中wuxiaoxiaoshen.github.io

发布于 2018-11-01

文章被以下专栏收录