『Go 內建庫第一季:strconv』

wuxiaoshen發表於2018-11-01

大家好,我叫謝偉,是一名程式設計師。

近期會持續更新內建庫的學習內容,主要的參考文獻是: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()

複製程式碼

參考

迭代進行中


全文完,

相關文章