• Go 语言入门学习笔记基础版


    Go 语言入门学习笔记基础版

    文档说明

    本文档整合阶段性全部学习内容,包含基础语法、输入输出、流程控制、数组/切片、函数、Map、结构体、方法、指针等核心知识点,搭配代码示例、场景说明、易错提醒与实战练习,适合系统复习与查阅。


    1. 程序基础结构

    1.1 标准可执行程序模板

    所有 Go 可执行文件固定格式:

    package main
    
    import "fmt"
    
    func main() {
        // 业务代码写在这里
    }
    
    • package main:声明为主包,代表当前文件是可执行程序,而非库文件
    • import "fmt":导入标准输入输出包,用于打印、读取控制台内容
    • func main():程序入口函数,程序运行时自动执行,无参数、无返回值

    2. 输入与输出

    2.1 三类标准打印函数(fmt 包)

    函数 是否自动换行 参数间自动加空格 支持格式化占位符 适用场景
    fmt.Print() 连续拼接简单内容
    fmt.Println() 日常常规打印(使用最多)
    fmt.Printf() 格式化输出、变量拼接

    常用格式化占位符

    • %d:十进制整数
    • %s:字符串
    • %f:浮点数;%.2f 表示保留 2 位小数
    • %v:通用占位符,可打印任意数据类型

    示例代码

    package main
    
    import "fmt"
    
    func main() {
        name := "张三"
        age := 20
        fmt.Printf("姓名:%s,年龄:%d\n", name, age)
    }
    

    2.2 内置原生打印函数

    print() / println()

    • 无需导入 fmt 包,Go 语言内置
    • 功能简单,仅用于临时调试
    • 正式项目、生产环境禁止使用
    println("临时调试信息")
    

    2.3 控制台输入 fmt.Scan

    作用:接收用户在控制台输入的数据。

    基础语法

    var 变量名 数据类型
    fmt.Scan(&变量名)
    

    核心规则

    • 必须添加 &(取地址符),否则编译报错
    • 支持一次性读取多个值,输入时用空格 / 回车分隔

    示例

    package main
    
    import "fmt"
    
    func main() {
        var num int
        fmt.Print("请输入一个数字:")
        fmt.Scan(&num)
        fmt.Println("你输入的数字:", num)
    
        // 一次性读取多个值
        var a, b int
        fmt.Scan(&a, &b)
        fmt.Println(a, b)
    }
    

    3. 变量基础

    3.1 变量定义与初始化

    完整写法

    var 变量名 数据类型
    var name string
    var num int
    

    定义并赋值

    var age int = 18
    

    类型推导(简写,推荐)

    无需手动声明类型,编译器自动推断。

    sex := "男"
    

    3.2 变量使用规则

    • 定义后的变量必须使用,否则编译报错
    • 变量名区分大小写
    • 同一代码块内,变量名不能重复定义

    4. 条件判断

    4.1 if / else 分支判断

    基础单分支

    if 条件表达式 {
        // 条件成立执行代码
    }
    

    双分支 if-else

    if 条件表达式 {
        // 条件成立
    } else {
        // 条件不成立
    }
    

    多分支 else if

    if score >= 90 {
        fmt.Println("优秀")
    } else if score >= 60 {
        fmt.Println("及格")
    } else {
        fmt.Println("不及格")
    }
    

    实战示例:判断奇偶数

    package main
    
    import "fmt"
    
    func main() {
        var num int
        fmt.Scan(&num)
        if num%2 == 0 {
            fmt.Println("偶数")
        } else {
            fmt.Println("奇数")
        }
    }
    

    4.2 switch 分支语句

    Go 语言 switch 默认自带 break,匹配成功后自动终止,无需手动添加。

    写法 1:带表达式(等值匹配)

    switch 变量/表达式 {
    case1:
        逻辑代码
    case2:
        逻辑代码
    default:
        // 所有case都不匹配时执行
    }
    

    示例:简易菜单选择

    package main
    
    import "fmt"
    
    func main() {
        var op int
        fmt.Println("1.加法  2.减法")
        fmt.Scan(&op)
    
        switch op {
        case 1:
            fmt.Println("执行加法运算")
        case 2:
            fmt.Println("执行减法运算")
        default:
            fmt.Println("输入选项错误")
        }
    }
    

    写法 2:无表达式(替代多 if 判断)

    score := 85
    switch {
    case score >= 90:
        fmt.Println("优秀")
    case score >= 60:
        fmt.Println("及格")
    default:
        fmt.Println("不及格")
    }
    

    补充规则

    • 一个 case 可匹配多个值:case 1,2,3:
    • default 可选,建议写在所有 case 最后

    5. 循环结构(Go 仅支持 for)

    Go 语言没有 while、do-while,所有循环统一使用 for 实现。

    5.1 四种常用 for 写法

    写法 1:标准三段式(计数循环,最常用)

    for 初始化语句; 循环条件; 后置语句 {
        循环体
    }
    

    示例:打印 1 ~ 10

    for i := 1; i <= 10; i++ {
        fmt.Println(i)
    }
    

    写法 2:仅保留条件(等效 while 循环)

    i := 1
    for i <= 10 {
        fmt.Println(i)
        i++
    }
    

    写法 3:死循环

    for {
        // 无限循环,必须配合 break 退出
    }
    

    写法 4:for range 遍历(数组 / 切片 / Map 专用)

    for 索引, 值 := range 容器 {
    
    }
    

    5.2 匿名变量 _

    遍历场景中,不需要使用索引时,用 _ 占位,避免「定义变量未使用」编译报错。

    nums := []int{1, 2, 3, 4}
    for _, v := range nums {
        fmt.Println(v)
    }
    

    5.3 循环控制关键字

    break

    跳出当前所在循环,直接终止循环执行。

    for i := 1; i <= 10; i++ {
        if i == 5 {
            break
        }
        fmt.Println(i)
    }
    

    continue

    跳过本次循环剩余代码,直接进入下一次循环。

    for i := 1; i <= 10; i++ {
        if i == 5 {
            continue
        }
        fmt.Println(i)
    }
    

    5.4 双层嵌套循环

    • 外层循环:控制行数
    • 内层循环:控制每行内容

    示例 1:打印直角三角形

    for i := 1; i <= 5; i++ {
        for j := 1; j <= i; j++ {
            fmt.Print("* ")
        }
        fmt.Println()
    }
    

    示例 2:九九乘法表

    for i := 1; i <= 9; i++ {
        for j := 1; j <= i; j++ {
            fmt.Printf("%d*%d=%d\t", j, i, i*j)
        }
        fmt.Println()
    }
    

    6. 数组与切片

    6.1 数组(长度固定)

    定义语法

    var 数组名 [长度]数据类型
    var arr [3]int
    

    多种初始化方式

    // 1. 先定义,后赋值
    var a [3]int
    a[0] = 10
    a[1] = 20
    
    // 2. 定义同时赋值
    var b [3]int = [3]int{1, 2, 3}
    
    // 3. 自动推导长度 ...(仅定义+初始化时可用)
    c := [...]int{4, 5, 6}
    

    数组核心特点

    • 长度在编译阶段确定,定义后无法修改
    • 元素下标从 0 开始
    • 属于值类型,赋值、函数传参时会完整拷贝数据

    易错点var arr [...]int 单独声明数组写法非法,编译器无法推断长度。

    6.2 切片 Slice(动态数组,开发首选)

    切片基于数组实现,长度可变,实际开发优先使用切片。

    定义与初始化

    // 1. 声明空切片
    var s1 []int
    
    // 2. 直接初始化元素
    s2 := []int{1, 3, 5, 7}
    
    // 3. make 创建切片(参数:长度, 容量)
    s3 := make([]int, 2, 5)
    

    核心操作:append 追加元素

    空切片不能直接通过下标赋值,必须使用 append 动态追加元素:

    var s []int
    s = append(s, 10)
    s = append(s, 20, 30)
    fmt.Println(s)
    

    切片截取

    语法:切片[起始下标:结束下标],含左不含右

    s := []int{10, 20, 30, 40}
    part := s[1:3]
    fmt.Println(part) // 输出 [20 30]
    

    切片易错写法

    var s []int
    s[0] = 10 // 运行报错:下标越界,空切片长度为0
    

    7. 函数

    7.1 基础函数

    语法格式

    func 函数名(参数列表) 返回值类型 {
        函数体
        return 返回值
    }
    

    示例:两数求和

    func add(a int, b int) int {
        return a + b
    }
    

    7.2 多返回值(Go 语言特色)

    一个函数可以同时返回多个结果。

    // 返回两数之和、两数之差
    func calc(a, b int) (int, int) {
        return a + b, a - b
    }
    
    func main() {
        sum, sub := calc(10, 4)
        fmt.Println(sum, sub)
    
        // 匿名变量 _ 忽略不需要的返回值
        _, sub2 := calc(20, 7)
        fmt.Println(sub2)
    }
    

    7.3 可变参数

    格式:参数名 ...数据类型,支持传入任意个数同类型参数,函数内部按切片处理。

    // 对任意个整数求和
    func sum(nums ...int) int {
        total := 0
        for _, v := range nums {
            total += v
        }
        return total
    }
    
    func main() {
        fmt.Println(sum(1, 2))
        fmt.Println(sum(1, 2, 3, 4))
    }
    

    7.4 匿名函数

    无函数名,可定义后立即执行,也可赋值给变量调用。

    func main() {
        // 写法1:定义并立即执行
        func(a, b int) {
            fmt.Println(a * b)
        }(3, 5)
    
        // 写法2:赋值给变量,重复调用
        f := func(x int) {
            fmt.Println(x * x)
        }
        f(6)
    }
    

    8. Map 键值对(字典)

    存储 key-value 格式数据,键唯一,遍历顺序无序。

    8.1 定义与初始化

    Map 必须使用 make 初始化,未初始化直接赋值会报错。

    // 格式:map[键类型]值类型
    user := make(map[string]string)
    
    // 新增 / 修改元素(key存在则覆盖,不存在则新增)
    user["name"] = "张三"
    user["age"] = "20"
    

    8.2 取值 + 判断 Key 是否存在

    Map 获取不存在的键,不会报错,会返回对应类型零值。通过第二个返回值 ok 判断键是否真实存在。

    age, ok := user["name"]
    if ok {
        fmt.Println("键存在,值:", age)
    } else {
        fmt.Println("该键不存在")
    }
    
    • age:key 对应的值
    • ok:布尔类型,true = 键存在,false = 键不存在

    8.3 删除元素

    使用内置函数 delete(map对象, key)

    delete(user, "name")
    

    8.4 Map 遍历

    for k, v := range user {
        fmt.Println(k, ":", v)
    }
    

    9. 结构体 struct

    结构体用于封装一组不同类型的数据,自定义现实事物模型。

    9.1 结构体定义

    type 结构体名 struct {
        字段名 字段类型
    }
    
    type Student struct {
        Name string
        Age  int
    }
    

    9.2 结构体实例化与赋值

    func main() {
        // 方式1:键值对赋值(推荐,可读性强)
        s1 := Student{
            Name: "小明",
            Age:  18,
        }
    
        // 方式2:按字段顺序赋值
        s2 := Student{"小红", 19}
    
        // 访问结构体字段
        fmt.Println(s1.Name, s1.Age)
    }
    

    10. 结构体方法

    方法是绑定在结构体上的函数,分为「值接收者」和「指针接收者」。

    10.1 值接收者

    func (接收者变量 结构体类型) 方法名() {}
    
    • 调用时会拷贝结构体副本
    • 无法修改原结构体数据
    • 适用场景:只读查询、打印信息、数值计算
    type Person struct {
        Name string
        Age  int
    }
    
    // 只读方法:值接收者
    func (p Person) GetName() string {
        return p.Name
    }
    
    // 反面示例:尝试用值接收者修改数据(无效)
    func (p Person) Rename(newName string) {
        p.Name = newName // 仅修改副本,原数据不变
    }
    

    10.2 指针接收者

    func (接收者变量 *结构体类型) 方法名() {}
    
    • 直接操作原结构体内存地址
    • 可以修改原结构体数据
    • 适用场景:更新 / 修改字段;结构体较大时,减少拷贝开销
    // 可修改数据:指针接收者
    func (p *Person) SetName(newName string) {
        p.Name = newName
    }
    

    10.3 选用口诀

    • 只读取数据 → 使用 值接收者
    • 需要修改数据 / 结构体体积大 → 使用 指针接收者

    11. 指针基础

    11.1 两个核心符号

    • &:取地址符,获取变量的内存地址
    • *:解引用符,根据地址读写对应的值

    11.2 基础使用

    func main() {
        a := 10
        fmt.Println("变量a的地址:", &a)
    
        // 定义指针变量,存储 int 类型地址
        var p *int
        p = &a
    
        // 通过指针修改原变量值
        *p = 20
        fmt.Println("修改后 a 的值:", a)
    }
    

    11.3 指针作为函数参数

    Go 函数参数默认值传递,普通传参只能修改副本;使用指针传参可直接修改外部原变量。

    普通传参(无法修改原值)

    func change(num int) {
        num = 100
    }
    

    指针传参(可修改原值)

    func change(num *int) {
        *num = 100
    }
    
    func main() {
        x := 10
        change(&x)
        fmt.Println(x) // 输出 100
    }
    

    12. 全套实战练习题

    基础练习

    • 循环顺序打印 1 ~ 10
    • 计算 1 ~ 100 所有数字累加和
    • 输入数字,判断奇数 / 偶数
    • 筛选 1~100 中所有偶数、能被 3 整除的数字

    进阶练习

    • 双层循环:打印直角三角形、九九乘法表
    • 猜数字小游戏(for + if + break)
    • 切片遍历、切片求和、求切片最大值与最小值
    • 简易菜单计算器(Scan + switch + 函数)
    • 学生信息管理(结构体 + Map + 方法)

    13. 高频易错点汇总

    1. fmt.Scan 传参必须加 &,漏写直接编译报错
    2. 空切片不能直接下标赋值,必须使用 append 追加元素
    3. 数组 [...] 语法,仅能在定义并初始化时使用
    4. for range 遍历返回索引和值,无用索引必须用 _ 占位
    5. Map 必须先用 make 初始化,未初始化无法赋值
    6. Map 取值搭配 ok 判断 key 是否存在,区分零值与键不存在
    7. 结构体方法:修改数据用指针接收者,只读逻辑用值接收者
    8. Go 的 switch 默认自带 break,不会顺序穿透
    9. 变量定义后必须使用,否则编译报错
  • 相关阅读:
    springboot+个人博客 毕业设计-附源码191613
    【Docker第三篇】彻底搞懂Dockerfile文件
    实战型开发1/3--结果&业务导向
    【音视频基础】AVI文件格式
    《确保安全:PostgreSQL安全配置与最佳实践》
    java I/O流使用导航
    java-php-python-仓库管理系统计算机毕业设计
    聊聊秒杀系统的设计(二)
    从0搭建vue3组件库: Input组件
    Vue.js核心技术解析与uni-app跨平台实战开发学习笔记 第3章 Vue.js生命周期函数 3.3 销毁期间生命周期函数 && 3.4 扩展
  • 原文地址:https://www.cnblogs.com/zxr1002/p/20170294