Go 语言类型转换
显式转换、字符串与数字互转、`strconv`、以及类型别名与新类型。
Key PointsGo 没有隐式转换;`T(x)` 是转换,`type A B` 是新建类型。
基本类型转换
Go
var i int = 300
var f float64 = 3.99
var b byte = 65
fmt.Println(int64(i))
fmt.Println(float64(i) / 7)
fmt.Println(int(f)) // 截断 → 3
fmt.Println(string(b)) // "A",按码点转
fmt.Println(int('A')) // 65Output
300
42.857142857142854
3
A
65string(65) yields "A", not "65" — that is a rune conversion, not number formatting. Use strconv.Itoa(65). Someone trips on this every year.strconv
Go
// 数字 → 字符串
fmt.Println(strconv.Itoa(42))
fmt.Println(strconv.FormatInt(255, 16))
fmt.Println(strconv.FormatFloat(3.14159, 'f', 2, 64))
// 字符串 → 数字(注意返回 error)
n, err := strconv.Atoi("42")
fmt.Println(n, err)
bad, err := strconv.Atoi("4x")
fmt.Println(bad, err != nil)
// 布尔
v, _ := strconv.ParseBool("true")
fmt.Println(v)Output
42
ff
3.14
42 <nil>
0 true
true| Function | Use |
|---|---|
Itoa / Atoi | int ↔ string |
FormatInt / ParseInt | 任意进制整数 |
FormatFloat / ParseFloat | 浮点 |
Quote / Unquote | 加/去引号与转义 |
字符串与字节
Go
s := "hello"
b := []byte(s) // 复制
s2 := string(b) // 复制回来
r := []rune("中文")
fmt.Println(len(b), len(r))
fmt.Println(string(r[0]))
// 注意:转换会复制,大字符串频繁转换很贵Output
5 2
中别名 vs 新类型
Go
// 类型别名:完全等价,只是换个名字
type MyInt = int
var a MyInt = 1
var b int = a // 直接赋值,无需转换
// 新类型:不同的类型,需要显式转换
type Celsius float64
type Fahrenheit float64
c := Celsius(100)
// f := Fahrenheit(c) + 32 // 需要转换
f := Fahrenheit(c*9/5 + 32)
fmt.Println(c, f)Output
100 212type A = B is an alias; type A B creates a new type. The new type inherits the underlying operations but cannot mix with the original — exactly how you add type safety to units and IDs.
指针与接口转换
Go
var x any = "hello"
// 接口 → 具体类型:类型断言
s := x.(string)
fmt.Println(s)
// 安全断言
n, ok := x.(int)
fmt.Println(n, ok)
// 具体类型 → 接口:自动,无需转换
var y any = 42
fmt.Println(y)Output
hello
0 false
42x.(T) without ok panics on failure. In production, whenever the type is uncertain, use v, ok := x.(T). The type-assertion chapter covers this in depth.
基本类型转换
Go
var i int = 300
var f float64 = 3.99
var b byte = 65
fmt.Println(int64(i))
fmt.Println(float64(i) / 7)
fmt.Println(int(f)) // 截断 → 3
fmt.Println(string(b)) // "A",按码点转
fmt.Println(int('A')) // 65Output
300
42.857142857142854
3
A
65string(65) 得到 "A" 而不是 "65"——这是码点转字符,不是数字转字符串。要数字转字符串用 strconv.Itoa(65)。这个坑每年都有人踩。strconv
Go
// 数字 → 字符串
fmt.Println(strconv.Itoa(42))
fmt.Println(strconv.FormatInt(255, 16))
fmt.Println(strconv.FormatFloat(3.14159, 'f', 2, 64))
// 字符串 → 数字(注意返回 error)
n, err := strconv.Atoi("42")
fmt.Println(n, err)
bad, err := strconv.Atoi("4x")
fmt.Println(bad, err != nil)
// 布尔
v, _ := strconv.ParseBool("true")
fmt.Println(v)Output
42
ff
3.14
42 <nil>
0 true
true| 函数 | 用途 |
|---|---|
Itoa / Atoi | int ↔ string |
FormatInt / ParseInt | 任意进制整数 |
FormatFloat / ParseFloat | 浮点 |
Quote / Unquote | 加/去引号与转义 |
字符串与字节
Go
s := "hello"
b := []byte(s) // 复制
s2 := string(b) // 复制回来
r := []rune("中文")
fmt.Println(len(b), len(r))
fmt.Println(string(r[0]))
// 注意:转换会复制,大字符串频繁转换很贵Output
5 2
中别名 vs 新类型
Go
// 类型别名:完全等价,只是换个名字
type MyInt = int
var a MyInt = 1
var b int = a // 直接赋值,无需转换
// 新类型:不同的类型,需要显式转换
type Celsius float64
type Fahrenheit float64
c := Celsius(100)
// f := Fahrenheit(c) + 32 // 需要转换
f := Fahrenheit(c*9/5 + 32)
fmt.Println(c, f)Output
100 212type A = B 是别名(= 号),type A B 是新类型。新类型继承底层类型的所有操作,但不能和原类型混用——这正是给单位、ID 加类型安全的手段。
指针与接口转换
Go
var x any = "hello"
// 接口 → 具体类型:类型断言
s := x.(string)
fmt.Println(s)
// 安全断言
n, ok := x.(int)
fmt.Println(n, ok)
// 具体类型 → 接口:自动,无需转换
var y any = 42
fmt.Println(y)Output
hello
0 false
42x.(T) 不带 ok 时,断言失败会 panic。生产代码里只要不确定类型,就用 v, ok := x.(T) 形式。下一章「类型断言」会展开。