Go语言入门指南 | 豆包MarsCode AI 刷题

102 阅读6分钟

以下是一份 Go 语言入门指南,涵盖基础语法和常用特征解析:

一、基础语法

1. 变量声明与赋值

  • 在 Go 语言中,可以使用不同的方式声明变量。常见的有使用var关键字声明,例如:
var num int
num = 10

这里先声明了一个int类型(整数类型)的变量num,然后进行赋值。Go 语言也支持短变量声明方式,使用:=操作符,例如:

name := "John"

这种方式会自动根据赋值的内容推断变量的类型,不过它只能在函数内部使用。

2. 数据类型

  • 基本数据类型

    • 整数类型:包括int(有符号整数,在不同平台上长度可能不同,通常是 32 位或 64 位)、int8(8 位有符号整数)、int16int32int64以及对应的无符号整数类型uintuint8(也可以写成byte,常用来表示字节数据)等。
    • 浮点类型:如float32float64,用于表示小数。
    • 布尔类型bool类型,只有truefalse两个值,常用于条件判断。
    • 字符串类型:使用双引号包裹字符内容,例如"Hello, World",它是不可变的,一旦创建就不能修改其内容。
  • 复合数据类型

    • 数组:具有固定长度,声明方式如下:
var arr [5]int

这就声明了一个长度为 5,元素类型为int的数组,并且可以通过索引来访问和修改元素,如arr[0] = 1

  • 切片(Slice) :可以看作是对数组的一个引用,长度可变,通过make函数创建,例如:
s := make([]int, 3)

创建了一个初始长度为 3,元素类型为int的切片,切片支持动态地增加或减少元素数量。

  • 映射(Map) :类似其他编程语言中的字典,以键值对形式存储数据,通过make函数创建,例如:
m := make(map[string]int)
m["key"] = 10

这里创建了一个键类型为string,值类型为int的映射,并添加了一对键值对。

3. 控制流语句

  • 条件判断:使用if语句,例如:
if num > 5 {
    fmt.Println("大于5")
} else {
    fmt.Println("小于等于5")
}

Go 语言中的if语句还可以在条件判断前声明一个变量,且该变量的作用域仅限于这个if语句块内,如:

if n := 10; n > 5 {
    fmt.Println("大于5")
}
  • 循环语句

    • for循环:最常用的循环方式,有多种形式。例如常规的计数循环:
for i := 0; i < 10; i++ {
    fmt.Println(i)
}

也可以省略初始条件、结束条件、递增语句等部分,形成类似while循环的效果,比如:

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

还有一种无限循环的写法:

for {
    // 循环体内容
}
  • switch语句:用于多分支条件判断,例如:
switch num {
case 1:
    fmt.Println("是1")
case 2:
    fmt.Println("是2")
default:
    fmt.Println("其他值")
}

Go 语言中的switch语句不需要在每个case后面写break,它默认执行完对应case的语句块后就结束,除非使用fallthrough关键字来强制执行下一个case的语句块。

4. 函数定义

  • 函数使用func关键字定义,格式如下:
func add(a int, b int) int {
    return a + b
}

上面定义了一个名为add的函数,接受两个int类型的参数ab,并返回一个int类型的结果。Go 语言还支持多返回值的函数,例如:

func div(a, b int) (int, error) {
    if b == 0 {
        return 0, fmt.Errorf("除数不能为0")
    }
    return a / b, nil
}

这个函数返回除法运算的结果以及一个可能的错误信息(如果除数为 0)。

二、常用特征解析

1. 包管理

  • Go 语言通过package来组织代码,每个.go文件开头都要声明所属的包名,例如:
package main

main包是特殊的,它是可执行程序的入口包。要使用其他包中的函数、类型等,需要使用import语句导入,比如导入标准库中的fmt包(用于格式化输出等操作):

import "fmt"

可以通过go mod命令来管理项目的依赖包,创建go.mod文件记录依赖信息,方便项目的构建和部署。

2. 并发编程

  • goroutine:Go 语言中实现并发的轻量级线程,通过在函数调用前添加go关键字就可以启动一个goroutine,例如:
func main() {
    go sayHello()
    // 主程序可以继续执行其他任务
    time.Sleep(time.Second)
}

func sayHello() {
    fmt.Println("Hello")
}

这里sayHello函数会在一个独立的goroutine中执行,不会阻塞主程序的执行,不过需要注意,主程序如果结束太快,goroutine可能来不及执行完,所以通常需要适当的等待机制(如上述代码中的time.Sleep)或者使用sync.WaitGroup等同步工具来确保goroutine完成任务。

  • channel:用于在goroutine之间进行通信和同步,它是一种类型,可以通过make函数创建,例如:
ch := make(chan int)
go func() {
    ch <- 10 // 向channel发送数据
}()
num := <-ch // 从channel接收数据

channel可以控制数据的流向,避免多个goroutine访问共享数据时出现竞争条件等并发问题,还可以设置为有缓冲或无缓冲等不同模式,来满足不同的并发场景需求。

3. 错误处理

  • Go 语言采用显式的错误处理方式,函数返回值中通常会包含一个error类型的值来表示是否发生错误,调用函数的地方需要检查这个错误并进行相应处理,例如:
res, err := strconv.Atoi("abc") // Atoi函数尝试将字符串转换为整数
if err!= nil {
    fmt.Println("转换出错:", err)
    return
}
fmt.Println("转换结果:", res)

这种方式使得代码中对错误的处理更加清晰明了,程序员能明确知道哪些操作可能会出错以及如何应对。

4. 接口(Interface)

  • 接口定义了一组方法签名,只要一个类型实现了接口中定义的所有方法,就可以说这个类型实现了该接口,例如:
type Shape interface {
    Area() float64
}

type Rectangle struct {
    width, height float64
}

func (r Rectangle) Area() float64 {
    return r.width * r.height
}

这里定义了Shape接口,包含Area方法,而Rectangle结构体实现了Area方法,也就实现了Shape接口。接口常用于实现多态等面向对象编程的特性,方便代码的扩展和复用,比如可以编写一个函数接受Shape接口类型的参数,这样就可以传入任何实现了Shape接口的具体类型来计算面积。

以上就是 Go 语言的基础语法和一些常用特征的解析,需要通过不断练习和实践这些内容,才能逐步掌握 Go 语言并用于开发各种类型的项目。