Go 语言基础:变量与常量

Go 语言基础:变量与常量

📋 目录

  • [Go 语言基础:变量与常量](#Go 语言基础:变量与常量)
    • [📋 目录](#📋 目录)
    • [🔑 变量](#🔑 变量)
      • [📖 前言](#📖 前言)
      • [📝 变量定义方法](#📝 变量定义方法)
        • [1. var 定义](#1. var 定义)
        • [2. 一次定义多个变量](#2. 一次定义多个变量)
        • [3. 类型推导式](#3. 类型推导式)
        • [4. 短变量声明法](#4. 短变量声明法)
        • [5. 匿名变量](#5. 匿名变量)
      • [🔢 变量的初始化](#🔢 变量的初始化)
    • [📄 fmt 包](#📄 fmt 包)
      • [📖 前言](#📖 前言)
      • [🖨️ Print 和 Println 的区别](#🖨️ Print 和 Println 的区别)
      • [📋 Println 和 Printf 的区别](#📋 Println 和 Printf 的区别)
      • [🎯 常用占位符](#🎯 常用占位符)
    • [📌 常量](#📌 常量)
      • [📖 基本定义](#📖 基本定义)
      • [🔢 const 结合 iota 的使用](#🔢 const 结合 iota 的使用)
        • [iota 基本概念](#iota 基本概念)
        • [iota 高级用法](#iota 高级用法)
    • [📏 命名规则](#📏 命名规则)
    • [💡 最佳实践](#💡 最佳实践)

🔑 变量

📖 前言

在程序运行过程中,数据都保存在内存中。当我们想要在代码中操作某个数据时,需要在内存中找到这个变量。如果直接通过内存地址操作变量,代码的可读性会很差且容易出错。因此,我们使用变量来保存数据的内存地址,通过变量名就能找到内存中对应的数据。

📝 变量定义方法

1. var 定义

基本语法:

go 复制代码
var 变量名 类型 = 表达式

示例:

go 复制代码
package main

import "fmt"

func main() {
    var name string = "zhangsan"
    var age int = 25
    var height float64 = 175.5
    
    fmt.Printf("姓名: %s, 年龄: %d, 身高: %.1f\n", name, age, height)
}
2. 一次定义多个变量

① 默认统一类型

go 复制代码
package main

import "fmt"

func main() {
    // var 变量名,变量名 类型
    
    // 没有赋值,输出为空值
    var username, sex string
    fmt.Printf("username=%s, sex=%s\n", username, sex)
    
    // 赋值后输出
    username = "张三"
    sex = "男"
    fmt.Printf("username=%s, sex=%s\n", username, sex)
}

输出:

复制代码
username=, sex=
username=张三, sex=男

② 分别指定类型

go 复制代码
package main

import "fmt"

func main() {
    var (
        name string = "张三"
        sex  string = "男"
        age  int    = 15
    )
    fmt.Printf("name=%s, sex=%s, age=%d\n", name, sex, age)
}

输出:

复制代码
name=张三, sex=男, age=15
3. 类型推导式

Go 语言可以根据赋值自动推导变量类型:

go 复制代码
package main

import "fmt"

func main() {
    var name = "张三"    // 自动推导为 string
    var age = 25        // 自动推导为 int
    var score = 95.5    // 自动推导为 float64
    var isStudent = true // 自动推导为 bool
    
    fmt.Printf("%T: %v\n", name, name)
    fmt.Printf("%T: %v\n", age, age)
    fmt.Printf("%T: %v\n", score, score)
    fmt.Printf("%T: %v\n", isStudent, isStudent)
}
4. 短变量声明法

函数内部 ,可以使用更简略的 := 方式声明并初始化变量。

语法:

go 复制代码
变量名 := 表达式

特点:

  • ✅ 只能用于声明局部变量
  • ❌ 不能用于全局变量的声明
  • ⚡ 更加简洁高效

示例:

go 复制代码
package main

import "fmt"

// a := 100  // ❌ 非法操作,不能在函数外使用

func main() {
    // ✅ 合法使用
    name := "张三"
    age := 25
    name, sex := "李四", "女"  // 多重赋值
    
    fmt.Printf("name=%s, age=%d, sex=%s\n", name, age, sex)
}
5. 匿名变量

在使用多重赋值时,如果想要忽略某个值,可以使用匿名变量 。匿名变量用下划线 _ 表示。

特点:

  • 🚫 不占用命名空间
  • 💾 不分配内存
  • 🔄 匿名变量之间不存在重复声明
  • 🎯 多用于占位,表示忽略值

示例:

go 复制代码
package main

import "fmt"

func GetInformation() (string, int) {
    return "李四", 23
}

func main() {
    // 获取所有返回值
    name, age := GetInformation()
    fmt.Printf("name=%s, age=%d\n", name, age)
    
    // 只要姓名,忽略年龄
    name, _ = GetInformation()
    fmt.Printf("name=%s\n", name)
    
    // 只要年龄,忽略姓名
    _, age = GetInformation()
    fmt.Printf("age=%d\n", age)
}

输出:

复制代码
name=李四, age=23
name=李四
age=23

🔢 变量的初始化

Go 语言在声明变量时,会自动对变量对应的内存区域进行初始化操作。每个变量会被初始化成其类型的默认值(零值)

数据类型 默认值
整型(int, int8, int16, int32, int64) 0
无符号整型(uint, uint8, uint16, uint32, uint64) 0
浮点型(float32, float64) 0.0
字符串(string) "" (空字符串)
布尔型(bool) false
切片(slice) nil
映射(map) nil
通道(chan) nil
函数(func) nil
指针(pointer) nil
接口(interface) nil

示例:

go 复制代码
package main

import "fmt"

func main() {
    var a int
    var b float64
    var c string
    var d bool
    var e []int
    
    fmt.Printf("int 默认值: %d\n", a)
    fmt.Printf("float64 默认值: %f\n", b)
    fmt.Printf("string 默认值: '%s'\n", c)
    fmt.Printf("bool 默认值: %t\n", d)
    fmt.Printf("slice 默认值: %v\n", e)
}

📄 fmt 包

📖 前言

Go 中要打印一个值需要引入 fmt 包。fmt 包提供了一些常见的打印数据的方法,如:PrintPrintlnPrintf。在实际开发中,后两个使用得非常多。

go 复制代码
import "fmt"

🖨️ Print 和 Println 的区别

主要区别:

  1. 间隔Println 在多个值之间有空格,Print 没有
  2. 换行Println 会自动换行,Print 不会

示例:

go 复制代码
package main

import "fmt"

func main() {
    fmt.Println("go", "python", "java")     // 有空格,自动换行
    fmt.Print("go", "python", "java")       // 无空格,不换行
    fmt.Print("Print不会换行")               // 继续在同一行
    fmt.Println("这里换行了")                // 换行
}

输出:

复制代码
go python java
gopythonjavaprint不会换行这里换行了

📋 Println 和 Printf 的区别

Printf格式化输出 ,在很多场景下比 Println 更方便和灵活。

示例:

go 复制代码
package main

import "fmt"

func main() {
    A := 10
    B := 20
    C := 30
    
    // Println 方式
    fmt.Println("A=", A, "B=", B, "C=", C)
    
    // Printf 方式(格式化输出)
    fmt.Printf("A=%d, B=%d, C=%d\n", A, B, C)
}

输出:

复制代码
A= 10 B= 20 C= 30
A=10, B=20, C=30

🎯 常用占位符

占位符 说明 示例
%d 十进制整数 fmt.Printf("%d", 42)42
%o 八进制整数 fmt.Printf("%o", 42)52
%x 十六进制整数(小写) fmt.Printf("%x", 42)2a
%X 十六进制整数(大写) fmt.Printf("%X", 42)2A
%f 浮点数 fmt.Printf("%f", 3.14)3.140000
%.2f 保留2位小数 fmt.Printf("%.2f", 3.14159)3.14
%s 字符串 fmt.Printf("%s", "hello")hello
%c 字符 fmt.Printf("%c", 65)A
%t 布尔值 fmt.Printf("%t", true)true
%v 默认格式 fmt.Printf("%v", 42)42
%T 类型 fmt.Printf("%T", 42)int
%p 指针地址 fmt.Printf("%p", &a)0xc000...
%% 百分号本身 fmt.Printf("100%%")100%

📌 常量

📖 基本定义

相对于变量,常量 是恒定不变的值,多用于定义程序运行期间不会改变的那些值。常量的声明和变量声明非常类似,只是把 var 换成了 const常量在定义的时候必须赋值

基本语法:

go 复制代码
const 常量名 类型 = 值

示例:

go 复制代码
package main

import "fmt"

func main() {
    const PI float64 = 3.14159
    const AppName string = "Go学习系统"
    const MaxUsers = 1000  // 类型推导
    
    fmt.Printf("圆周率: %f\n", PI)
    fmt.Printf("应用名称: %s\n", AppName)
    fmt.Printf("最大用户数: %d\n", MaxUsers)
}

批量定义:

go 复制代码
package main

import "fmt"

func main() {
    const (
        a = 2.5
        b = 3.6
        c       // 省略值,表示和上面一行的值相同
    )
    
    const (
        A = 3
        B       // 值为 3
        C       // 值为 3
    )
    
    fmt.Printf("a=%f\tb=%f\tc=%f\n", a, b, c)
    fmt.Printf("A=%d\tB=%d\tC=%d\n", A, B, C)
}

输出:

复制代码
a=2.500000      b=3.600000      c=3.600000
A=3     B=3     C=3

🔢 const 结合 iota 的使用

iota 基本概念
  • iota 是 Go 语言的常量计数器,只能在常量的表达式中使用
  • iotaconst 关键字出现时将被重置为 0
  • const 中每新增一行常量声明将使 iota 计数一次(可理解为 const 语句块中的行索引)

基本示例:

go 复制代码
package main

import "fmt"

func main() {
    const (
        Sunday = iota    // 0
        Monday           // 1
        Tuesday          // 2
        Wednesday        // 3
        Thursday         // 4
        Friday           // 5
        Saturday         // 6
    )
    
    fmt.Printf("Sunday: %d\n", Sunday)
    fmt.Printf("Monday: %d\n", Monday)
    fmt.Printf("Saturday: %d\n", Saturday)
}
iota 高级用法

① 跳过某些值和中间插队:

go 复制代码
package main

import "fmt"

func main() {
    const (
        a = iota    // 0
        b = 1       // 1 (中间插队)
        c           // 1 (继承上一行的值)
        d = 1       // 1 (再次赋值)
        e = iota    // 4 (恢复 iota,当前行索引为 4)
        _           // 5 (跳过)
        f           // 6 (继续计数)
    )
    
    fmt.Printf("a=%d\tb=%d\tc=%d\td=%d\te=%d\tf=%d\n", a, b, c, d, e, f)
}

输出:

复制代码
a=0     b=1     c=1     d=1     e=4     f=6

② 实际应用示例:

go 复制代码
package main

import "fmt"

func main() {
    // 文件权限
    const (
        Read = 1 << iota    // 1 << 0 = 1
        Write               // 1 << 1 = 2  
        Execute             // 1 << 2 = 4
    )
    
    // 网络协议端口
    const (
        HTTP = iota + 80    // 0 + 80 = 80
        HTTPS               // 1 + 80 = 81
        FTP                 // 2 + 80 = 82
    )
    
    fmt.Printf("权限 - Read: %d, Write: %d, Execute: %d\n", Read, Write, Execute)
    fmt.Printf("端口 - HTTP: %d, HTTPS: %d, FTP: %d\n", HTTP, HTTPS, FTP)
}

输出:

复制代码
权限 - Read: 1, Write: 2, Execute: 4
端口 - HTTP: 80, HTTPS: 81, FTP: 82

📏 命名规则

🔤 标识符命名规则

  1. 组成元素:变量名必须由数字、字母、下划线组成
  2. 开头限制:标识符开头不能是数字
  3. 关键字限制:标识符不能是保留字和关键字
  4. 大小写敏感:变量的名字是区分大小写的
  5. 见名知意:变量名称建议用名词,方法名称建议用动词

✅ 合法的标识符

go 复制代码
var name string        // ✅
var user_name string   // ✅
var userName string    // ✅
var age18 int         // ✅
var _temp float64     // ✅
var π float64         // ✅ 支持 Unicode 字符

❌ 不合法的标识符

go 复制代码
var 2name string      // ❌ 不能以数字开头
var user-name string  // ❌ 不能包含 -
var class string      // ❌ class 是关键字
var func string       // ❌ func 是关键字

📚 Go 语言关键字(25个)

复制代码
break    default     func    interface  select
case     defer       go      map        struct  
chan     else        goto    package    switch
const    fallthrough if      range      type
continue for         import  return     var

🎯 命名约定

① 驼峰命名法:

go 复制代码
// 小驼峰(私有)
var userName string
var maxCount int

// 大驼峰(公有,可导出)
var UserName string
var MaxCount int

② 常见命名模式:

go 复制代码
// 常量:全大写,下划线分隔
const MAX_USER_COUNT = 1000
const API_VERSION = "v1.0"

// 包级常量:大驼峰
const DefaultTimeout = 30

// 布尔变量:is/has/can 前缀
var isReady bool
var hasPermission bool
var canAccess bool

// 计数器:count/num 后缀
var userCount int
var pageNum int

💡 最佳实践

🎯 变量使用建议

  1. 就近声明:在变量使用的地方附近声明
  2. 零值可用:利用 Go 的零值特性,减少不必要的初始化
  3. 短变量声明 :在函数内部优先使用 :=
  4. 批量声明:相关变量可以批量声明

🔒 常量使用建议

  1. 配置参数:将不变的配置定义为常量
  2. 魔法数字:避免在代码中直接写数字,用常量替代
  3. 枚举值 :使用 iota 定义枚举类型

📝 代码示例:综合应用

go 复制代码
package main

import "fmt"

// 全局常量
const (
    AppName    = "Go学习系统"
    AppVersion = "1.0.0"
)

// 状态枚举
const (
    StatusPending = iota    // 0
    StatusRunning           // 1
    StatusCompleted         // 2
    StatusFailed            // 3
)

func main() {
    // 短变量声明
    userName := "张三"
    userAge := 25
    
    // 批量变量声明
    var (
        score       float64 = 95.5
        isVIP       bool    = true
        subjects            = []string{"数学", "语文", "英语"}
    )
    
    // 匿名变量的使用
    info, _ := getUserInfo(userName)
    
    // 格式化输出
    fmt.Printf("=== %s %s ===\n", AppName, AppVersion)
    fmt.Printf("用户信息: %s\n", info)
    fmt.Printf("姓名: %s, 年龄: %d, 分数: %.1f\n", userName, userAge, score)
    fmt.Printf("VIP用户: %t\n", isVIP)
    fmt.Printf("学习科目: %v\n", subjects)
    fmt.Printf("当前状态: %d\n", StatusRunning)
}

func getUserInfo(name string) (string, error) {
    return fmt.Sprintf("用户 %s 的详细信息", name), nil
}

🎉 恭喜!您已掌握 Go 语言变量和常量的核心概念,继续加油学习!

相关推荐
NiKo_W2 小时前
Linux 文件系统与基础指令
linux·开发语言·指令
工程师小星星2 小时前
Golang语言的文件组织方式
开发语言·后端·golang
乂爻yiyao2 小时前
java 代理模式实现
java·开发语言·代理模式
张子夜 iiii3 小时前
实战项目-----Python+OpenCV 实现对视频的椒盐噪声注入与实时平滑还原”
开发语言·python·opencv·计算机视觉
2301_770373733 小时前
Java集合
java·开发语言
哈喽姥爷3 小时前
Spring Boot---自动配置原理和自定义Starter
java·spring boot·后端·自定义starter·自动配置原理
啊?啊?3 小时前
18 从对象内存到函数调用:C++ 虚函数表原理(继承覆盖 / 动态绑定)+ 多态实战
开发语言·c++·多态原理
bkspiderx3 小时前
C++标准库:文件流类
开发语言·c++
阿拉斯加大闸蟹4 小时前
基于RDMA 通信的可负载均衡高性能服务架构
运维·架构·负载均衡