Go 类型转换详解

0 阅读6分钟

Go 编程实战系列(十三)

上一篇《Go 布尔类型 bool 详解》中,我们学习了 Go 中的逻辑判断基础。

在实际开发中,不同类型的数据经常需要进行转换。

例如:

  • 用户输入通常是字符串;

  • 数据库 ID 通常是整数;

  • JSON 数据可能需要转换;

  • 配置文件读取出来通常是文本;

  • 网络传输的数据需要解析。

因此,类型转换是 Go 编程中非常重要的一部分。

Go 是一门强类型语言,与一些弱类型语言不同,Go 不会自动帮你完成大部分类型转换。

例如:

var age int = 20

var price float64 = 99.9

下面代码错误:

result := age + price

因为:

intfloat64

不是同一种类型

Go 要求开发者明确告诉编译器:

我要把什么类型转换成什么类型。

这种设计可以减少很多隐藏错误。

本文将详细介绍:

  • 什么是类型转换;

  • 基本类型转换;

  • 数字之间转换;

  • 字符串转换;

  • strconv 包;

  • 类型转换注意事项;

  • 常见错误。


一、什么是类型转换?

类型转换(Type Conversion)就是:

将一个数据从一种类型转换成另一种类型。

例如:

var a int = 100

var b int64 = int64(a)

这里:

int

转换为

int64

转换语法:

目标类型(变量)

例如:

float64(age)

表示:

将:

age

转换成:

float64

二、Go 为什么不支持隐式转换?

很多语言支持自动转换。

例如:

C:

int a = 10;

double b = a;

编译器自动完成转换。

但是 Go 不这样设计。

例如:

var a int = 10

var b int64 = a

错误:

cannot use a as int64

必须:

var b int64 = int64(a)

原因:

Go 希望代码更加明确。

例如:

int64(a)

看到代码就知道:

开发者主动进行了转换。

这样可以避免:

  • 数据丢失;

  • 精度错误;

  • 隐式行为。


三、整数类型转换

整数之间可以直接转换。

例如:

package main

import "fmt"

func main(){

	var a int = 100

	var b int64 = int64(a)

	fmt.Println(b)

}

输出:

100

int 转 int32

var a int = 1000

var b int32 = int32(a)

int64 转 int

var id int64 = 10001

var num int = int(id)

但是需要注意:

如果原来的数字超过目标类型范围,会发生数据丢失。

例如:

var num int64 = 999999999999

result := int32(num)

因为:

int32

无法保存这么大的数字。

可能导致:

  • 溢出;

  • 数据错误。


四、整数和浮点数转换

整数转浮点数:

var age int = 20

var score float64 = float64(age)

结果:

20

浮点数转整数:

var price float64 = 99.99

var num int = int(price)

结果:

99

注意:

Go 会直接截断小数。

不会:

99.99

变成

100

不会四舍五入。

如果需要四舍五入:

可以使用:

math.Round()

例如:

result := math.Round(99.99)

结果:

100

五、数字转字符串

实际开发中非常常见。

例如:

用户 ID:

id := 1001

需要拼接:

用户ID:1001

不能:

"用户ID:" + id

因为:

stringint

不能直接连接。

需要转换。


Go 推荐使用:

strconv

标准库。

导入:

import "strconv"

int 转 string

使用:

strconv.Itoa()

例如:

package main

import (
	"fmt"
	"strconv"
)

func main(){

	id := 1001

	text := strconv.Itoa(id)

	fmt.Println(text)

}

输出:

1001

拼接:

message := "用户ID:" + strconv.Itoa(id)

fmt.Println(message)

输出:

用户ID:1001

六、int64 转字符串

如果是:

int64

使用:

strconv.FormatInt()

例如:

var id int64 = 100000

text := strconv.FormatInt(id,10)

fmt.Println(text)

参数:

第二个:

10

表示十进制。


其他进制:

二进制:

strconv.FormatInt(id,2)

十六进制:

strconv.FormatInt(id,16)

七、字符串转数字

程序中大量数据来自:

  • HTTP 请求;

  • 表单;

  • JSON;

  • 配置文件。

这些通常都是字符串。

例如:

ageText := "20"

需要转换:

stringint

使用:

strconv.Atoi()

例如:

package main

import (
	"fmt"
	"strconv"
)

func main(){
	text := "20"
	age, err := strconv.Atoi(text)
	if err != nil {
		fmt.Println("转换失败")
		return
	}
	fmt.Println(age)
}

输出:

20

为什么返回两个值?

因为转换可能失败。

例如:

text := "hello"

无法转换成数字。

所以:

age, err

其中:

age

保存结果
err

保存错误信息

八、字符串转 int64

使用:

strconv.ParseInt()

例如:

id, err := strconv.ParseInt(
	"10001",
	10,
	64,
)

参数:

第一个:

字符串。

第二个:

进制。

第三个:

位数。


九、字符串转浮点数

使用:

strconv.ParseFloat()

例如:

price, err := strconv.ParseFloat(
	"99.99",
	64,
)

结果:

99.99

十、字符串转布尔值

使用:

strconv.ParseBool()

例如:

result, err := strconv.ParseBool(
	"true",
)

结果:

true

支持:

true

false

TRUE

FALSE

十一、布尔转字符串

使用:

strconv.FormatBool()

例如:

enabled := true

text := strconv.FormatBool(enabled)

fmt.Println(text)

输出:

true

十二、byte 与 string 转换

在 Go 中:

byte

本质:

uint8

经常用于处理数据。


字符串转 byte:

text := "Hello"

data := []byte(text)

fmt.Println(data)

输出:

[72 101 108 108 111]

byte 转字符串:

result := string(data)

fmt.Println(result)

输出:

Hello

应用场景:

  • 文件读取;

  • 网络通信;

  • 加密算法;

  • 图片处理。


十三、rune 与 string 转换

处理中文时,经常使用:

rune

例如:

text := "中国"

转换:

chars := []rune(text)

得到:

[中 国]

可以修改:

chars[0]='美'

再转换:

result := string(chars)

输出:

美国

十四、类型转换常见错误

1. 字符串不能直接转数字

错误:

num := int("100")

Go 不支持。

正确:

num, _ := strconv.Atoi("100")

2. 数字不能直接拼接字符串

错误:

id := 100

text := "ID:" + id

正确:

text := "ID:" + strconv.Itoa(id)

3. 忽略转换错误

错误:

age, _ := strconv.Atoi(text)

虽然可以运行,但是可能隐藏问题。

推荐:

age, err := strconv.Atoi(text)

if err != nil {

	return

}

4. 小数转换丢失精度

例如:

price := 99.99

num := int(price)

结果:

99

小数部分消失。


十五、实际开发中的类型转换场景

1. HTTP 参数转换

例如:

请求:

/user?id=100

获取:

id := "100"

转换:

userID, _ := strconv.Atoi(id)

2. JSON 数据处理

JSON:

{
 "age":"20"
}

字符串:

"20"

转换:

strconv.Atoi()

3. 数据库存储

数据库:

BIGINT

对应:

int64

4. 配置文件

例如:

yaml:

port: "8080"

程序:

port, _ := strconv.Atoi(portText)

十六、完整示例

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 转 stringstrconv.Itoa
int64 转 stringstrconv.FormatInt
string 转 intstrconv.Atoi
string 转 int64strconv.ParseInt
string 转 floatstrconv.ParseFloat
string 转 boolstrconv.ParseBool
bool 转 stringstrconv.FormatBool

掌握类型转换,是后续学习:

  • 文件处理;

  • HTTP 开发;

  • JSON;

  • 数据库;

  • Web API;

的重要基础。


本章练习

  1. 将 int 转换成 string。
  2. 将 string "100" 转换成 int。
  3. 将 float64 转换成 int,观察结果。
  4. 使用 strconv.ParseInt 转换用户 ID。
  5. 将 bool 转换成字符串。
  6. 将字符串转换成 []byte。
  7. 将中文字符串转换成 []rune 并修改字符。

下一篇预告

《Go fmt 包详解》

下一篇将介绍 Go 中最常用的标准库之一:

fmt

内容包括:

  • fmt.Println;

  • fmt.Printf;

  • fmt.Sprintf;

  • 格式化占位符;

  • 输出变量类型;

  • 格式化数字;

  • 格式化字符串;

  • 输入读取;

  • 实际开发中的日志输出技巧。

fmt 包是学习 Go、调试程序以及开发工具时使用频率最高的标准库之一。