引入
Go 是强类型语言,不同类型之间不能隐式转换。int 和 float64 运算要手动转换,"42" 和 42 不是同一个东西,接口值需要断言才能拿到具体类型。类型转换在 Go 里无处不在,必须显式地告诉编译器”我知道自己在干什么”。
正文
定义
定义
Go 类型转换分为三种:显式类型转换(数值类型之间用
T(v)语法)、strconv包(字符串和数字之间互转)、类型断言(从接口类型中取出具体类型的值)。Go 不支持隐式类型转换。
语法
// 显式类型转换
var f float64 = float64(42)
var i int = int(3.14)
// strconv 包
n, _ := strconv.Atoi("42")
s := strconv.Itoa(42)
// 类型断言
var x interface{} = "hello"
str := x.(string)例子
数值类型之间的转换
// int → float64
i := 42
f := float64(i) // 42.0
// float64 → int(截断,不是四舍五入)
f2 := 3.99
i2 := int(f2) // 3
// int32 → int64
var a int32 = 100
var b int64 = int64(a)
// uint8 → int
var c uint8 = 255
var d int = int(c)语法统一是 T(v),把值 v 转成类型 T。不会自动转,必须手动写。
float64 → int 是截断
fmt.Println(int(3.99)) // 3
fmt.Println(int(-3.99)) // -3不会四舍五入,直接丢掉小数部分。要四舍五入用 math.Round():
fmt.Println(int(math.Round(3.5))) // 4strconv 包:字符串和数字互转
import "strconv"
// 字符串 → int
n, err := strconv.Atoi("42")
if err != nil {
fmt.Println("转换失败:", err)
}
// 字符串 → float64
f, err := strconv.ParseFloat("3.14", 64)
// 字符串 → bool
b, err := strconv.ParseBool("true")
// int → 字符串
s1 := strconv.Itoa(42) // "42"
// float64 → 字符串
s2 := strconv.FormatFloat(3.14, 'f', 2, 64) // "3.14"
// bool → 字符串
s3 := strconv.FormatBool(true) // "true"| 函数 | 说明 | 示例 |
|---|---|---|
strconv.Atoi(s) | 字符串 → int | "42" → 42 |
strconv.Itoa(i) | int → 字符串 | 42 → "42" |
strconv.ParseFloat(s, 64) | 字符串 → float64 | "3.14" → 3.14 |
strconv.FormatFloat(f, 'f', 2, 64) | float64 → 字符串 | 3.14 → "3.14" |
strconv.ParseBool(s) | 字符串 → bool | "true" → true |
strconv.FormatBool(b) | bool → 字符串 | true → "true" |
strconv.ParseInt(s, 10, 64) | 字符串 → int64 | "42" → 42 |
Atoi 和 ParseFloat 都返回两个值:转换结果和 error,要检查 error。
类型断言
类型断言用于从接口类型中取出具体类型的值:
var x interface{} = "hello"
// 单返回值(转换失败会 panic)
s := x.(string)
fmt.Println(s) // "hello"
// 双返回值(安全方式,不会 panic)
s, ok := x.(string)
if ok {
fmt.Println("是字符串:", s)
}
n, ok := x.(int)
if !ok {
fmt.Println("不是 int")
}type switch
func describe(i interface{}) string {
switch v := i.(type) {
case int:
return fmt.Sprintf("整数: %d", v)
case string:
return fmt.Sprintf("字符串: %s", v)
case bool:
return fmt.Sprintf("布尔值: %v", v)
default:
return "未知类型"
}
}
fmt.Println(describe(42)) // 整数: 42
fmt.Println(describe("hello")) // 字符串: hello
fmt.Println(describe(true)) // 布尔值: truetype switch 可以一次判断多种类型,比写一堆 if-else 的类型断言清晰。
常见转换场景
// 切片类型转换
var ints []int = []int{1, 2, 3}
// var floats []float64 = ints // 错误!不能直接转切片
// 必须逐个转换
floats := make([]float64, len(ints))
for i, v := range ints {
floats[i] = float64(v)
}切片不能整体转换类型,即使元素类型可以转,也得循环逐个处理。
常见写法
| 写法 | 说明 |
|---|---|
float64(i) | int 转 float64 |
int(f) | float64 转 int(截断) |
int64(i) | int 转 int64 |
strconv.Atoi("42") | 字符串 → int |
strconv.Itoa(42) | int → 字符串 |
strconv.ParseFloat(s, 64) | 字符串 → float64 |
x.(string) | 类型断言(单值,会 panic) |
x.(string) + ok | 类型断言(双值,安全) |
switch v := x.(type) | type switch |
特点
- Go 没有隐式类型转换,所有转换必须显式写出
- 数值类型转换语法是
T(v),简洁统一 float64→int是截断,不是四舍五入strconv包处理字符串和数字的互转,比fmt.Sprintf更正规strconv的Parse系列函数返回error,必须检查- 类型断言
x.(T)只对接口类型有效 - 单值类型断言失败会 panic,双值方式更安全
- 切片不能整体转换类型,必须逐个元素转换
理解
Go 的类型转换思路就是”不帮你猜”。int 和 float64 运算?自己转。字符串变数字?用 strconv。接口值取具体类型?用类型断言。虽然代码要多写几行,但每一步都明明白白,不会有 C 语言那种隐式转换带来的精度丢失或溢出问题。记住三把工具:T(v) 转数值、strconv 转字符串、.(T) 断言接口。
引出
类型转换搞定了基本类型之间的关系。接下来进入函数部分——Go 函数,学习怎么定义函数、传参数、返回值,开始写真正有结构的代码。