数据类型与变量
2026/3/20大约 14 分钟
数据类型与变量
一、类型系统概览
Go 是一门强类型静态语言,所有变量在编译时确定类型。Go 的类型系统简洁而强大,不支持隐式类型转换,这使得代码更加安全可靠。
Go 类型体系
├── 基本类型(Basic Types)
│ ├── 布尔型:bool
│ ├── 整数型:int, int8, int16, int32, int64
│ │ uint, uint8, uint16, uint32, uint64, uintptr
│ ├── 浮点型:float32, float64
│ ├── 复数型:complex64, complex128
│ ├── 字符型:byte(uint8), rune(int32)
│ └── 字符串:string
├── 复合类型(Composite Types)
│ ├── 数组:[N]T
│ ├── 切片:[]T
│ ├── 映射:map[K]V
│ └── 结构体:struct
├── 引用类型(Reference Types)
│ ├── 指针:*T
│ ├── 切片:[]T
│ ├── 映射:map[K]V
│ ├── 通道:chan T
│ └── 函数:func
└── 接口类型(Interface Types)
├── interface{}(空接口,Go 1.18 前)
└── any(Go 1.18+ 空接口别名)
二、变量声明
2.1 声明方式
Go 提供了多种变量声明方式,适用于不同场景:
package main
import "fmt"
func main() {
// 方式一:完整声明(指定类型和初始值)
var name string = "DevOps"
// 方式二:类型推断(省略类型,由编译器推断)
var age = 30
// 方式三:短变量声明(最常用,仅限函数内部)
host := "192.168.1.100"
port := 8080
// 方式四:只声明不赋值(使用零值初始化)
var isReady bool // false
var count int // 0
var message string // ""
var ratio float64 // 0.0
// 方式五:批量声明
var (
serverName string = "web-01"
serverPort int = 443
isHTTPS bool = true
)
// 方式六:多变量同时赋值
x, y, z := 1, 2.0, "three"
// 方式七:变量交换(Go 特有简洁写法)
a, b := 10, 20
a, b = b, a // 交换值,无需临时变量
fmt.Println(name, age, host, port)
fmt.Println(isReady, count, message, ratio)
fmt.Println(serverName, serverPort, isHTTPS)
fmt.Println(x, y, z)
fmt.Println(a, b) // 20, 10
}
2.2 零值机制
Go 的零值机制确保变量被声明后立即可用,无需显式初始化:
package main
import "fmt"
type Server struct {
Host string
Port int
}
func main() {
// 各类型的零值
var b bool // false
var i int // 0
var f float64 // 0.0
var s string // ""(空字符串)
var p *int // nil
var sl []int // nil(但可以直接 append)
var m map[string]int // nil(不能直接写入,需要 make)
var ch chan int // nil
var fn func() // nil
var iface error // nil
var st Server // {Host:"", Port:0}
fmt.Printf("bool: %v\n", b)
fmt.Printf("int: %v\n", i)
fmt.Printf("float64: %v\n", f)
fmt.Printf("string: %q\n", s)
fmt.Printf("pointer: %v\n", p)
fmt.Printf("slice: %v (nil: %v)\n", sl, sl == nil)
fmt.Printf("map: %v (nil: %v)\n", m, m == nil)
fmt.Printf("chan: %v\n", ch)
fmt.Printf("func: %v\n", fn)
fmt.Printf("error: %v\n", iface)
fmt.Printf("struct: %+v\n", st)
}
零值陷阱
nil的 slice 可以直接append,但nil的 map 不能直接赋值,必须先用make初始化- 指针零值是
nil,解引用会 panic
2.3 变量作用域
package main
import "fmt"
// 包级变量(全局作用域,包内可见)
var globalVar = "I am global"
// 大写开头:导出变量(其他包可访问)
var ExportedVar = "I am exported"
// 小写开头:未导出变量(仅本包可访问)
var internalVar = "I am internal"
func main() {
// 函数级变量
localVar := "I am local"
// 块级作用域
{
blockVar := "I am block-scoped"
fmt.Println(blockVar) // 正常
fmt.Println(localVar) // 正常,可访问外层
}
// fmt.Println(blockVar) // 编译错误:未定义
// if/for 块作用域
if x := 10; x > 5 {
fmt.Println(x) // x 仅在 if 块内可用
}
// fmt.Println(x) // 编译错误
// for 块作用域
for i := 0; i < 3; i++ {
fmt.Println(i)
}
// fmt.Println(i) // 编译错误
fmt.Println(globalVar, localVar)
}
三、基本数据类型
3.1 整数类型
package main
import (
"fmt"
"math"
"unsafe"
)
func main() {
// ========== 有符号整数 ==========
var i8 int8 = 127 // -128 ~ 127
var i16 int16 = 32767 // -32768 ~ 32767
var i32 int32 = 2147483647 // -2^31 ~ 2^31-1
var i64 int64 = 9223372036854775807 // -2^63 ~ 2^63-1
var i int = 42 // 平台相关:32 位或 64 位
// ========== 无符号整数 ==========
var u8 uint8 = 255 // 0 ~ 255
var u16 uint16 = 65535 // 0 ~ 65535
var u32 uint32 = 4294967295 // 0 ~ 2^32-1
var u64 uint64 = 18446744073709551615 // 0 ~ 2^64-1
var u uint = 42 // 平台相关
// ========== 特殊整数类型 ==========
var b byte = 'A' // uint8 的别名,用于表示 ASCII 字符
var r rune = '中' // int32 的别名,用于表示 Unicode 码点
var ptr uintptr // 足够存储指针的无符号整数
fmt.Printf("int8: %d, size: %d bytes\n", i8, unsafe.Sizeof(i8))
fmt.Printf("int: %d, size: %d bytes\n", i, unsafe.Sizeof(i))
fmt.Printf("byte: %c (%d)\n", b, b)
fmt.Printf("rune: %c (U+%04X)\n", r, r)
// ========== 整数字面量 ==========
decimal := 42 // 十进制
octal := 0o52 // 八进制(Go 1.13+ 推荐 0o 前缀)
hex := 0x2A // 十六进制
binary := 0b101010 // 二进制(Go 1.13+)
readable := 1_000_000 // 下划线分隔(Go 1.13+,提高可读性)
fmt.Printf("decimal=%d, octal=%d, hex=%d, binary=%d\n",
decimal, octal, hex, binary)
fmt.Printf("readable: %d\n", readable)
// ========== 常用操作 ==========
// 位运算(运维常用于权限、标志位)
permissions := 0o755
fmt.Printf("权限: %o (owner=%o, group=%o, other=%o)\n",
permissions,
(permissions>>6)&7,
(permissions>>3)&7,
permissions&7)
_ = i16; _ = i32; _ = i64
_ = u8; _ = u16; _ = u32; _ = u64; _ = u; _ = ptr
// 数值范围
fmt.Printf("int8 范围: %d ~ %d\n", math.MinInt8, math.MaxInt8)
fmt.Printf("int16 范围: %d ~ %d\n", math.MinInt16, math.MaxInt16)
fmt.Printf("int32 范围: %d ~ %d\n", math.MinInt32, math.MaxInt32)
fmt.Printf("int64 范围: %d ~ %d\n", math.MinInt64, math.MaxInt64)
}
3.2 浮点数类型
package main
import (
"fmt"
"math"
)
func main() {
var f32 float32 = 3.14
var f64 float64 = 3.141592653589793
// 科学计数法
avogadro := 6.022e23 // 6.022 × 10^23
planck := 6.626e-34 // 6.626 × 10^-34
fmt.Printf("float32: %.2f (精度约 7 位)\n", f32)
fmt.Printf("float64: %.15f (精度约 15 位)\n", f64)
fmt.Printf("avogadro: %e\n", avogadro)
fmt.Printf("planck: %e\n", planck)
// 特殊浮点值
inf := math.Inf(1) // 正无穷
negInf := math.Inf(-1) // 负无穷
nan := math.NaN() // 非数字
fmt.Printf("+Inf: %f, -Inf: %f, NaN: %f\n", inf, negInf, nan)
fmt.Println("NaN == NaN:", nan == nan) // false(NaN 不等于自身)
// 浮点数精度问题
a := 0.1
b := 0.2
c := 0.3
fmt.Printf("0.1 + 0.2 = %.20f\n", a+b)
fmt.Printf("0.1 + 0.2 == 0.3: %v\n", a+b == c) // false
// 正确的浮点比较方式
const epsilon = 1e-9
fmt.Printf("近似相等: %v\n", math.Abs((a+b)-c) < epsilon)
// 运维场景:计算磁盘使用率
totalDisk := 500.0 // GB
usedDisk := 387.5 // GB
usage := (usedDisk / totalDisk) * 100
fmt.Printf("磁盘使用率: %.1f%%\n", usage)
// 运维场景:CPU 负载阈值判断
loadAvg := 3.75
cpuCores := 4.0
loadPercent := (loadAvg / cpuCores) * 100
if loadPercent > 80 {
fmt.Printf("警告: CPU 负载 %.1f%% 超过阈值\n", loadPercent)
} else {
fmt.Printf("正常: CPU 负载 %.1f%%\n", loadPercent)
}
}
3.3 布尔类型
package main
import "fmt"
func main() {
var isRunning bool = true
var isStopped bool // 零值为 false
// 布尔运算
fmt.Println("AND:", isRunning && isStopped) // false
fmt.Println("OR:", isRunning || isStopped) // true
fmt.Println("NOT:", !isRunning) // false
// 运维场景:服务状态判断
httpOK := true
dbOK := true
cacheOK := false
// 全部健康才算健康
allHealthy := httpOK && dbOK && cacheOK
// 任一异常即告警
anyFailed := !httpOK || !dbOK || !cacheOK
fmt.Printf("全部健康: %v\n", allHealthy) // false
fmt.Printf("存在故障: %v\n", anyFailed) // true
// 注意:Go 中布尔值不能和整数互转
// var n int = true // 编译错误
// var b bool = 1 // 编译错误
// 如果需要转换,必须显式处理
flag := 1
b := flag != 0
fmt.Println("int to bool:", b)
}
3.4 字符串类型
字符串是运维开发中使用最频繁的类型之一:
package main
import (
"fmt"
"strings"
"strconv"
"unicode/utf8"
)
func main() {
// ========== 字符串声明 ==========
s1 := "Hello, Go!" // 双引号:解释型字符串
s2 := `Hello, "Go"!\n不会转义` // 反引号:原始字符串(保留原样)
s3 := "中文字符串"
fmt.Println(s1)
fmt.Println(s2)
fmt.Println(s3)
// ========== 字符串是不可变的 ==========
s := "hello"
// s[0] = 'H' // 编译错误:字符串不可修改
// 需要先转为 []byte 或 []rune
bs := []byte(s)
bs[0] = 'H'
s = string(bs)
fmt.Println(s) // "Hello"
// ========== 字符串长度 ==========
str := "Hello, 世界"
fmt.Println("len():", len(str)) // 13(字节数)
fmt.Println("RuneCountInString:", utf8.RuneCountInString(str)) // 9(字符数)
// ========== 字符串遍历 ==========
// 按字节遍历
for i := 0; i < len(str); i++ {
fmt.Printf("byte[%d] = %x\n", i, str[i])
}
// 按字符(rune)遍历(推荐)
for i, ch := range str {
fmt.Printf("rune[%d] = %c (U+%04X)\n", i, ch, ch)
}
// ========== 字符串操作 ==========
path := "/var/log/nginx/access.log"
// 包含判断
fmt.Println(strings.Contains(path, "nginx")) // true
fmt.Println(strings.HasPrefix(path, "/var")) // true
fmt.Println(strings.HasSuffix(path, ".log")) // true
// 查找
fmt.Println(strings.Index(path, "nginx")) // 9
fmt.Println(strings.LastIndex(path, "/")) // 15
// 分割
parts := strings.Split(path, "/")
fmt.Println(parts) // ["", "var", "log", "nginx", "access.log"]
// 连接
hosts := []string{"web-01", "web-02", "web-03"}
fmt.Println(strings.Join(hosts, ", "))
// 替换
config := "host=localhost port=3306"
config = strings.Replace(config, "localhost", "10.0.0.1", 1)
fmt.Println(config)
// 全部替换
config = strings.ReplaceAll(config, " ", "\n")
fmt.Println(config)
// 大小写转换
fmt.Println(strings.ToUpper("hello"))
fmt.Println(strings.ToLower("HELLO"))
fmt.Println(strings.Title("hello world"))
// 去除空白
fmt.Println(strings.TrimSpace(" hello "))
fmt.Println(strings.Trim("/path/", "/"))
fmt.Println(strings.TrimLeft(" hello", " "))
fmt.Println(strings.TrimRight("hello ", " "))
// 重复
fmt.Println(strings.Repeat("=", 40))
fmt.Println(strings.Repeat("-", 40))
// ========== 字符串与其他类型转换 ==========
// 数字 -> 字符串
n := 42
s4 := strconv.Itoa(n) // int -> string
s5 := fmt.Sprintf("%d", n) // 格式化
s6 := strconv.FormatFloat(3.14, 'f', 2, 64) // float -> string
s7 := strconv.FormatBool(true) // bool -> string
fmt.Println(s4, s5, s6, s7)
// 字符串 -> 数字
n2, err := strconv.Atoi("42") // string -> int
if err != nil {
fmt.Println("转换错误:", err)
}
f2, _ := strconv.ParseFloat("3.14", 64) // string -> float64
b2, _ := strconv.ParseBool("true") // string -> bool
n3, _ := strconv.ParseInt("FF", 16, 64) // 十六进制 -> int64
fmt.Printf("int=%d, float=%.2f, bool=%v, hex=%d\n", n2, f2, b2, n3)
}
3.5 字符串构建器
package main
import (
"fmt"
"strings"
)
func main() {
// 低效方式:字符串拼接(每次创建新字符串)
s := ""
for i := 0; i < 100; i++ {
s += fmt.Sprintf("line %d\n", i) // 每次都分配新内存
}
// 高效方式一:strings.Builder(推荐)
var builder strings.Builder
for i := 0; i < 100; i++ {
builder.WriteString(fmt.Sprintf("line %d\n", i))
}
result := builder.String()
fmt.Println(len(result))
// 高效方式二:预估容量
var b strings.Builder
b.Grow(4096) // 预分配空间
for i := 0; i < 100; i++ {
fmt.Fprintf(&b, "line %d\n", i)
}
// 运维场景:生成 Nginx 配置
var conf strings.Builder
conf.WriteString("server {\n")
conf.WriteString(" listen 80;\n")
conf.WriteString(" server_name example.com;\n")
conf.WriteString("\n")
conf.WriteString(" location / {\n")
conf.WriteString(" proxy_pass http://backend;\n")
conf.WriteString(" }\n")
conf.WriteString("}\n")
fmt.Println(conf.String())
}
四、类型转换
Go 不支持隐式类型转换,所有转换必须显式进行:
package main
import (
"fmt"
"strconv"
)
func main() {
// ========== 数值类型转换 ==========
var i int = 42
var f float64 = float64(i) // int -> float64
var u uint = uint(f) // float64 -> uint
fmt.Printf("int=%d, float64=%.1f, uint=%d\n", i, f, u)
// 注意精度丢失
var bigInt int64 = 1<<53 + 1
var asFloat float64 = float64(bigInt)
fmt.Printf("int64=%d, float64=%.0f, 精度丢失=%v\n",
bigInt, asFloat, int64(asFloat) != bigInt)
// 注意溢出
var big int32 = 256
var small int8 = int8(big)
fmt.Printf("int32=%d -> int8=%d (溢出)\n", big, small) // 0
// ========== 字符串与字节切片转换 ==========
s := "Hello, 世界"
bs := []byte(s) // string -> []byte
rs := []rune(s) // string -> []rune
fmt.Printf("bytes: %v\n", bs)
fmt.Printf("runes: %v\n", rs)
s2 := string(bs) // []byte -> string
s3 := string(rs) // []rune -> string
fmt.Println(s2, s3)
// 单个数字转字符串
fmt.Println(string(65)) // "A"(Unicode 码点)
fmt.Println(string(rune(20320))) // "你"
// 注意:string(42) 不是 "42",而是 "*"(ASCII 42)
// 正确的数字转字符串:
fmt.Println(strconv.Itoa(42)) // "42"
// ========== 类型断言(用于接口类型) ==========
var val interface{} = "hello"
// 安全断言(推荐)
if str, ok := val.(string); ok {
fmt.Println("是字符串:", str)
}
// 类型 switch
switch v := val.(type) {
case string:
fmt.Println("string:", v)
case int:
fmt.Println("int:", v)
case bool:
fmt.Println("bool:", v)
default:
fmt.Printf("未知类型: %T\n", v)
}
}
五、常量与 iota
5.1 常量声明
package main
import "fmt"
// 单个常量
const Pi = 3.14159265358979
const MaxRetry = 3
// 批量常量
const (
AppName = "ops-agent"
AppVersion = "2.1.0"
MaxConn = 1000
)
// 常量可以是类型化或无类型的
const (
TypedConst int = 100 // 类型化常量
UntypedConst = 100 // 无类型常量(更灵活)
)
func main() {
fmt.Println(AppName, AppVersion, MaxConn)
// 无类型常量可以用于不同类型的运算
var i int = UntypedConst
var f float64 = UntypedConst
var i32 int32 = UntypedConst
fmt.Println(i, f, i32)
// 但类型化常量不行
// var f2 float64 = TypedConst // 编译错误
var f2 float64 = float64(TypedConst) // 需要显式转换
fmt.Println(f2)
}
5.2 iota 枚举
iota 是 Go 的常量生成器,从 0 开始,每行递增 1:
package main
import "fmt"
// 基本用法
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)
// 自定义类型枚举(推荐方式)
type LogLevel int
const (
DEBUG LogLevel = iota // 0
INFO // 1
WARN // 2
ERROR // 3
FATAL // 4
)
func (l LogLevel) String() string {
names := [...]string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL"}
if l < DEBUG || l > FATAL {
return "UNKNOWN"
}
return names[l]
}
// 位运算枚举(适合权限、标志位)
type Permission uint
const (
Read Permission = 1 << iota // 1 (001)
Write // 2 (010)
Execute // 4 (100)
)
func (p Permission) String() string {
var perms []string
if p&Read != 0 {
perms = append(perms, "read")
}
if p&Write != 0 {
perms = append(perms, "write")
}
if p&Execute != 0 {
perms = append(perms, "execute")
}
return fmt.Sprintf("%v", perms)
}
// 跳过某些值
const (
_ = iota // 0 跳过
KB = 1 << (10 * iota) // 1 << 10 = 1024
MB // 1 << 20 = 1048576
GB // 1 << 30
TB // 1 << 40
PB // 1 << 50
)
// HTTP 状态码分组
type HTTPStatus int
const (
StatusOK HTTPStatus = 200
StatusCreated HTTPStatus = 201
StatusBadRequest HTTPStatus = 400
StatusUnauthorized HTTPStatus = 401
StatusForbidden HTTPStatus = 403
StatusNotFound HTTPStatus = 404
StatusInternalServerError HTTPStatus = 500
StatusBadGateway HTTPStatus = 502
StatusServiceUnavailable HTTPStatus = 503
)
func main() {
// 日志级别
level := WARN
fmt.Printf("当前日志级别: %s (%d)\n", level, level)
// 权限组合
perm := Read | Write
fmt.Printf("权限: %s (%03b)\n", perm, uint(perm))
fmt.Printf("有读权限: %v\n", perm&Read != 0)
fmt.Printf("有执行权限: %v\n", perm&Execute != 0)
// 添加权限
perm |= Execute
fmt.Printf("添加执行后: %s (%03b)\n", perm, uint(perm))
// 移除权限
perm &^= Write // AND NOT 操作
fmt.Printf("移除写入后: %s (%03b)\n", perm, uint(perm))
// 存储单位
fileSize := int64(3*GB + 512*MB)
fmt.Printf("文件大小: %d bytes (%.2f GB)\n", fileSize, float64(fileSize)/float64(GB))
}
六、格式化输出
6.1 fmt 包格式化动词
package main
import "fmt"
type Server struct {
Name string
IP string
Port int
}
func main() {
s := Server{Name: "web-01", IP: "10.0.0.1", Port: 8080}
// 通用动词
fmt.Printf("%%v: %v\n", s) // {web-01 10.0.0.1 8080}
fmt.Printf("%%+v: %+v\n", s) // {Name:web-01 IP:10.0.0.1 Port:8080}
fmt.Printf("%%#v: %#v\n", s) // main.Server{Name:"web-01", IP:"10.0.0.1", Port:8080}
fmt.Printf("%%T: %T\n", s) // main.Server
// 整数
n := 255
fmt.Printf("%%d: %d\n", n) // 255(十进制)
fmt.Printf("%%b: %b\n", n) // 11111111(二进制)
fmt.Printf("%%o: %o\n", n) // 377(八进制)
fmt.Printf("%%O: %O\n", n) // 0o377(带前缀八进制)
fmt.Printf("%%x: %x\n", n) // ff(小写十六进制)
fmt.Printf("%%X: %X\n", n) // FF(大写十六进制)
fmt.Printf("%%#x: %#x\n", n) // 0xff(带前缀)
// 浮点数
f := 3.14159265
fmt.Printf("%%f: %f\n", f) // 3.141593
fmt.Printf("%%.2f: %.2f\n", f) // 3.14
fmt.Printf("%%e: %e\n", f) // 3.141593e+00
fmt.Printf("%%g: %g\n", f) // 3.14159265
// 字符串
str := "Hello"
fmt.Printf("%%s: %s\n", str) // Hello
fmt.Printf("%%q: %q\n", str) // "Hello"
fmt.Printf("%%10s: %10s\n", str) // 右对齐,宽度10
fmt.Printf("%%-10s: %-10s|\n", str) // 左对齐,宽度10
// 布尔
fmt.Printf("%%t: %t\n", true) // true
// 指针
x := 42
fmt.Printf("%%p: %p\n", &x) // 0xc000012088
// 宽度和精度
fmt.Printf("|%10d|\n", 42) // | 42|
fmt.Printf("|%-10d|\n", 42) // |42 |
fmt.Printf("|%010d|\n", 42) // |0000000042|
fmt.Printf("|%+d|\n", 42) // |+42|
}
6.2 格式化实战
package main
import (
"fmt"
"strings"
)
type DiskInfo struct {
Mount string
Total uint64 // bytes
Used uint64
Avail uint64
}
func formatBytes(bytes uint64) string {
const (
KB = 1024
MB = KB * 1024
GB = MB * 1024
TB = GB * 1024
)
switch {
case bytes >= TB:
return fmt.Sprintf("%.1fT", float64(bytes)/float64(TB))
case bytes >= GB:
return fmt.Sprintf("%.1fG", float64(bytes)/float64(GB))
case bytes >= MB:
return fmt.Sprintf("%.1fM", float64(bytes)/float64(MB))
case bytes >= KB:
return fmt.Sprintf("%.1fK", float64(bytes)/float64(KB))
default:
return fmt.Sprintf("%dB", bytes)
}
}
func main() {
disks := []DiskInfo{
{"/", 107374182400, 42949672960, 64424509440},
{"/home", 536870912000, 214748364800, 322122547200},
{"/var", 214748364800, 193273528320, 21474836480},
}
// 表格式输出
header := fmt.Sprintf("%-12s %8s %8s %8s %6s", "Mount", "Total", "Used", "Avail", "Use%")
fmt.Println(header)
fmt.Println(strings.Repeat("-", len(header)+4))
for _, d := range disks {
usePercent := float64(d.Used) / float64(d.Total) * 100
status := ""
if usePercent > 80 {
status = " [WARNING]"
}
fmt.Printf("%-12s %8s %8s %8s %5.1f%%%s\n",
d.Mount,
formatBytes(d.Total),
formatBytes(d.Used),
formatBytes(d.Avail),
usePercent,
status,
)
}
}
输出效果:
Mount Total Used Avail Use%
----------------------------------------------------
/ 100.0G 40.0G 60.0G 40.0%
/home 500.0G 200.0G 300.0G 40.0%
/var 200.0G 180.0G 20.0G 90.0% [WARNING]
七、类型别名与自定义类型
package main
import "fmt"
// 类型定义(创建全新的类型)
type UserID int64
type IPAddress string
type Port uint16
// 类型别名(只是另一个名字,Go 1.9+)
type Byte = uint8 // 等同于 byte
type Rune = int32 // 等同于 rune
// 为自定义类型添加方法
func (ip IPAddress) IsPrivate() bool {
s := string(ip)
return len(s) > 3 && (s[:3] == "10." || s[:4] == "172." || s[:4] == "192.")
}
func (p Port) IsWellKnown() bool {
return p < 1024
}
func (p Port) String() string {
wellKnown := map[Port]string{
22: "SSH", 80: "HTTP", 443: "HTTPS",
3306: "MySQL", 5432: "PostgreSQL", 6379: "Redis",
8080: "HTTP-ALT", 9090: "Prometheus",
}
if name, ok := wellKnown[p]; ok {
return fmt.Sprintf("%d(%s)", p, name)
}
return fmt.Sprintf("%d", p)
}
func main() {
ip := IPAddress("192.168.1.100")
port := Port(443)
uid := UserID(10001)
fmt.Printf("IP: %s, 私有: %v\n", ip, ip.IsPrivate())
fmt.Printf("Port: %s, 知名端口: %v\n", port, port.IsWellKnown())
fmt.Printf("UserID: %d\n", uid)
// 类型定义不能直接赋值给原始类型
var n int64 = 100
// var id UserID = n // 编译错误
var id UserID = UserID(n) // 需要显式转换
fmt.Println(id)
// 类型别名可以直接赋值
var b Byte = 65
var u uint8 = b // OK,Byte 就是 uint8
fmt.Println(b, u)
}
八、本章小结
| 主题 | 核心要点 |
|---|---|
| 变量声明 | := 短声明最常用,var 用于包级变量和明确类型 |
| 零值机制 | 所有类型都有零值,确保变量可用 |
| 整数类型 | 注意 int 是平台相关的,跨平台用 int64 |
| 浮点数 | 不要直接比较,使用 epsilon 近似比较 |
| 字符串 | 不可变、UTF-8 编码、strings.Builder 高效拼接 |
| 类型转换 | 必须显式转换,注意精度丢失和溢出 |
| 常量/iota | iota 适合枚举、位掩码、存储单位 |
| 自定义类型 | 为原始类型添加语义和方法 |
运维开发建议
- 端口号用
uint16,IP 地址用string或net.IP - 文件大小用
int64(避免 32 位溢出) - 配置参数优先使用自定义类型,增加类型安全
- 字符串拼接用
strings.Builder,避免性能问题