Go 编程实战系列(十三)
上一篇《Go 布尔类型 bool 详解》中,我们学习了 Go 中的逻辑判断基础。
在实际开发中,不同类型的数据经常需要进行转换。
例如:
-
用户输入通常是字符串;
-
数据库 ID 通常是整数;
-
JSON 数据可能需要转换;
-
配置文件读取出来通常是文本;
-
网络传输的数据需要解析。
因此,类型转换是 Go 编程中非常重要的一部分。
Go 是一门强类型语言,与一些弱类型语言不同,Go 不会自动帮你完成大部分类型转换。
例如:
go
var age int = 20
var price float64 = 99.9
下面代码错误:
go
result := age + price
因为:
go
int
和
float64
不是同一种类型
Go 要求开发者明确告诉编译器:
我要把什么类型转换成什么类型。
这种设计可以减少很多隐藏错误。
本文将详细介绍:
-
什么是类型转换;
-
基本类型转换;
-
数字之间转换;
-
字符串转换;
-
strconv 包;
-
类型转换注意事项;
-
常见错误。
一、什么是类型转换?
类型转换(Type Conversion)就是:
将一个数据从一种类型转换成另一种类型。
例如:
css
var a int = 100
var b int64 = int64(a)
这里:
go
int
转换为
int64
转换语法:
scss
目标类型(变量)
例如:
scss
float64(age)
表示:
将:
age
转换成:
go
float64
二、Go 为什么不支持隐式转换?
很多语言支持自动转换。
例如:
C:
ini
int a = 10;
double b = a;
编译器自动完成转换。
但是 Go 不这样设计。
例如:
css
var a int = 10
var b int64 = a
错误:
php
cannot use a as int64
必须:
css
var b int64 = int64(a)
原因:
Go 希望代码更加明确。
例如:
scss
int64(a)
看到代码就知道:
开发者主动进行了转换。
这样可以避免:
-
数据丢失;
-
精度错误;
-
隐式行为。
三、整数类型转换
整数之间可以直接转换。
例如:
go
package main
import "fmt"
func main(){
var a int = 100
var b int64 = int64(a)
fmt.Println(b)
}
输出:
100
int 转 int32
css
var a int = 1000
var b int32 = int32(a)
int64 转 int
go
var id int64 = 10001
var num int = int(id)
但是需要注意:
如果原来的数字超过目标类型范围,会发生数据丢失。
例如:
go
var num int64 = 999999999999
result := int32(num)
因为:
go
int32
无法保存这么大的数字。
可能导致:
-
溢出;
-
数据错误。
四、整数和浮点数转换
整数转浮点数:
go
var age int = 20
var score float64 = float64(age)
结果:
20
浮点数转整数:
go
var price float64 = 99.99
var num int = int(price)
结果:
99
注意:
Go 会直接截断小数。
不会:
99.99
变成
100
不会四舍五入。
如果需要四舍五入:
可以使用:
lua
math.Round()
例如:
css
result := math.Round(99.99)
结果:
100
五、数字转字符串
实际开发中非常常见。
例如:
用户 ID:
bash
id := 1001
需要拼接:
makefile
用户ID:1001
不能:
bash
"用户ID:" + id
因为:
c
string
和
int
不能直接连接。
需要转换。
Go 推荐使用:
strconv
标准库。
导入:
arduino
import "strconv"
int 转 string
使用:
scss
strconv.Itoa()
例如:
go
package main
import (
"fmt"
"strconv"
)
func main(){
id := 1001
text := strconv.Itoa(id)
fmt.Println(text)
}
输出:
yaml
1001
拼接:
css
message := "用户ID:" + strconv.Itoa(id)
fmt.Println(message)
输出:
makefile
用户ID:1001
六、int64 转字符串
如果是:
go
int64
使用:
scss
strconv.FormatInt()
例如:
css
var id int64 = 100000
text := strconv.FormatInt(id,10)
fmt.Println(text)
参数:
第二个:
10
表示十进制。
其他进制:
二进制:
bash
strconv.FormatInt(id,2)
十六进制:
bash
strconv.FormatInt(id,16)
七、字符串转数字
程序中大量数据来自:
-
HTTP 请求;
-
表单;
-
JSON;
-
配置文件。
这些通常都是字符串。
例如:
go
ageText := "20"
需要转换:
c
string
↓
int
使用:
scss
strconv.Atoi()
例如:
go
package main
import (
"fmt"
"strconv"
)
func main(){
text := "20"
age, err := strconv.Atoi(text)
if err != nil {
fmt.Println("转换失败")
return
}
fmt.Println(age)
}
输出:
20
为什么返回两个值?
因为转换可能失败。
例如:
arduino
text := "hello"
无法转换成数字。
所以:
age, err
其中:
age
保存结果
err
保存错误信息
八、字符串转 int64
使用:
scss
strconv.ParseInt()
例如:
bash
id, err := strconv.ParseInt(
"10001",
10,
64,
)
参数:
第一个:
字符串。
第二个:
进制。
第三个:
位数。
九、字符串转浮点数
使用:
scss
strconv.ParseFloat()
例如:
css
price, err := strconv.ParseFloat(
"99.99",
64,
)
结果:
99.99
十、字符串转布尔值
使用:
scss
strconv.ParseBool()
例如:
css
result, err := strconv.ParseBool(
"true",
)
结果:
arduino
true
支持:
objectivec
true
false
TRUE
FALSE
十一、布尔转字符串
使用:
scss
strconv.FormatBool()
例如:
arduino
enabled := true
text := strconv.FormatBool(enabled)
fmt.Println(text)
输出:
arduino
true
十二、byte 与 string 转换
在 Go 中:
arduino
byte
本质:
go
uint8
经常用于处理数据。
字符串转 byte:
go
text := "Hello"
data := []byte(text)
fmt.Println(data)
输出:
csharp
[72 101 108 108 111]
byte 转字符串:
css
result := string(data)
fmt.Println(result)
输出:
Hello
应用场景:
-
文件读取;
-
网络通信;
-
加密算法;
-
图片处理。
十三、rune 与 string 转换
处理中文时,经常使用:
go
rune
例如:
arduino
text := "中国"
转换:
go
chars := []rune(text)
得到:
css
[中 国]
可以修改:
arduino
chars[0]='美'
再转换:
go
result := string(chars)
输出:
美国
十四、类型转换常见错误
1. 字符串不能直接转数字
错误:
go
num := int("100")
Go 不支持。
正确:
css
num, _ := strconv.Atoi("100")
2. 数字不能直接拼接字符串
错误:
bash
id := 100
text := "ID:" + id
正确:
scss
text := "ID:" + strconv.Itoa(id)
3. 忽略转换错误
错误:
arduino
age, _ := strconv.Atoi(text)
虽然可以运行,但是可能隐藏问题。
推荐:
go
age, err := strconv.Atoi(text)
if err != nil {
return
}
4. 小数转换丢失精度
例如:
go
price := 99.99
num := int(price)
结果:
99
小数部分消失。
十五、实际开发中的类型转换场景
1. HTTP 参数转换
例如:
请求:
bash
/user?id=100
获取:
bash
id := "100"
转换:
bash
userID, _ := strconv.Atoi(id)
2. JSON 数据处理
JSON:
json
{
"age":"20"
}
字符串:
arduino
"20"
转换:
scss
strconv.Atoi()
3. 数据库存储
数据库:
sql
BIGINT
对应:
go
int64
4. 配置文件
例如:
yaml:
vbnet
port: "8080"
程序:
css
port, _ := strconv.Atoi(portText)
十六、完整示例
go
package main
import (
"fmt"
"strconv"
)
func main(){
// 数字转字符串
age := 18
text := strconv.Itoa(age)
fmt.Println(text)
// 字符串转数字
num, err := strconv.Atoi(text)
if err == nil {
fmt.Println(num)
}
// 数字转浮点
score := float64(age)
fmt.Println(score)
}
输出:
18
18
18
十七、本章小结
本篇介绍了 Go 类型转换。
重点内容:
-
Go 不支持隐式类型转换;
-
转换必须明确指定;
-
数字之间可以直接转换;
-
浮点转整数会丢失小数;
-
字符串和数字转换使用 strconv;
-
byte 与 string 可以互相转换;
-
rune 适合处理中文;
-
类型转换需要注意范围和错误。
常用方法总结:
| 功能 | 方法 |
|---|---|
| int 转 string | strconv.Itoa |
| int64 转 string | strconv.FormatInt |
| string 转 int | strconv.Atoi |
| string 转 int64 | strconv.ParseInt |
| string 转 float | strconv.ParseFloat |
| string 转 bool | strconv.ParseBool |
| bool 转 string | strconv.FormatBool |
掌握类型转换,是后续学习:
-
文件处理;
-
HTTP 开发;
-
JSON;
-
数据库;
-
Web API;
的重要基础。
本章练习
- 将 int 转换成 string。
- 将 string "100" 转换成 int。
- 将 float64 转换成 int,观察结果。
- 使用 strconv.ParseInt 转换用户 ID。
- 将 bool 转换成字符串。
- 将字符串转换成 \[\]byte。
- 将中文字符串转换成 \[\]rune 并修改字符。
下一篇预告
《Go fmt 包详解》
下一篇将介绍 Go 中最常用的标准库之一:
fmt
内容包括:
-
fmt.Println;
-
fmt.Printf;
-
fmt.Sprintf;
-
格式化占位符;
-
输出变量类型;
-
格式化数字;
-
格式化字符串;
-
输入读取;
-
实际开发中的日志输出技巧。
fmt 包是学习 Go、调试程序以及开发工具时使用频率最高的标准库之一。