第2篇_Go语言基础语法_变量常量与数据类型

Go语言基础语法:变量、常量与数据类型

目录

前言

在上一篇文章中,我们了解了Go语言的发展历程和环境搭建。今天我们将深入学习Go语言的基础语法,重点掌握变量、常量和数据类型的使用。这些知识是Go语言编程的基石,掌握好这些内容将为后续的学习奠定坚实的基础。

Go语言作为一门强类型、静态编译的语言,在变量和类型处理上有着独特的设计哲学。它既保持了C语言的高效性,又提供了现代编程语言的便利性。让我们一起来探索Go语言在这方面的精妙设计。

变量声明的多种方式

1. 使用var关键字声明

Go语言提供了多种变量声明方式,其中最基础的是使用var关键字:

go 复制代码
package main

import "fmt"

func main() {
    // 方式1:声明并初始化
    var name string = "张三"
    var age int = 25
    var height float64 = 175.5
    
    // 方式2:先声明,后赋值
    var email string
    email = "zhangsan@example.com"
    
    // 方式3:类型推断
    var city = "北京"  // Go会自动推断为string类型
    var population = 21540000  // 自动推断为int类型
    
    // 方式4:批量声明
    var (
        username string = "admin"
        password string = "123456"
        isActive bool   = true
    )
    
    fmt.Printf("姓名: %s, 年龄: %d, 身高: %.1f\n", name, age, height)
    fmt.Printf("邮箱: %s, 城市: %s, 人口: %d\n", email, city, population)
    fmt.Printf("用户名: %s, 是否激活: %t\n", username, isActive)
}

2. 短变量声明(:=)

Go语言最具特色的是短变量声明操作符:=,它让代码更加简洁:

go 复制代码
package main

import "fmt"

func main() {
    // 短变量声明,只能在函数内使用
    name := "李四"
    age := 30
    salary := 8500.50
    married := true
    
    // 多变量同时声明
    x, y, z := 1, 2, 3
    
    // 函数返回值的接收
    result, err := divide(10, 2)
    if err != nil {
        fmt.Println("错误:", err)
        return
    }
    
    fmt.Printf("姓名: %s, 年龄: %d, 薪资: %.2f, 已婚: %t\n", 
               name, age, salary, married)
    fmt.Printf("坐标: (%d, %d, %d)\n", x, y, z)
    fmt.Printf("除法结果: %.2f\n", result)
}

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("除数不能为零")
    }
    return a / b, nil
}

3. 变量的零值

Go语言中,未初始化的变量会被赋予对应类型的零值:

go 复制代码
package main

import "fmt"

func main() {
    var (
        intVar    int     // 0
        floatVar  float64 // 0.0
        boolVar   bool    // false
        stringVar string  // ""
        pointerVar *int   // nil
    )
    
    fmt.Printf("int零值: %d\n", intVar)
    fmt.Printf("float64零值: %f\n", floatVar)
    fmt.Printf("bool零值: %t\n", boolVar)
    fmt.Printf("string零值: '%s'\n", stringVar)
    fmt.Printf("pointer零值: %v\n", pointerVar)
    
    // 判断字符串是否为空
    if stringVar == "" {
        fmt.Println("字符串变量为空")
    }
    
    // 判断指针是否为nil
    if pointerVar == nil {
        fmt.Println("指针变量为nil")
    }
}

Go语言基本数据类型详解

1. 数值类型

Go语言提供了丰富的数值类型,让我们详细了解:

go 复制代码
package main

import (
    "fmt"
    "unsafe"
)

func main() {
    // 整数类型
    var int8Var int8 = 127        // -128 到 127
    var int16Var int16 = 32767    // -32768 到 32767
    var int32Var int32 = 2147483647
    var int64Var int64 = 9223372036854775807
    
    // 无符号整数类型
    var uint8Var uint8 = 255      // 0 到 255
    var uint16Var uint16 = 65535  // 0 到 65535
    var uint32Var uint32 = 4294967295
    var uint64Var uint64 = 18446744073709551615
    
    // 浮点数类型
    var float32Var float32 = 3.14159
    var float64Var float64 = 3.141592653589793
    
    // 复数类型
    var complex64Var complex64 = 1 + 2i
    var complex128Var complex128 = 2 + 3i
    
    // 其他数值类型
    var intVar int = 42           // 根据系统位数决定大小
    var uintVar uint = 42         // 根据系统位数决定大小
    var byteVar byte = 255        // uint8的别名
    var runeVar rune = 'A'        // int32的别名,表示Unicode码点
    
    // 打印类型大小
    fmt.Printf("int8大小: %d字节\n", unsafe.Sizeof(int8Var))
    fmt.Printf("int16大小: %d字节\n", unsafe.Sizeof(int16Var))
    fmt.Printf("int32大小: %d字节\n", unsafe.Sizeof(int32Var))
    fmt.Printf("int64大小: %d字节\n", unsafe.Sizeof(int64Var))
    fmt.Printf("float32大小: %d字节\n", unsafe.Sizeof(float32Var))
    fmt.Printf("float64大小: %d字节\n", unsafe.Sizeof(float64Var))
    
    // 打印值
    fmt.Printf("复数64: %v\n", complex64Var)
    fmt.Printf("复数128: %v\n", complex128Var)
    fmt.Printf("rune值: %c (Unicode: %d)\n", runeVar, runeVar)
}

2. 字符串和字符类型

go 复制代码
package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    // 字符串类型
    var str1 string = "Hello, 世界!"
    str2 := `这是一个原始字符串
可以包含换行符
和特殊字符: \n \t`
    
    // 字符类型(rune)
    var char1 rune = 'A'
    var char2 rune = '世'
    var char3 rune = '🌟'
    
    // 字节类型(byte)
    var b1 byte = 'A'  // ASCII字符
    
    // 字符串操作
    fmt.Printf("字符串1: %s\n", str1)
    fmt.Printf("字符串1长度(字节): %d\n", len(str1))
    fmt.Printf("字符串1长度(字符): %d\n", utf8.RuneCountInString(str1))
    
    fmt.Printf("原始字符串:\n%s\n", str2)
    
    // 字符信息
    fmt.Printf("字符A: %c, Unicode: %d, 字节: %d\n", char1, char1, char1)
    fmt.Printf("字符世: %c, Unicode: %d\n", char2, char2)
    fmt.Printf("字符🌟: %c, Unicode: %d\n", char3, char3)
    fmt.Printf("字节A: %c, 值: %d\n", b1, b1)
    
    // 字符串遍历
    fmt.Println("按字节遍历:")
    for i := 0; i < len(str1); i++ {
        fmt.Printf("索引%d: %c\n", i, str1[i])
    }
    
    fmt.Println("按字符遍历:")
    for i, r := range str1 {
        fmt.Printf("索引%d: %c\n", i, r)
    }
}

3. 布尔类型

go 复制代码
package main

import "fmt"

func main() {
    // 布尔类型只有两个值:true和false
    var isActive bool = true
    var isComplete bool = false
    var isReady bool  // 零值为false
    
    // 布尔运算
    result1 := isActive && isComplete  // 逻辑与
    result2 := isActive || isComplete  // 逻辑或
    result3 := !isActive              // 逻辑非
    
    fmt.Printf("isActive: %t\n", isActive)
    fmt.Printf("isComplete: %t\n", isComplete)
    fmt.Printf("isReady: %t\n", isReady)
    fmt.Printf("AND运算: %t\n", result1)
    fmt.Printf("OR运算: %t\n", result2)
    fmt.Printf("NOT运算: %t\n", result3)
    
    // 条件判断
    age := 18
    if age >= 18 {
        fmt.Println("已成年")
    } else {
        fmt.Println("未成年")
    }
    
    // 复杂条件
    score := 85
    if score >= 90 {
        fmt.Println("优秀")
    } else if score >= 80 {
        fmt.Println("良好")
    } else if score >= 60 {
        fmt.Println("及格")
    } else {
        fmt.Println("不及格")
    }
}

常量定义和iota的使用

1. 常量的基本使用

go 复制代码
package main

import "fmt"

func main() {
    // 单个常量定义
    const PI float64 = 3.14159265359
    const COMPANY_NAME string = "科技有限公司"
    const MAX_USERS = 1000  // 类型推断
    
    // 批量常量定义
    const (
        StatusOK     = 200
        StatusError  = 500
        StatusNotFound = 404
    )
    
    // 无类型常量(更灵活)
    const MULTIPLIER = 10
    
    fmt.Printf("圆周率: %.10f\n", PI)
    fmt.Printf("公司名称: %s\n", COMPANY_NAME)
    fmt.Printf("最大用户数: %d\n", MAX_USERS)
    
    // 常量可以用于不同的数值类型
    var intVal int = MULTIPLIER
    var floatVal float64 = MULTIPLIER
    var complexVal complex128 = MULTIPLIER
    
    fmt.Printf("整数: %d, 浮点数: %.1f, 复数: %.1f\n", 
               intVal, floatVal, complexVal)
}

2. iota枚举器的强大功能

go 复制代码
package main

import "fmt"

func main() {
    // 基本iota使用
    const (
        Monday    = iota  // 0
        Tuesday   = iota  // 1
        Wednesday = iota  // 2
        Thursday  = iota  // 3
        Friday    = iota  // 4
        Saturday  = iota  // 5
        Sunday    = iota  // 6
    )
    
    // 简化写法
    const (
        January = iota + 1  // 1
        February            // 2
        March               // 3
        April               // 4
        May                 // 5
        June                // 6
        July                // 7
        August              // 8
        September           // 9
        October             // 10
        November            // 11
        December            // 12
    )
    
    // 跳过某些值
    const (
        _ = iota  // 跳过0
        KB = 1 << (10 * iota)  // 1024
        MB                     // 1048576
        GB                     // 1073741824
        TB                     // 1099511627776
    )
    
    // 复杂的iota表达式
    const (
        ReadPermission   = 1 << iota  // 1 (二进制: 001)
        WritePermission               // 2 (二进制: 010)
        ExecutePermission             // 4 (二进制: 100)
    )
    
    fmt.Printf("星期一: %d, 星期天: %d\n", Monday, Sunday)
    fmt.Printf("一月: %d, 十二月: %d\n", January, December)
    fmt.Printf("1KB = %d字节\n", KB)
    fmt.Printf("1MB = %d字节\n", MB)
    fmt.Printf("1GB = %d字节\n", GB)
    
    // 权限组合使用
    fullPermission := ReadPermission | WritePermission | ExecutePermission
    fmt.Printf("读权限: %d, 写权限: %d, 执行权限: %d\n", 
               ReadPermission, WritePermission, ExecutePermission)
    fmt.Printf("完整权限: %d (二进制: %b)\n", fullPermission, fullPermission)
}

3. 实际应用:状态机和配置常量

go 复制代码
package main

import "fmt"

// HTTP状态码
const (
    StatusContinue           = 100
    StatusSwitchingProtocols = 101
    StatusOK                 = 200
    StatusCreated            = 201
    StatusAccepted           = 202
    StatusNoContent          = 204
    StatusMovedPermanently   = 301
    StatusFound              = 302
    StatusBadRequest         = 400
    StatusUnauthorized       = 401
    StatusForbidden          = 403
    StatusNotFound           = 404
    StatusInternalServerError = 500
    StatusBadGateway         = 502
    StatusServiceUnavailable = 503
)

// 用户状态
const (
    UserStatusInactive = iota
    UserStatusActive
    UserStatusSuspended
    UserStatusDeleted
)

// 订单状态
const (
    OrderStatusPending = iota + 1  // 从1开始
    OrderStatusPaid
    OrderStatusShipped
    OrderStatusDelivered
    OrderStatusCancelled
)

func main() {
    // 模拟用户状态管理
    userStatus := UserStatusActive
    
    switch userStatus {
    case UserStatusInactive:
        fmt.Println("用户未激活")
    case UserStatusActive:
        fmt.Println("用户已激活")
    case UserStatusSuspended:
        fmt.Println("用户已暂停")
    case UserStatusDeleted:
        fmt.Println("用户已删除")
    default:
        fmt.Println("未知状态")
    }
    
    // 模拟HTTP响应处理
    responseCode := StatusNotFound
    
    if responseCode >= 200 && responseCode < 300 {
        fmt.Println("请求成功")
    } else if responseCode >= 400 && responseCode < 500 {
        fmt.Println("客户端错误")
    } else if responseCode >= 500 {
        fmt.Println("服务器错误")
    }
    
    // 订单状态流转
    orderStatus := OrderStatusPending
    fmt.Printf("当前订单状态: %d\n", orderStatus)
    
    // 状态升级
    orderStatus = OrderStatusPaid
    fmt.Printf("订单已支付,状态: %d\n", orderStatus)
}

类型转换和类型推断

1. 显式类型转换

go 复制代码
package main

import (
    "fmt"
    "strconv"
)

func main() {
    // 数值类型间的转换
    var intVal int = 42
    var floatVal float64 = float64(intVal)
    var float32Val float32 = float32(floatVal)
    var uintVal uint = uint(intVal)
    
    fmt.Printf("原始int: %d\n", intVal)
    fmt.Printf("转换为float64: %.2f\n", floatVal)
    fmt.Printf("转换为float32: %.2f\n", float32Val)
    fmt.Printf("转换为uint: %d\n", uintVal)
    
    // 注意:不同大小的整数类型转换
    var bigInt int64 = 1000000
    var smallInt int8 = int8(bigInt)  // 可能会溢出
    fmt.Printf("int64: %d -> int8: %d (注意溢出)\n", bigInt, smallInt)
    
    // 字符串和数值之间的转换
    var numStr string = "123"
    var strNum int
    
    // 字符串转数字
    if val, err := strconv.Atoi(numStr); err == nil {
        strNum = val
        fmt.Printf("字符串'%s'转换为数字: %d\n", numStr, strNum)
    }
    
    // 数字转字符串
    var num int = 456
    var result string = strconv.Itoa(num)
    fmt.Printf("数字%d转换为字符串: '%s'\n", num, result)
    
    // 更复杂的字符串数值转换
    floatStr := "3.14159"
    if floatNum, err := strconv.ParseFloat(floatStr, 64); err == nil {
        fmt.Printf("字符串'%s'转换为浮点数: %.5f\n", floatStr, floatNum)
    }
    
    // 布尔值转换
    boolStr := "true"
    if boolVal, err := strconv.ParseBool(boolStr); err == nil {
        fmt.Printf("字符串'%s'转换为布尔值: %t\n", boolStr, boolVal)
    }
}

2. 类型推断的智能性

go 复制代码
package main

import "fmt"

func main() {
    // 基本类型推断
    var a = 42        // int
    var b = 3.14      // float64
    var c = "hello"   // string
    var d = true      // bool
    var e = 'A'       // rune (int32)
    
    fmt.Printf("a的类型: %T, 值: %v\n", a, a)
    fmt.Printf("b的类型: %T, 值: %v\n", b, b)
    fmt.Printf("c的类型: %T, 值: %v\n", c, c)
    fmt.Printf("d的类型: %T, 值: %v\n", d, d)
    fmt.Printf("e的类型: %T, 值: %v\n", e, e)
    
    // 从表达式推断类型
    x := 10
    y := 20
    sum := x + y      // int
    avg := float64(sum) / 2  // float64
    
    fmt.Printf("sum的类型: %T, 值: %v\n", sum, sum)
    fmt.Printf("avg的类型: %T, 值: %v\n", avg, avg)
    
    // 从函数返回值推断类型
    result := calculateArea(5.0, 3.0)
    fmt.Printf("result的类型: %T, 值: %.2f\n", result, result)
    
    // 复杂表达式的类型推断
    complex1 := 1 + 2i       // complex128
    complex2 := complex64(1 + 2i)  // complex64
    
    fmt.Printf("complex1的类型: %T\n", complex1)
    fmt.Printf("complex2的类型: %T\n", complex2)
}

func calculateArea(length, width float64) float64 {
    return length * width
}

3. 类型断言和接口转换

go 复制代码
package main

import "fmt"

func main() {
    // 接口类型和类型断言
    var i interface{} = "hello world"
    
    // 类型断言(安全方式)
    if str, ok := i.(string); ok {
        fmt.Printf("成功断言为string: %s\n", str)
    } else {
        fmt.Println("断言失败")
    }
    
    // 类型断言(直接方式,可能panic)
    str := i.(string)
    fmt.Printf("直接断言: %s\n", str)
    
    // 类型选择
    checkType := func(x interface{}) {
        switch v := x.(type) {
        case int:
            fmt.Printf("整数: %d\n", v)
        case float64:
            fmt.Printf("浮点数: %.2f\n", v)
        case string:
            fmt.Printf("字符串: %s\n", v)
        case bool:
            fmt.Printf("布尔值: %t\n", v)
        default:
            fmt.Printf("未知类型: %T\n", v)
        }
    }
    
    checkType(42)
    checkType(3.14)
    checkType("Go语言")
    checkType(true)
    checkType([]int{1, 2, 3})
}

作用域和生命周期

1. 不同作用域的变量

go 复制代码
package main

import "fmt"

// 包级别变量(全局变量)
var globalVar string = "我是全局变量"
var packageVar = "我是包变量"

func main() {
    // 函数级别变量
    var functionVar string = "我是函数变量"
    localVar := "我是本地变量"
    
    fmt.Println("=== 作用域演示 ===")
    fmt.Println(globalVar)
    fmt.Println(packageVar)
    fmt.Println(functionVar)
    fmt.Println(localVar)
    
    // 块级作用域
    if true {
        blockVar := "我是块变量"
        fmt.Println(blockVar)
        
        // 可以访问外层变量
        fmt.Println("在块内访问函数变量:", functionVar)
        
        // 内层变量可以覆盖外层同名变量
        localVar := "我是内层的localVar"
        fmt.Println("内层localVar:", localVar)
    }
    
    // 块外无法访问块内变量
    // fmt.Println(blockVar)  // 编译错误
    
    fmt.Println("外层localVar:", localVar)  // 仍然是原值
    
    // for循环的作用域
    for i := 0; i < 3; i++ {
        loopVar := fmt.Sprintf("循环变量_%d", i)
        fmt.Println(loopVar)
    }
    // fmt.Println(i)       // 编译错误,i超出作用域
    // fmt.Println(loopVar) // 编译错误,loopVar超出作用域
    
    demonstrateScope()
}

func demonstrateScope() {
    fmt.Println("\n=== 函数作用域演示 ===")
    
    // 可以访问全局变量
    fmt.Println("在函数中访问全局变量:", globalVar)
    
    // 局部变量覆盖全局变量
    globalVar := "我是局部的globalVar"
    fmt.Println("局部覆盖后:", globalVar)
    
    // 嵌套函数的作用域
    innerFunction := func() {
        innerVar := "我是内部函数变量"
        fmt.Println(innerVar)
        fmt.Println("内部函数访问外层:", globalVar)
    }
    
    innerFunction()
}

2. 变量的生命周期

go 复制代码
package main

import (
    "fmt"
    "runtime"
)

// 全局变量在程序启动时创建,程序结束时销毁
var globalCounter int = 0

func main() {
    fmt.Println("=== 变量生命周期演示 ===")
    
    // 局部变量在函数调用时创建,函数返回时销毁
    localVar := "我是局部变量"
    fmt.Println(localVar)
    
    // 演示闭包中的变量生命周期
    counter := createCounter()
    fmt.Printf("第1次调用: %d\n", counter())
    fmt.Printf("第2次调用: %d\n", counter())
    fmt.Printf("第3次调用: %d\n", counter())
    
    // 演示指针和内存分配
    demonstrateMemoryAllocation()
    
    // 强制垃圾回收
    runtime.GC()
    fmt.Println("执行垃圾回收")
}

// 闭包函数,返回的函数保持对局部变量的引用
func createCounter() func() int {
    count := 0  // 这个变量的生命周期被延长了
    
    return func() int {
        count++
        return count
    }
}

func demonstrateMemoryAllocation() {
    fmt.Println("\n=== 内存分配演示 ===")
    
    // 栈分配的变量
    stackVar := 42
    fmt.Printf("栈变量地址: %p, 值: %d\n", &stackVar, stackVar)
    
    // 堆分配的变量(通过new创建)
    heapVar := new(int)
    *heapVar = 100
    fmt.Printf("堆变量地址: %p, 值: %d\n", heapVar, *heapVar)
    
    // 切片会在堆上分配
    slice := make([]int, 1000)
    slice[0] = 999
    fmt.Printf("切片首元素地址: %p, 值: %d\n", &slice[0], slice[0])
    
    // 大数组可能在堆上分配
    bigArray := [10000]int{1, 2, 3}
    fmt.Printf("大数组首元素地址: %p, 值: %d\n", &bigArray[0], bigArray[0])
}

3. 变量遮蔽(Shadowing)

go 复制代码
package main

import "fmt"

var x = "全局x"

func main() {
    fmt.Println("=== 变量遮蔽演示 ===")
    fmt.Printf("全局x: %s\n", x)
    
    // 函数级别遮蔽全局变量
    x := "函数x"
    fmt.Printf("函数x: %s\n", x)
    
    // 块级别遮蔽
    {
        x := "块x"
        fmt.Printf("块x: %s\n", x)
        
        // 更深层的遮蔽
        {
            x := "深层块x"
            fmt.Printf("深层块x: %s\n", x)
        }
        
        fmt.Printf("回到块x: %s\n", x)
    }
    
    fmt.Printf("回到函数x: %s\n", x)
    
    // 短变量声明的遮蔽陷阱
    demonstrateShadowingTrap()
}

func demonstrateShadowingTrap() {
    fmt.Println("\n=== 遮蔽陷阱演示 ===")
    
    var err error
    
    // 这里创建了一个新的err变量,遮蔽了外层的err
    if data, err := getData(); err != nil {
        fmt.Printf("内层err: %v\n", err)
    }
    
    // 外层的err仍然是nil
    fmt.Printf("外层err: %v\n", err)
    
    // 正确的做法
    var data string
    data, err = getData()
    if err != nil {
        fmt.Printf("正确方式的err: %v\n", err)
    } else {
        fmt.Printf("获取的数据: %s\n", data)
    }
}

func getData() (string, error) {
    return "hello", fmt.Errorf("模拟错误")
}

实战案例:构建一个简单的用户信息管理程序

让我们通过一个完整的案例来综合运用所学的知识:

go 复制代码
package main

import (
    "fmt"
    "strconv"
    "strings"
    "time"
)

// 用户状态常量
const (
    UserStatusInactive = iota
    UserStatusActive
    UserStatusSuspended
    UserStatusDeleted
)

// 用户类型常量
const (
    UserTypeRegular = iota + 1
    UserTypeVIP
    UserTypeAdmin
)

// 权限常量(使用位运算)
const (
    PermissionRead = 1 << iota
    PermissionWrite
    PermissionDelete
    PermissionAdmin
)

// 用户信息结构体(我们将在后续文章详细介绍结构体)
type User struct {
    ID          int
    Username    string
    Email       string
    Age         int
    Balance     float64
    IsActive    bool
    UserType    int
    Permissions int
    CreatedAt   time.Time
}

func main() {
    fmt.Println("=== 用户信息管理系统 ===")
    
    // 创建用户数据
    users := createSampleUsers()
    
    // 显示所有用户信息
    displayUsers(users)
    
    // 用户状态管理
    fmt.Println("\n=== 用户状态管理 ===")
    manageUserStatus()
    
    // 权限管理
    fmt.Println("\n=== 权限管理 ===")
    managePermissions()
    
    // 数据类型转换演示
    fmt.Println("\n=== 数据转换演示 ===")
    demonstrateDataConversion()
}

func createSampleUsers() []User {
    var users []User
    
    // 用户1:普通用户
    user1 := User{
        ID:          1,
        Username:    "张三",
        Email:       "zhangsan@example.com",
        Age:         25,
        Balance:     1500.50,
        IsActive:    true,
        UserType:    UserTypeRegular,
        Permissions: PermissionRead | PermissionWrite,
        CreatedAt:   time.Now().AddDate(0, -2, 0),
    }
    
    // 用户2:VIP用户
    user2 := User{
        ID:          2,
        Username:    "李四",
        Email:       "lisi@example.com",
        Age:         30,
        Balance:     5000.00,
        IsActive:    true,
        UserType:    UserTypeVIP,
        Permissions: PermissionRead | PermissionWrite | PermissionDelete,
        CreatedAt:   time.Now().AddDate(0, -6, 0),
    }
    
    // 用户3:管理员
    user3 := User{
        ID:          3,
        Username:    "管理员",
        Email:       "admin@example.com",
        Age:         35,
        Balance:     0.00,
        IsActive:    true,
        UserType:    UserTypeAdmin,
        Permissions: PermissionRead | PermissionWrite | PermissionDelete | PermissionAdmin,
        CreatedAt:   time.Now().AddDate(-1, 0, 0),
    }
    
    users = append(users, user1, user2, user3)
    return users
}

func displayUsers(users []User) {
    fmt.Println("\n当前用户列表:")
    fmt.Println(strings.Repeat("-", 80))
    fmt.Printf("%-3s %-10s %-20s %-3s %-10s %-8s %-10s %-10s\n",
        "ID", "用户名", "邮箱", "年龄", "余额", "状态", "类型", "权限")
    fmt.Println(strings.Repeat("-", 80))
    
    for _, user := range users {
        status := "激活"
        if !user.IsActive {
            status = "禁用"
        }
        
        userType := getUserTypeName(user.UserType)
        permissions := getPermissionNames(user.Permissions)
        
        fmt.Printf("%-3d %-10s %-20s %-3d %-10.2f %-8s %-10s %s\n",
            user.ID, user.Username, user.Email, user.Age, user.Balance,
            status, userType, permissions)
    }
}

func getUserTypeName(userType int) string {
    switch userType {
    case UserTypeRegular:
        return "普通用户"
    case UserTypeVIP:
        return "VIP用户"
    case UserTypeAdmin:
        return "管理员"
    default:
        return "未知"
    }
}

func getPermissionNames(permissions int) string {
    var perms []string
    
    if permissions&PermissionRead != 0 {
        perms = append(perms, "读")
    }
    if permissions&PermissionWrite != 0 {
        perms = append(perms, "写")
    }
    if permissions&PermissionDelete != 0 {
        perms = append(perms, "删")
    }
    if permissions&PermissionAdmin != 0 {
        perms = append(perms, "管理")
    }
    
    return strings.Join(perms, ",")
}

func manageUserStatus() {
    currentStatus := UserStatusActive
    
    fmt.Printf("当前用户状态: %s\n", getStatusName(currentStatus))
    
    // 状态转换
    currentStatus = UserStatusSuspended
    fmt.Printf("用户已被暂停: %s\n", getStatusName(currentStatus))
    
    currentStatus = UserStatusActive
    fmt.Printf("用户已恢复: %s\n", getStatusName(currentStatus))
}

func getStatusName(status int) string {
    switch status {
    case UserStatusInactive:
        return "未激活"
    case UserStatusActive:
        return "已激活"
    case UserStatusSuspended:
        return "已暂停"
    case UserStatusDeleted:
        return "已删除"
    default:
        return "未知状态"
    }
}

func managePermissions() {
    // 基础权限
    userPerms := PermissionRead
    fmt.Printf("初始权限: %s\n", getPermissionNames(userPerms))
    
    // 添加写权限
    userPerms |= PermissionWrite
    fmt.Printf("添加写权限后: %s\n", getPermissionNames(userPerms))
    
    // 添加删除权限
    userPerms |= PermissionDelete
    fmt.Printf("添加删除权限后: %s\n", getPermissionNames(userPerms))
    
    // 检查是否有特定权限
    if userPerms&PermissionWrite != 0 {
        fmt.Println("用户有写权限")
    }
    
    // 移除写权限
    userPerms &^= PermissionWrite
    fmt.Printf("移除写权限后: %s\n", getPermissionNames(userPerms))
}

func demonstrateDataConversion() {
    // 字符串转数字
    ageStr := "25"
    if age, err := strconv.Atoi(ageStr); err == nil {
        fmt.Printf("年龄字符串'%s'转换为数字: %d\n", ageStr, age)
    }
    
    // 浮点数转换
    balanceStr := "1500.50"
    if balance, err := strconv.ParseFloat(balanceStr, 64); err == nil {
        fmt.Printf("余额字符串'%s'转换为浮点数: %.2f\n", balanceStr, balance)
    }
    
    // 布尔值转换
    activeStr := "true"
    if isActive, err := strconv.ParseBool(activeStr); err == nil {
        fmt.Printf("状态字符串'%s'转换为布尔值: %t\n", activeStr, isActive)
    }
    
    // 数字转字符串
    userID := 12345
    userIDStr := strconv.Itoa(userID)
    fmt.Printf("用户ID %d 转换为字符串: '%s'\n", userID, userIDStr)
    
    // 格式化输出
    price := 99.99
    priceStr := fmt.Sprintf("%.2f", price)
    fmt.Printf("价格 %.2f 格式化为字符串: '%s'\n", price, priceStr)
}

最佳实践与小贴士

1. 变量命名最佳实践

go 复制代码
package main

import "fmt"

func main() {
    // ✅ 好的命名
    var userName string = "张三"
    var userAge int = 25
    var isUserActive bool = true
    var maxRetryCount int = 3
    
    // ❌ 不好的命名
    var u string = "张三"           // 太短,含义不明
    var userAgeInYears int = 25     // 太冗长
    var flag bool = true            // 含义模糊
    var MAX_RETRY_COUNT int = 3     // 不符合Go命名规范
    
    // ✅ 常量命名(使用驼峰命名)
    const MaxConnections = 100
    const DefaultTimeout = 30
    const APIVersion = "v1.0"
    
    // ✅ 包级别变量可以使用简短名称
    var (
        cfg    *Config   // 配置
        logger *Logger   // 日志器
        db     *Database // 数据库
    )
    
    fmt.Printf("用户: %s, 年龄: %d, 激活: %t\n", userName, userAge, isUserActive)
}

// 假设的类型定义
type Config struct{}
type Logger struct{}
type Database struct{}

2. 类型选择指南

go 复制代码
package main

import "fmt"

func main() {
    // ✅ 整数类型选择指南
    var counter int        // 一般计数器使用int
    var id int64          // ID通常使用int64
    var age uint8         // 年龄可以使用uint8(0-255)
    var fileSize int64    // 文件大小使用int64
    
    // ✅ 浮点数类型选择
    var price float64     // 金钱计算使用float64
    var ratio float32     // 比率可以使用float32
    
    // ✅ 字符串处理
    var name string       // 普通字符串
    var description string = `这是一个多行字符串
可以包含换行符
和其他特殊字符`
    
    // ✅ 布尔值使用
    var isReady bool      // 明确的布尔状态
    var hasError bool     // 错误标志
    
    fmt.Printf("计数器: %d, ID: %d, 年龄: %d\n", counter, id, age)
    fmt.Printf("价格: %.2f, 比率: %.2f\n", price, ratio)
    fmt.Printf("姓名: %s\n", name)
    fmt.Printf("描述: %s\n", description)
    fmt.Printf("就绪: %t, 有错误: %t\n", isReady, hasError)
}

3. 错误处理模式

go 复制代码
package main

import (
    "fmt"
    "strconv"
)

func main() {
    // ✅ 标准错误处理模式
    input := "123abc"
    if num, err := strconv.Atoi(input); err != nil {
        fmt.Printf("转换失败: %v\n", err)
    } else {
        fmt.Printf("转换成功: %d\n", num)
    }
    
    // ✅ 多返回值处理
    result, err := divide(10, 0)
    if err != nil {
        fmt.Printf("计算错误: %v\n", err)
        return
    }
    fmt.Printf("结果: %.2f\n", result)
    
    // ✅ 类型断言的安全处理
    var value interface{} = "hello"
    if str, ok := value.(string); ok {
        fmt.Printf("字符串值: %s\n", str)
    } else {
        fmt.Println("类型断言失败")
    }
}

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("除数不能为零")
    }
    return a / b, nil
}

4. 性能优化小贴士

go 复制代码
package main

import (
    "fmt"
    "strconv"
    "strings"
)

func main() {
    // ✅ 字符串拼接优化
    var parts []string
    for i := 0; i < 5; i++ {
        parts = append(parts, "part"+strconv.Itoa(i))
    }
    result := strings.Join(parts, ",")
    fmt.Printf("拼接结果: %s\n", result)
    
    // ❌ 低效的字符串拼接
    badResult := ""
    for i := 0; i < 5; i++ {
        badResult += "part" + strconv.Itoa(i) + ","
    }
    fmt.Printf("低效拼接: %s\n", badResult)
    
    // ✅ 预分配切片容量
    numbers := make([]int, 0, 100)  // 预分配容量为100
    for i := 0; i < 100; i++ {
        numbers = append(numbers, i)
    }
    
    // ✅ 使用常量而不是重复计算
    const Pi = 3.14159265359
    radius := 5.0
    area := Pi * radius * radius
    fmt.Printf("圆面积: %.2f\n", area)
}

总结

通过本文的学习,我们深入了解了Go语言的基础语法,包括:

核心知识点回顾

  1. 变量声明 :掌握了var关键字和短变量声明:=的使用方法
  2. 数据类型:熟悉了Go语言丰富的数据类型体系
  3. 常量和iota:学会了常量定义和iota枚举器的强大功能
  4. 类型转换:理解了显式类型转换和类型推断机制
  5. 作用域管理:掌握了变量的作用域和生命周期概念

实践要点

  • 类型安全:Go语言是强类型语言,类型转换必须显式进行
  • 零值初始化:未初始化的变量会被赋予类型的零值
  • 作用域规则:理解不同层级的作用域,避免变量遮蔽陷阱
  • 命名规范:遵循Go语言的命名约定,使用驼峰命名法
  • 错误处理:养成良好的错误处理习惯

性能考虑

  • 选择合适的数据类型以优化内存使用
  • 注意类型转换的性能开销
  • 合理使用常量减少重复计算
  • 理解栈和堆分配的区别

下一步学习

在下一篇文章中,我们将学习Go语言的控制结构,包括条件语句、循环语句和分支语句。这些控制结构将让我们能够编写更复杂的程序逻辑。

技术评估

  • 实用性: ⭐⭐⭐⭐⭐ (基础必备)
  • 学习曲线: ⭐⭐ (相对简单)
  • 性能表现: ⭐⭐⭐⭐⭐ (类型安全且高效)
  • 开发效率: ⭐⭐⭐⭐ (语法简洁)
  • 未来发展: ⭐⭐⭐⭐⭐ (Go语言核心基础)

欢迎关注我的技术博客,一起交流Go语言学习心得!在后续文章中,我们将继续深入学习Go语言的高级特性,包括函数、结构体、接口、并发编程等内容。如果你有任何问题或建议,欢迎在评论区留言讨论!

© 版权所有 | Go语言从入门到精通系列文章 本文为原创内容,未经作者明确授权,禁止任何形式的转载、复制或内容搬运。违者将依法追究法律责任。如需转载,请联系作者获得书面许可。

相关推荐
liulanba6 分钟前
NAT 和 PNAT
开发语言·php
stone519523 分钟前
TOTP算法与HOTP算法
c语言·物联网·算法·嵌入式·iot平台·智能门锁
PineappleCoder23 分钟前
👶 小孩报数问题:当熊孩子遇上“约瑟夫环
前端·算法
hqwest1 小时前
C#WPF实战出真汁01--项目介绍
开发语言·c#·wpf
xnglan1 小时前
蓝桥杯手算题和杂题简易做法
数据结构·数据库·c++·python·算法·职场和发展·蓝桥杯
凛冬君主2 小时前
插入排序专栏
java·算法·排序算法
姓刘的哦2 小时前
Win10上Qt使用Libcurl库
开发语言·qt
檀越剑指大厂2 小时前
【开发语言】Groovy语言:Java生态中的动态力量
java·开发语言
stbomei2 小时前
C 语言判断一个数是否是素数的三种方法文章提纲
c语言·开发语言·算法
小牛壮士2 小时前
Tokenizer(切词器)的不同实现算法
开发语言·算法·c#