Go语言学习笔记

64 阅读4分钟

Go 语言入门指南:基础语法和常用特性解析

1. Go语言简介

Go 语言(又称 Golang)由 Google 于 2007 年开始设计并于 2009 年公开发布。它是一种静态类型、编译型语言,字节后端大部分就是用Go写的

2. Go 语言基础语法

2.1 Hello World

一个简单的 Go 语言程序如下:

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

Go 程序通常由三个部分组成:

  • 包声明package main 表示当前文件属于 main 包。Go 程序的执行从 main 包的 main 函数开始。
  • 导入包import 语句导入需要的库。Go 提供了大量的标准库,fmt 包就是其中之一,用于格式化输出。
  • 函数定义main 函数是程序的入口,所有程序的执行都从这里开始。

2.2 变量声明

Go 中的变量声明非常简洁,有三种主要方式来声明变量:

  1. 显式声明

    var a int
    var b string
    var c bool
    

    这三行分别声明了一个整型变量 a、字符串变量 b 和布尔型变量 c,并且没有初始化,因此它们的零值分别是 0""false

  2. 声明并初始化

    var a int = 10
    var b string = "Go"
    var c bool = true
    

    上述声明同时为变量赋初值。

  3. 简短声明:Go 提供了一个简便的方式来声明并初始化变量,使用 := 运算符:

    a := 10
    b := "Go"
    c := true
    

    这种方式无需显式指定类型,Go 会自动推断类型。

2.3 数据类型

Go 是强类型语言,每个变量都有明确的类型。Go 支持多种基本数据类型,包括:

  • 数值类型intfloat32float64complex64complex128
  • 布尔类型bool
  • 字符类型byte(即 uint8)和 rune(即 int32
  • 字符串类型string,支持 Unicode 编码。
  • 数组、切片、映射(map)等复合类型

2.4 控制结构

Go 支持常见的控制结构:条件语句、循环语句和跳转语句。

  1. 条件语句: Go 中的条件语句使用 if 语句,且支持可选的初始化语句:

    if x := 10; x > 5 {
        fmt.Println("x is greater than 5")
    }
    
  2. 循环语句: Go 没有 forwhile 等多个循环类型,只有一种 for 循环,它可以用作任何类型的循环:

    for i := 0; i < 10; i++ {
        fmt.Println(i)
    }
    
    // 无限循环
    for {
        fmt.Println("This will run forever")
    }
    
  3. 跳转语句breakcontinuegoto 是 Go 中常用的跳转语句:

    for i := 0; i < 10; i++ {
        if i == 5 {
            break  // 跳出循环
        }
        fmt.Println(i)
    }
    

2.5 函数

Go 语言中的函数非常灵活,支持多个返回值和命名返回值。

  1. 基本函数

    func add(a int, b int) int {
        return a + b
    }
    
  2. 多个返回值: Go 支持多个返回值:

    func swap(a, b int) (int, int) {
        return b, a
    }
    
  3. 命名返回值: 在 Go 中,可以为返回值命名,使得函数内部直接修改返回值变量:

    func split(sum int) (x, y int) {
        x = sum * 4 / 9
        y = sum - x
        return
    }
    
  4. 变长参数: Go 支持函数的变长参数,通过 ... 来实现:

    func sum(nums ...int) int {
        total := 0
        for _, num := range nums {
            total += num
        }
        return total
    }
    

2.6 指针

Go 语言中也支持指针类型,但与 C 语言不同的是,Go 不支持指针运算。指针在函数传参时特别有用,可以避免值传递时的内存复制开销。

  1. 指针声明

    var p *int
    
  2. 指针操作

    var a int = 58
    var p *int = &a  // 取地址
    fmt.Println(*p)   // 取值
    

3. Go 的高级特性

3.1 并发编程

Go 最大的特点之一就是内建对并发的支持。Go 提供了轻量级的线程—协程(goroutines),通过 go 关键字启动。

  1. Goroutine

    go func() {
        fmt.Println("This is a Goroutine")
    }()
    
  2. Channel: Go 使用通道(channel)来实现不同 Goroutines 之间的通信。通道是 Go 的一个强大特性,它能够让不同的 Goroutine 通过通道进行同步和数据交换。

    ch := make(chan int)
    
    go func() {
        ch <- 42  // 将数据发送到通道
    }()
    
    value := <-ch  // 从通道中接收数据
    fmt.Println(value)
    

3.2 面向对象

Go 是一种结构化的语言,它没有传统的面向对象特性如类和继承,但通过组合和接口实现面向对象的功能。

  1. 结构体: Go 语言的结构体(struct)类似于其他语言中的类,它是用户自定义数据类型的集合。

    type Person struct {
        Name string
        Age  int
    }
    
    func (p Person) Greet() {
        fmt.Printf("Hello, my name is %s and I am %d years old.\n", p.Name, p.Age)
    }
    
  2. 接口: Go 使用接口来实现多态,不需要显式声明实现关系,只要实现了接口的方法,就认为是实现了接口。

    type Speaker interface {
        Speak() string
    }
    
    type Person struct {
        Name string
    }
    
    func (p Person) Speak() string {
        return "Hello, my name is " + p.Name
    }
    
    func sayHello(speaker Speaker) {
        fmt.Println(speaker.Speak())
    }
    

3.3 错误处理

Go 语言的错误处理非常简洁,不支持异常机制,而是通过多返回值的方式返回错误信息。

func divide(a, b int) (int, error) {
    if b == 0 {
        return 0, fmt.Errorf("division by zero")
    }
    return a / b, nil
}

使用时,通过判断错误值来处理:

result, err := divide(10, 2)
if err != nil {
    fmt.Println("Error:", err)
} else {
    fmt.Println("Result:", result)
}