引入

Go 是强类型语言,不同类型之间不能隐式转换。intfloat64 运算要手动转换,"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)))  // 4

strconv 包:字符串和数字互转

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

AtoiParseFloat 都返回两个值:转换结果和 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))     // 布尔值: true

type 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)intfloat64
int(f)float64int(截断)
int64(i)intint64
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),简洁统一
  • float64int截断,不是四舍五入
  • strconv 包处理字符串和数字的互转,比 fmt.Sprintf 更正规
  • strconvParse 系列函数返回 error必须检查
  • 类型断言 x.(T) 只对接口类型有效
  • 单值类型断言失败会 panic,双值方式更安全
  • 切片不能整体转换类型,必须逐个元素转换

理解

Go 的类型转换思路就是”不帮你猜”。intfloat64 运算?自己转。字符串变数字?用 strconv。接口值取具体类型?用类型断言。虽然代码要多写几行,但每一步都明明白白,不会有 C 语言那种隐式转换带来的精度丢失或溢出问题。记住三把工具:T(v) 转数值、strconv 转字符串、.(T) 断言接口。

引出

类型转换搞定了基本类型之间的关系。接下来进入函数部分——Go 函数,学习怎么定义函数、传参数、返回值,开始写真正有结构的代码。