1?
介紹
Go 語言作為強類型語言,在使用 Golang 開發項目時,經常會遇到類型轉換的場景,整型之間可以直接轉換,字節切片和字符串之間也可以直接轉換。
但是,如果整型和字符串之間做類型轉換,則需要使用?strconv
?標準庫提供的函數。
2?
標準庫?strconv
?類型轉換
Go 語言標準庫?strconv 提供了一些類型轉換的函數,比如在項目開發中使用比較多的整型和字符串之間的類型轉換。
func main() {salary := 5000salaryStr := strconv.Itoa(salary)fmt.Printf("%T salary=%d\n", salary, salary)fmt.Printf("%T salaryStr=%s\n", salaryStr, salaryStr)age := "23"ageInt, err := strconv.Atoi(age)fmt.Printf("%T age=%s\n", age, age)fmt.Printf("%T ageInt=%d err=%v\n", ageInt, ageInt, err)
}
輸出結果:
int salary=5000
string salaryStr=5000
string age=23
int ageInt=23 err=<nil>
閱讀上面這段代碼,我們使用標準庫?strconv
?將整型變量?salary
?轉換為字符串類型變量?salaryStr
;將字符串類型變量?age
?轉換為整型變量?ageInt
。
但是,讀者朋友們有沒有發現一個問題,我們使用標準庫?strconv
?提供的函數?Atoi
?將字符串類型變量轉換為整型變量,得到的是?int
?類型,如果我們需要得到一個?int8
?類型的變量,我們需要繼續做類型轉換,例如:
age := "23"
ageInt, err := strconv.Atoi(age)
ageInt8 := int8(ageInt)
也就是說,如果我們需要將一個字符串類型的變量轉換為一個非?int
?類型的整型變量,需要做二次轉換,在實際項目開發中,使用起來稍微繁瑣一些。
此外,使用標準庫?strconv
?做類型轉換,除了在一些場景中稍微繁瑣之外,還有另外一個問題,我們先閱讀以下一段代碼。
func main() {phoneNumber := "138001380001380013800013800138000"phoneNumberInt, err := strconv.Atoi(phoneNumber)fmt.Printf("%T phoneNumber=%s\n", phoneNumber, phoneNumber)fmt.Printf("%T phoneNumberInt=%d err=%v\n", phoneNumberInt, phoneNumberInt, err)
}
輸出結果:
string phoneNumber=138001380001380013800013800138000
int phoneNumberInt=9223372036854775807 err=strconv.Atoi: parsing "138001380001380013800013800138000": value out of range
閱讀上面這段代碼輸出的錯誤信息?value out of range
,也就是說如果我們需要轉換的值超出返回,Go 語言標準庫?strconv
?提供的函數?Atoi
?會返回錯誤。
所以,在使用函數?Atoi
?時,我們要做好參數驗證和錯誤處理。
有沒有使用更簡單的類型轉換庫,接下來,我們來看一下流行的三方庫?cast
。
3?
三方庫?cast
?類型轉換
Go 類型轉換的三方庫?cast
?是一個使用比較多的庫,我們使用?cast?來處理 Part02 的類型轉換需求,代碼如下:
func main() {age2 := "23"age2Int8 := cast.ToInt8(age2)fmt.Printf("%T age2=%s\n", age2, age2)fmt.Printf("%T age2Int8=%d\n", age2Int8, age2Int8)phoneNumber2 := "138001380001380013800013800138000"phoneNumber2Int := cast.ToInt(phoneNumber2)fmt.Printf("%T phoneNumber2=%s\n", phoneNumber2, phoneNumber2)fmt.Printf("%T phoneNumber2Int=%d\n", phoneNumber2Int, phoneNumber2Int)
}
輸出結果:
string?age2=23
int8?age2Int8=23
string?phoneNumber2=138001380001380013800013800138000
int?phoneNumber2Int=0
閱讀上面這段代碼,我們可以發現,使用?cast
?可以直接將字符串類型的變量轉換為我們需要的整型變量,使用起來不再感到繁瑣。
同時,需要注意的是,如果轉換失敗,將返回類型零值,字符串類型變量?phoneNumber2
?在使用?cast
?轉換為?int
?類型的變量時,返回的結果就是?int
?的類型零值。
使用?cast
?比使用?strconv
?更簡單,而且不需要處理錯誤。但是,cast
?還有一個陷阱,我們需要特別注意一下,我們先閱讀以下一段代碼:
func main() {month := "07"monthInt8 := cast.ToInt8(month)fmt.Printf("%T month=%s\n", month, month)fmt.Printf("%T monthInt8=%d\n", monthInt8, monthInt8)month2 := "08"month2Int8 := cast.ToInt8(month2)fmt.Printf("%T month2=%s\n", month2, month2)fmt.Printf("%T month2Int8=%d\n", month2Int8, month2Int8)
}
輸出結果:
string?month=07
int8?monthInt8=7
string?month2=08
int8?month2Int8=0
閱讀上面這段代碼的輸出結果,我們可以發現使用?cast
?將字符串類型?month
?和?month2
?轉換為整型時,字符串是以?"0"
?開頭的月份,"07"
?轉換后得到整型?7
,而?"08"
?轉換后得到整型?0
。
我們再使用?strconv
?轉換?"08"
,代碼如下:
func main() {month2 := "08"month2Int8 := cast.ToInt8(month2)fmt.Printf("%T month2=%s\n", month2, month2)fmt.Printf("%T month2Int8=%d\n", month2Int8, month2Int8)month2Int2, err := strconv.Atoi(month2)fmt.Printf("%T month2Int2=%d err=%v\n", month2Int2, month2Int2, err)
}
輸出結果:
int8?month2Int8=0
int?month2Int2=8?err=<nil>
讀者朋友們從輸出結果可以看到,"08"
?使用?strconv
?轉換后得到整型?8
,所以我們在轉換以一個或多個?"0"
?開頭的字符串為整型時,字符串?"0"
?后面的數值大于?7
?將不能使用?cast
?轉換,最好就是在轉換以一個或多個?"0"
?開頭的字符串為整型時,比如?"08"
、"009"
、"00010"
?等,使用?strconv
?轉換,而不要使用?cast
?轉換。
4?
總結
本文我們介紹 Go 語言類型轉換的兩個庫,分別是標準庫?strconv
?和三方庫?cast
,其中?cast
?更方便、更安全,但是也有陷阱,我們需要特別注意,避免在項目開發中掉進陷阱。
關于這兩個類型轉換庫的更多用法,感興趣的讀者朋友們可以熟讀手冊,多多動手練習。
參考資料:
strconv:?https://pkg.go.dev/strconv
cast:?https://github.com/spf13/cast