Go 语言基础语法(保姆级教程)

Go 语言基础语法:从零开始掌握核心概念

如果你正在学习一门新编程语言,Go 语言(又称 Golang)是一个非常值得投入精力的选择。它由 Google 开发,以简洁、高效和并发能力强著称。无论你是初学者还是有一定经验的开发者,掌握 Go 语言基础语法,都是迈向实战的第一步。

Go 语言的设计哲学是“简单即美”。它没有复杂的继承体系,没有泛型(直到 Go 1.18 才引入),但它的语法清晰、类型安全、编译快速。这使得它特别适合构建微服务、命令行工具和高并发系统。

今天我们就来系统梳理 Go 语言基础语法中的关键部分。文章内容循序渐进,适合从零开始的开发者,也适合想巩固基础的中级开发者。


变量声明与数据类型

在任何编程语言中,变量都是存储数据的基本单元。Go 语言的变量声明方式非常直观。

package main

import "fmt"

func main() {
    // 方式一:显式声明类型
    var name string = "Alice"
    var age int = 25
    var isStudent bool = true

    // 方式二:类型推断(推荐)
    message := "Hello, Go!"
    count := 100
    pi := 3.14159

    // 输出变量值
    fmt.Println("姓名:", name)
    fmt.Println("年龄:", age)
    fmt.Println("是否学生:", isStudent)
    fmt.Println("消息:", message)
    fmt.Println("计数:", count)
    fmt.Println("π 的近似值:", pi)
}

说明

  • var 是 Go 中用于声明变量的关键词。
  • := 是 Go 的短变量声明语法,它会自动推断变量类型,非常方便。
  • 注意::= 只能在函数内部使用,不能用于全局变量声明。
  • 声明变量后必须使用,否则编译会报错(Go 的严谨性体现之一)。

基本数据类型一览

类型 说明 示例
int 整数类型,根据系统位数决定大小 var n int = 42
int8 / int16 / int32 / int64 有符号整数,位数明确 var b int8 = -128
uint / uint8 / uint16 / uint32 / uint64 无符号整数 var u uint = 255
float32 / float64 浮点数,float64 更常用 var f float64 = 3.14
bool 布尔类型,值为 true 或 false var t bool = true
string 字符串类型,UTF-8 编码 var s string = "Go"

提示:Go 语言中字符串是不可变的,一旦创建就不能修改。如果需要拼接,可以使用 + 操作符或 strings.Builder


控制流程:if、for、switch

控制流程是程序执行逻辑的核心。Go 语言的控制语句设计得非常简洁。

if 条件语句

package main

import "fmt"

func main() {
    score := 85

    // Go 的 if 语句支持初始化语句
    if level := "未达标"; score < 60 {
        fmt.Println("成绩:", score, ",等级:", level)
    } else if score < 80 {
        fmt.Println("成绩:", score, ",等级:B")
    } else {
        fmt.Println("成绩:", score, ",等级:A")
    }
}

说明

  • if 后面可以跟一个初始化语句,作用域仅限于当前 if 块。
  • Go 不支持括号中的条件表达式,必须用大括号 {} 包裹代码块。
  • 没有 else if 的括号,直接写 else if 即可。

for 循环:唯一循环结构

Go 只有 for 一种循环,但它功能强大,可以替代其他语言的 whilefor

package main

import "fmt"

func main() {
    // 传统 for 循环
    for i := 0; i < 5; i++ {
        fmt.Printf("第 %d 次循环\n", i+1)
    }

    // 类似 while 的循环
    j := 0
    for j < 3 {
        fmt.Printf("while 循环:%d\n", j)
        j++
    }

    // 无限循环(配合 break 使用)
    k := 0
    for {
        fmt.Printf("无限循环:%d\n", k)
        k++
        if k >= 2 {
            break // 退出循环
        }
    }
}

说明

  • for 的三个部分(初始化、条件、递增)是可选的,但分号必须保留。
  • 无限循环 for {} 常用于服务启动,配合 breakreturn 退出。

switch 语句:多分支选择

package main

import "fmt"

func main() {
    day := 3

    switch day {
    case 1:
        fmt.Println("星期一")
    case 2:
        fmt.Println("星期二")
    case 3:
        fmt.Println("星期三")
    default:
        fmt.Println("其他日子")
    }
}

说明

  • Go 的 switch 不需要 break,每个 case 自动结束。
  • 如果需要“穿透”执行,可以使用 fallthrough 关键字。
  • switch 也可以用于类型判断,结合 type switch 使用。

函数定义与调用

函数是 Go 语言中组织代码的基本单元。它的语法清晰,参数和返回值定义明确。

package main

import "fmt"

// 定义一个函数:计算两个数的和
func add(a int, b int) int {
    return a + b
}

// 带有命名返回值的函数
func divide(x, y float64) (result float64, err error) {
    if y == 0 {
        err = fmt.Errorf("除数不能为零")
        return 0, err
    }
    result = x / y
    return result, nil
}

func main() {
    sum := add(10, 20)
    fmt.Println("10 + 20 =", sum)

    res, err := divide(10.0, 2.0)
    if err != nil {
        fmt.Println("错误:", err)
    } else {
        fmt.Println("10 / 2 =", res)
    }
}

说明

  • 函数参数类型写在参数名后,多个参数可合并类型。
  • 返回值可以命名,命名后可以直接使用 return 返回。
  • error 是 Go 中处理错误的标准方式,函数返回 error 类型可判断是否出错。
  • res, err := divide(...) 是 Go 的“多值返回”特性,非常实用。

数组、切片与映射

创建数组与初始化

package main

import "fmt"

func main() {
    // 定义一个长度为 5 的整型数组
    var numbers [5]int
    numbers[0] = 10
    numbers[1] = 20
    fmt.Println("数组:", numbers)

    // 初始化数组
    scores := [3]int{88, 92, 76}
    fmt.Println("分数数组:", scores)
}

说明

  • 数组长度固定,不可变。
  • 数组是值类型,赋值或传参时会复制整个数组。
  • 通常在实际开发中更推荐使用切片。

切片(Slice):动态数组

package main

import "fmt"

func main() {
    // 创建一个空切片
    var slice []int

    // 使用 make 创建切片
    slice = make([]int, 3, 5) // 长度 3,容量 5
    slice[0] = 100
    slice[1] = 200
    fmt.Println("切片内容:", slice)

    // 从数组创建切片
    data := [5]int{1, 2, 3, 4, 5}
    subSlice := data[1:4] // 从索引 1 到 3(不包含 4)
    fmt.Println("子切片:", subSlice)

    // 切片追加元素
    slice = append(slice, 300, 400)
    fmt.Println("追加后:", slice)
}

说明

  • 切片是动态的,长度可变,内部维护一个底层数组。
  • make([]T, len, cap) 用于创建指定长度和容量的切片。
  • append 会自动扩容,当容量不够时,会创建新数组并复制数据。

映射(Map):键值对容器

package main

import "fmt"

func main() {
    // 创建一个映射,键为字符串,值为整数
    studentScores := map[string]int{
        "Alice": 95,
        "Bob":   87,
        "Charlie": 92,
    }

    // 查询值
    score := studentScores["Alice"]
    fmt.Println("Alice 的成绩:", score)

    // 检查键是否存在
    if value, exists := studentScores["Diana"]; exists {
        fmt.Println("Diana 的成绩:", value)
    } else {
        fmt.Println("Diana 不存在")
    }

    // 添加或修改键值对
    studentScores["Eve"] = 98
    fmt.Println("更新后:", studentScores)
}

说明

  • map 是引用类型,传递时不会复制整个结构。
  • 使用 key, ok := map[key] 可以判断键是否存在。
  • map 无序,不保证遍历时的顺序。

结构体与方法

结构体(struct)是 Go 中组织数据的常用方式,类似于其他语言的“类”或“结构体”。

package main

import "fmt"

// 定义一个结构体:Person
type Person struct {
    Name string
    Age  int
    City string
}

// 为 Person 添加方法:介绍自己
func (p Person) introduce() {
    fmt.Printf("大家好,我是 %s,今年 %d 岁,来自 %s。\n", p.Name, p.Age, p.City)
}

// 可以通过指针接收者修改结构体
func (p *Person) updateCity(newCity string) {
    p.City = newCity
}

func main() {
    // 创建结构体实例
    person := Person{Name: "李明", Age: 30, City: "北京"}

    // 调用方法
    person.introduce()

    // 更新城市
    person.updateCity("上海")
    person.introduce()
}

说明

  • func (p Person) introduce() 是值接收者,不会修改原结构体。
  • func (p *Person) updateCity() 是指针接收者,可以修改原数据。
  • 方法可以绑定到任何类型,包括自定义类型和内置类型。

Go 语言基础语法是理解整个语言生态的基石。从变量声明、控制流程到函数、数据结构,每一步都体现了 Go 的简洁与高效。掌握这些内容,你就能写出结构清晰、运行稳定的 Go 程序。

无论是构建后端服务,还是编写工具脚本,Go 语言基础语法都能为你打下坚实基础。建议你动手写一写代码,边学边练,才能真正掌握。