Go 语言入门笔记青训营X豆包MarsCode 技术训练营第一课 | Go语言学习
Go 语言,又称为 Golang,是一种静态强类型、编译型的编程语言,由 Google 开发并开源。Go 语言以其简洁、高效和并发支持而闻名,特别适合构建大规模的网络服务和分布式系统。本指南将带领你了解 Go 语言的基础语法和一些常用特性,并通过代码示例来加深理解。
1. Go 语言基础
1.1 变量和类型
Go 语言是静态类型语言,所有变量在使用前必须声明类型。Go 支持基本数据类型,如 int、float64、bool 和 string。
var a int = 10var b float64 = 20.5var c bool = truevar d string = "Hello, Go!"
1.2 控制流程
Go 语言支持传统的控制流程语句,如 if、else、for 和 switch。
if a > 5 {
fmt.Println("a is greater than 5")}
for i := 0; i < 5; i++ {
fmt.Println(i)}
switch d {case "Hello":
fmt.Println("String starts with Hello")default:
fmt.Println("String is something else")}
2. 函数和方法
在 Go 中,函数是一等公民,可以作为参数传递给其他函数,也可以从其他函数返回。
func add(x, y int) int {
return x + y}
func main() {
result := add(3, 5)
fmt.Println("Sum:", result)}
3. 包和模块
Go 语言使用包(package)来组织代码。每个 Go 文件都属于一个包,main 包是程序的入口点。
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")}
4. 并发:Goroutine 和 Channel
Go 语言的并发模型基于 Goroutines 和 Channels。Goroutines 是轻量级的线程,由 Go 运行时管理,而 Channels 用于在 Goroutines 之间安全地传递数据。
func hello(i int) {
fmt.Println("hello goroutine : ", i)}
func main() {
for i := 0; i < 5; i+++ {
go hello(i)
}
time.Sleep(time.Second)}
在 Go 语言中,使用互斥锁(Mutex)可以保证并发操作的安全性。
var (
x int64
Lock sync.Mutex)
func addWithLock() {
for i := 0; i < 2000; i++ {
Lock.Lock()
x++
Lock.Unlock()
}}
func addWithoutLock() {
for i := 0; i < 2000; i++ {
x++
}}
在上述代码中,addWithLock 函数使用互斥锁来保护对共享变量 x 的访问,而 addWithoutLock 函数则没有使用互斥锁,可能会导致竞态条件。
4.1 WaitGroup
sync.WaitGroup 是 Go 语言中用于等待一组 Goroutine 完成的工具。
func ManyGoWait() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()}
在上述代码中,我们创建了 5 个 Goroutine,并使用 WaitGroup 等待它们全部完成。
4. 2 Channel
Channels 用于在 Goroutines 之间同步通信。
func main() {
ch := make(chan int)
go func() {
ch <- 1
close(ch)
}()
v, ok := <-ch
fmt.Println(v, ok)}
4.3 并发与并行
在计算机科学中,并发(Concurrency)和并行(Parallelism)是两个核心概念。并发是指两个或多个任务可以在同一时间段内开始、运行和完成,而并行则是指任务在物理上同时执行。
4.3.1 Goroutine
Go 语言的 Goroutine 是一种轻量级的线程,由 Go 运行时(runtime)管理。Goroutine 的调度不需要操作系统内核的干预,这使得 Goroutine 的创建和销毁非常高效。
func hello(i int) {
fmt.Println("hello goroutine : ", i)}
func HelloGoRoutine() {
for i := 0; i < 5; i+++ {
go func(j int) {
hello(j)
}(i)
}
time.Sleep(time.Second)}
在上述代码中,我们创建了 5 个 Goroutine,每个 Goroutine 都会打印出自己的编号。
4.3.2 CSP (Communicating Sequential Processes)
CSP 是 Go 语言的并发模型,它鼓励通过通道(Channel)进行通信,以实现 Goroutine 之间的同步和数据交换。
func CatSquare() {
src := make(chan int, 3)
dest := make(chan int, 3)
go func() {
for i := 0; i < 10; i++ {
src <- i
}
close(src)
}()
go func() {
for i := range src {
dest <- i * i
}
close(dest)
}()
for i := range dest {
fmt.Println(i)
}}
5. 错误处理
Go 语言通过返回值来处理错误,而不是抛出异常。
func Divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("cannot divide by zero")
}
return a / b, nil}
func main() {
result, err := Divide(10, 0)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Result:", result)
}}
6. 接口和多态
Go 语言的接口(interface)定义了一组方法,任何实现了这些方法的类型都满足该接口。
type Shape interface {
Area() float64}
type Circle struct {
radius float64}
func (c Circle) Area() float64 {
return math.Pi * c.radius * c.radius}
func main() {
var s Shape
s := Circle{radius: 5}
s = s
fmt.Println(s.Area())}
7. 结构体和方法
结构体(struct)是 Go 语言中定义复杂数据类型的方式,可以包含多个字段和方法。
type Person struct {
Name string
Age int}
func (p Person) Introduce() {
fmt.Printf("Hi, my name is %s and I am %d years old.\n", p.Name, p.Age)}
func main() {
person := Person{Name: "Alice", Age: 30}
person.Introduce()}
8. 切片和映射
切片(slice)是动态数组,映射(map)是键值对的集合。
func main() {
slice := []int{1, 2, 3}
slice = append(slice, 4)
map := map[string]int{"one": 1, "two": 2}
map["three"] = 3
fmt.Println(slice)
fmt.Println(map)}
9 . 依赖管理
Go 语言的依赖管理经历了从 GOPATH 到 Go Vendor,再到 Go Module 的演进。
9 .1 GOPATH
在早期的 Go 语言中,依赖管理依赖于环境变量 GOPATH。每个项目可以有自己的 vendor 目录,但这导致了依赖冲突和版本控制的问题。
9 .2 Go Vendor
Go Vendor 允许项目引入一份依赖的副本,解决了多个项目需要同一个 package 依赖的冲突问题。
9 .3 Go Module
Go Module 是 Go 语言的官方依赖管理工具,它通过 go.mod 文件来管理依赖版本,并通过 go get 命令来下载依赖。
module example/project/app
require (
example/lib1 v1.0.2
example/lib2 v1.0.0 // indirect
example/lib3 v0.1.0-20190725025543-5a5fe074e612
example/lib4 v0.0.0-20180306012644-bacd9c7ef1dd // indirect
example/lib5 v3.0.2
example/lib6 v3.2.0+incompatible)
9 .4 依赖配置 - go.mod
go.mod 文件用于描述项目的依赖关系,包括直接依赖和间接依赖。
9 .5 依赖分发 - Proxy
Go 语言支持通过代理服务器来分发依赖,这可以提高依赖下载的稳定性和可靠性。
9 .6 依赖分发 - 变量 GOPROXY
通过设置环境变量 GOPROXY,可以指定 Go 语言使用代理服务器来下载依赖。
9 .7 工具 - go get
go get 是 Go 语言的依赖管理工具,它支持多种参数来控制依赖的下载和更新。
9 .8 工具 - go mod
go mod 是 Go 语言的模块管理工具,它提供了初始化、下载、添加、删除依赖等功能。
10 . 总结
Go 语言以其简洁的语法、强大的并发支持和高效的性能,成为了许多开发者构建现代应用程序的首选语言。通过本指南,我们介绍了 Go 语言的基础语法、并发模型、错误处理、接口和多态、以及切片和映射等特性。希望这些内容能够帮助你快速上手 Go 语言,并在实际项目中灵活运用。
在使用Go 语言的过程当中我发现因为其提供了强大的并发支持和依赖管理工具,通过理解并发模型、依赖管理和并发安全,我可以更好地利用 Go 语言的特性来构建高性能的软件。