当前位置: 首页 > ops >正文

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

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

目录

  • 前言
  • 变量声明的多种方式
  • Go语言基本数据类型详解
  • 常量定义和iota的使用
  • 类型转换和类型推断
  • 作用域和生命周期
  • 实战案例:构建一个简单的用户信息管理程序
  • 最佳实践与小贴士
  • 总结

前言

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

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

变量声明的多种方式

1. 使用var关键字声明

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

package mainimport "fmt"func main() {// 方式1:声明并初始化var name string = "张三"var age int = 25var height float64 = 175.5// 方式2:先声明,后赋值var email stringemail = "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语言最具特色的是短变量声明操作符:=,它让代码更加简洁:

package mainimport "fmt"func main() {// 短变量声明,只能在函数内使用name := "李四"age := 30salary := 8500.50married := 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语言中,未初始化的变量会被赋予对应类型的零值:

package mainimport "fmt"func main() {var (intVar    int     // 0floatVar  float64 // 0.0boolVar   bool    // falsestringVar 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("字符串变量为空")}// 判断指针是否为nilif pointerVar == nil {fmt.Println("指针变量为nil")}
}

Go语言基本数据类型详解

1. 数值类型

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

package mainimport ("fmt""unsafe"
)func main() {// 整数类型var int8Var int8 = 127        // -128 到 127var int16Var int16 = 32767    // -32768 到 32767var int32Var int32 = 2147483647var int64Var int64 = 9223372036854775807// 无符号整数类型var uint8Var uint8 = 255      // 0 到 255var uint16Var uint16 = 65535  // 0 到 65535var uint32Var uint32 = 4294967295var uint64Var uint64 = 18446744073709551615// 浮点数类型var float32Var float32 = 3.14159var float64Var float64 = 3.141592653589793// 复数类型var complex64Var complex64 = 1 + 2ivar 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. 字符串和字符类型

package mainimport ("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. 布尔类型

package mainimport "fmt"func main() {// 布尔类型只有两个值:true和falsevar isActive bool = truevar isComplete bool = falsevar 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 := 18if age >= 18 {fmt.Println("已成年")} else {fmt.Println("未成年")}// 复杂条件score := 85if score >= 90 {fmt.Println("优秀")} else if score >= 80 {fmt.Println("良好")} else if score >= 60 {fmt.Println("及格")} else {fmt.Println("不及格")}
}

常量定义和iota的使用

1. 常量的基本使用

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

2. iota枚举器的强大功能

package mainimport "fmt"func main() {// 基本iota使用const (Monday    = iota  // 0Tuesday   = iota  // 1Wednesday = iota  // 2Thursday  = iota  // 3Friday    = iota  // 4Saturday  = iota  // 5Sunday    = iota  // 6)// 简化写法const (January = iota + 1  // 1February            // 2March               // 3April               // 4May                 // 5June                // 6July                // 7August              // 8September           // 9October             // 10November            // 11December            // 12)// 跳过某些值const (_ = iota  // 跳过0KB = 1 << (10 * iota)  // 1024MB                     // 1048576GB                     // 1073741824TB                     // 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 | ExecutePermissionfmt.Printf("读权限: %d, 写权限: %d, 执行权限: %d\n", ReadPermission, WritePermission, ExecutePermission)fmt.Printf("完整权限: %d (二进制: %b)\n", fullPermission, fullPermission)
}

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

package mainimport "fmt"// HTTP状态码
const (StatusContinue           = 100StatusSwitchingProtocols = 101StatusOK                 = 200StatusCreated            = 201StatusAccepted           = 202StatusNoContent          = 204StatusMovedPermanently   = 301StatusFound              = 302StatusBadRequest         = 400StatusUnauthorized       = 401StatusForbidden          = 403StatusNotFound           = 404StatusInternalServerError = 500StatusBadGateway         = 502StatusServiceUnavailable = 503
)// 用户状态
const (UserStatusInactive = iotaUserStatusActiveUserStatusSuspendedUserStatusDeleted
)// 订单状态
const (OrderStatusPending = iota + 1  // 从1开始OrderStatusPaidOrderStatusShippedOrderStatusDeliveredOrderStatusCancelled
)func main() {// 模拟用户状态管理userStatus := UserStatusActiveswitch userStatus {case UserStatusInactive:fmt.Println("用户未激活")case UserStatusActive:fmt.Println("用户已激活")case UserStatusSuspended:fmt.Println("用户已暂停")case UserStatusDeleted:fmt.Println("用户已删除")default:fmt.Println("未知状态")}// 模拟HTTP响应处理responseCode := StatusNotFoundif responseCode >= 200 && responseCode < 300 {fmt.Println("请求成功")} else if responseCode >= 400 && responseCode < 500 {fmt.Println("客户端错误")} else if responseCode >= 500 {fmt.Println("服务器错误")}// 订单状态流转orderStatus := OrderStatusPendingfmt.Printf("当前订单状态: %d\n", orderStatus)// 状态升级orderStatus = OrderStatusPaidfmt.Printf("订单已支付,状态: %d\n", orderStatus)
}

类型转换和类型推断

1. 显式类型转换

package mainimport ("fmt""strconv"
)func main() {// 数值类型间的转换var intVal int = 42var 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 = 1000000var 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 = valfmt.Printf("字符串'%s'转换为数字: %d\n", numStr, strNum)}// 数字转字符串var num int = 456var 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. 类型推断的智能性

package mainimport "fmt"func main() {// 基本类型推断var a = 42        // intvar b = 3.14      // float64var c = "hello"   // stringvar d = true      // boolvar 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 := 10y := 20sum := x + y      // intavg := float64(sum) / 2  // float64fmt.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       // complex128complex2 := complex64(1 + 2i)  // complex64fmt.Printf("complex1的类型: %T\n", complex1)fmt.Printf("complex2的类型: %T\n", complex2)
}func calculateArea(length, width float64) float64 {return length * width
}

3. 类型断言和接口转换

package mainimport "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. 不同作用域的变量

package mainimport "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. 变量的生命周期

package mainimport ("fmt""runtime"
)// 全局变量在程序启动时创建,程序结束时销毁
var globalCounter int = 0func 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 := 42fmt.Printf("栈变量地址: %p, 值: %d\n", &stackVar, stackVar)// 堆分配的变量(通过new创建)heapVar := new(int)*heapVar = 100fmt.Printf("堆变量地址: %p, 值: %d\n", heapVar, *heapVar)// 切片会在堆上分配slice := make([]int, 1000)slice[0] = 999fmt.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)

package mainimport "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变量,遮蔽了外层的errif data, err := getData(); err != nil {fmt.Printf("内层err: %v\n", err)}// 外层的err仍然是nilfmt.Printf("外层err: %v\n", err)// 正确的做法var data stringdata, 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("模拟错误")
}

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

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

package mainimport ("fmt""strconv""strings""time"
)// 用户状态常量
const (UserStatusInactive = iotaUserStatusActiveUserStatusSuspendedUserStatusDeleted
)// 用户类型常量
const (UserTypeRegular = iota + 1UserTypeVIPUserTypeAdmin
)// 权限常量(使用位运算)
const (PermissionRead = 1 << iotaPermissionWritePermissionDeletePermissionAdmin
)// 用户信息结构体(我们将在后续文章详细介绍结构体)
type User struct {ID          intUsername    stringEmail       stringAge         intBalance     float64IsActive    boolUserType    intPermissions intCreatedAt   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 []stringif 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 := UserStatusActivefmt.Printf("当前用户状态: %s\n", getStatusName(currentStatus))// 状态转换currentStatus = UserStatusSuspendedfmt.Printf("用户已被暂停: %s\n", getStatusName(currentStatus))currentStatus = UserStatusActivefmt.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 := PermissionReadfmt.Printf("初始权限: %s\n", getPermissionNames(userPerms))// 添加写权限userPerms |= PermissionWritefmt.Printf("添加写权限后: %s\n", getPermissionNames(userPerms))// 添加删除权限userPerms |= PermissionDeletefmt.Printf("添加删除权限后: %s\n", getPermissionNames(userPerms))// 检查是否有特定权限if userPerms&PermissionWrite != 0 {fmt.Println("用户有写权限")}// 移除写权限userPerms &^= PermissionWritefmt.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 := 12345userIDStr := strconv.Itoa(userID)fmt.Printf("用户ID %d 转换为字符串: '%s'\n", userID, userIDStr)// 格式化输出price := 99.99priceStr := fmt.Sprintf("%.2f", price)fmt.Printf("价格 %.2f 格式化为字符串: '%s'\n", price, priceStr)
}

最佳实践与小贴士

1. 变量命名最佳实践

package mainimport "fmt"func main() {// ✅ 好的命名var userName string = "张三"var userAge int = 25var isUserActive bool = truevar maxRetryCount int = 3// ❌ 不好的命名var u string = "张三"           // 太短,含义不明var userAgeInYears int = 25     // 太冗长var flag bool = true            // 含义模糊var MAX_RETRY_COUNT int = 3     // 不符合Go命名规范// ✅ 常量命名(使用驼峰命名)const MaxConnections = 100const DefaultTimeout = 30const 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. 类型选择指南

package mainimport "fmt"func main() {// ✅ 整数类型选择指南var counter int        // 一般计数器使用intvar id int64          // ID通常使用int64var age uint8         // 年龄可以使用uint8(0-255)var fileSize int64    // 文件大小使用int64// ✅ 浮点数类型选择var price float64     // 金钱计算使用float64var 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. 错误处理模式

package mainimport ("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. 性能优化小贴士

package mainimport ("fmt""strconv""strings"
)func main() {// ✅ 字符串拼接优化var parts []stringfor 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)  // 预分配容量为100for i := 0; i < 100; i++ {numbers = append(numbers, i)}// ✅ 使用常量而不是重复计算const Pi = 3.14159265359radius := 5.0area := Pi * radius * radiusfmt.Printf("圆面积: %.2f\n", area)
}

总结

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

核心知识点回顾

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

实践要点

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

性能考虑

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

下一步学习

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

技术评估

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

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

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

http://www.xdnf.cn/news/17788.html

相关文章:

  • Android项目中Ktor的引入与使用实践
  • 在 Linux 服务器搭建Coturn即ICE/TURN/STUN实现P2P(点对点)直连
  • 图论Day3学习心得
  • 无脑整合springboot2.7+nacos2.2.3+dubbo3.2.9实现远程调用及配置中心
  • 计算机网络 THU 考研专栏简介
  • L2 级别自动驾驶 硬件架构设计
  • LeetCode 922.按奇偶排序数组2
  • ElasticSearch不同环境同步索引数据
  • Spring Ai 如何配置以及如何搭建
  • Jmeter自定义脚本
  • 零基础学会制作 基于STM32单片机智能加湿系统/加湿监测/蓝牙系统/监测水量
  • 探索无人机图传技术:创新视野与无限可能
  • 在 macOS 上顺利安装 lapsolver
  • OpenCV Python——VSCode编写第一个OpenCV-Python程序 ,图像读取及翻转cv2.flip(上下、左右、上下左右一起翻转)
  • 死锁总结及解决方案
  • 关于截屏时实现游戏暂停以及本地和上线不同步问题
  • 用GPT解释“GPT-5”是什么,有什么优势
  • python-pycharm切换python各种版本的环境与安装python各种版本的环境(pypi轮子下载)
  • Flink Stream API 源码走读 - map 和 flatMap
  • KNN(k近邻算法)
  • Chrome插件开发实战:从架构到发布全流程
  • 准备用Qt6 重写音视频会议系统服务端
  • 开源 Arkts 鸿蒙应用 开发(十五)自定义绘图控件--仪表盘
  • 开源 Arkts 鸿蒙应用 开发(十六)自定义绘图控件--波形图
  • 【Javaweb学习|黑马笔记|Day1】初识,入门网页,HTML-CSS|常见的标签和样式|标题排版和样式、正文排版和样式
  • 前端css学习笔记6:盒子模型
  • 国内著名AI搜索优化专家孟庆涛发表《AI搜索内容可信度评估综合指南》
  • liteflow
  • Vue3中的ref与reactive全面解析:如何正确选择响应式声明方式
  • Java List 集合详解(ArrayList、LinkedList、Vector)