文章目录
- 1. 下载安装Go
- 官网安装
- 使用 Homebrew 安装 (Mac)
- 创建工作目录 (Workspace)
- 设置环境变量
- 通过 VSCode 扩展商店安装 Go 插件
- 处理权限问题
- 2. Hello, World 示例
- 3. 语法基础
- 变量声明
- 常量
- 数组
- 切片(Slice)
- Map(集合)
- 控制结构
- for 循环
- 基本形式:
- 类似 `while` 的形式:
- 无限循环:
- 条件判断
- 函数与指针
- 函数
- 指针
- 结构体与接口
- 结构体
- 接口
- 并发
- goroutine
- 通道(Channel)
- 错误处理
- 5. 常用数据结构和算法
- 1. 队列(Queue)
- 2. 栈(Stack)
- 3. 链表(Linked List)
- 4. 哈希表(Map)
- 5. 集合(Set)
- 6. 二叉树(Binary Tree)
- 7. 图(Graph)
- 8. 链表(Linked List)
1. 下载安装Go
官网安装
访问 Go官网,根据操作系统下载并安装对应版本。
使用 Homebrew 安装 (Mac)
brew update
brew install golang
创建工作目录 (Workspace)
在$HOME
目录下创建一个Go工作目录:
mkdir $HOME/go_workspace
设置环境变量
编辑终端配置文件(例如 ~/.zshrc
或 ~/.bashrc
),添加以下内容:
export GOROOT=/opt/homebrew/opt/go/libexec
export GOPATH=$HOME/go_workspace
export PATH=$PATH:$GOPATH/bin
export PATH=$PATH:$GOROOT/bin
通过 VSCode 扩展商店安装 Go 插件
-
打开 VSCode:
- 通过应用程序启动 VSCode 或者在终端中运行
code
命令(如果已安装 VSCode 命令行工具)。
- 通过应用程序启动 VSCode 或者在终端中运行
-
进入扩展商店:
- 在左侧工具栏中,点击“扩展”图标(看起来像一个四方的拼图块),或者使用快捷键
Command+Shift+X
打开扩展商店。
- 在左侧工具栏中,点击“扩展”图标(看起来像一个四方的拼图块),或者使用快捷键
-
搜索并安装 Go 插件:
- 在扩展商店的搜索框中,输入 “Go”,会看到由 Microsoft 提供的官方 Go 扩展。
- 点击 “Install” 按钮进行安装。
-
自动安装工具:
- 安装插件后,当你首次打开一个 Go 项目或 Go 文件时,VSCode 通常会自动提示你安装所需的工具。如果有此提示,选择“安装所有工具”即可。
- 如果没有提示,仍然可以使用
Command+Shift+P
打开命令面板,输入Go: Install/Update Tools
,然后选择并安装所有相关工具。
处理权限问题
如果在安装工具时遇到权限问题,如权限被拒绝(Permission Denied)或 /usr/local/pkg
目录不存在,可以使用以下命令修复权限问题:
sudo mkdir /usr/local/pkg
sudo chown -R $(whoami) /usr/local/pkg
这会创建所需的目录并将其权限设置为当前用户,从而避免权限问题。
2. Hello, World 示例
新建一个 hello.go
文件,内容如下:
package main
import "fmt"
func main() {
fmt.Println("Hello, Go!")
}
运行程序:
go run hello.go
输出结果:
Hello, Go!
生成可执行文件:
go build hello.go
./hello
3. 语法基础
变量声明
Go 语言使用 var
关键字声明变量,语法为:
var identifier type
示例:
package main
import "fmt"
var a string = "Geek Go" // 变量声明在函数外部
func main() {
fmt.Println(a) // 输出:Geek Go,函数体内可以放执行代码
}
简化版:
package main
import "fmt"
var a string = "Geek Go" // 变量声明在函数外部
func main() {
fmt.Println(a) // 输出:Geek Go,函数体内可以放执行代码
b, c := 1, 2 // 自动推断类型为 int
fmt.Println(b, c) // 输出:1 2
}
常量
常量使用 const
关键字来声明:
package main
import "fmt"
func main() {
const pi = 3.14 // 声明常量
fmt.Println("Pi的值是:", pi)
}
数组
数组声明并使用 for
循环遍历:
package main
import "fmt"
func main() {
var arr [5]int = [5]int{1, 2, 3, 4, 5}
// 使用 for 循环遍历数组
for i := 0; i < len(arr); i++ {
fmt.Println(arr[i])
}
}
切片(Slice)
切片是长度可变的动态数组:
package main
import "fmt"
func main() {
slice := []int{1, 2, 3, 4, 5}
// 打印切片的一部分
fmt.Println(slice[1:4]) // 输出:[2 3 4]
// 向切片添加元素
slice = append(slice, 6, 7)
fmt.Println("追加后的切片:", slice)
}
Map(集合)
Map 是键值对的集合:
package main
import "fmt"
func main() {
// 创建一个 Map
cars := make(map[string]string)
cars["A"] = "Audi"
cars["B"] = "BMW"
cars["T"] = "Tesla"
// 遍历 Map
for k, v := range cars {
fmt.Printf("%s -> %s\n", k, v)
}
}
控制结构
for 循环
Go 语言的 for
循环有三种常见形式:
基本形式:
package main
import "fmt"
func main() {
for i := 0; i < 5; i++ {
fmt.Println(i)
}
}
类似 while
的形式:
package main
import "fmt"
func main() {
i := 0
for i < 5 {
fmt.Println(i)
i++
}
}
无限循环:
package main
import "fmt"
func main() {
for {
fmt.Println("This will run forever")
break // 使用 break 来防止无限循环
}
}
条件判断
使用 if
语句进行条件判断:
package main
import "fmt"
func main() {
x := 10
if x > 10 {
fmt.Println("x is greater than 10")
} else {
fmt.Println("x is 10 or less")
}
}
函数与指针
函数
Go 中函数的定义和调用:
package main
import "fmt"
// 定义一个函数来求两个数的和
func add(x int, y int) int {
return x + y
}
func main() {
result := add(3, 4)
fmt.Println("3 + 4 =", result)
}
指针
Go 中指针的使用:
package main
import "fmt"
func main() {
x := 10
var p *int
p = &x // 获取变量x的地址
fmt.Println("x的值是:", x)
fmt.Println("p指向的地址是:", p)
fmt.Println("p指向的值是:", *p) // 通过指针访问值
}
结构体与接口
结构体
结构体用于定义复杂数据类型:
package main
import "fmt"
// 定义一个结构体
type Book struct {
title string
author string
price float32
}
func main() {
// 创建结构体实例
book := Book{title: "Go语言教程", author: "GeekHall", price: 9.9}
// 输出结构体内容
fmt.Println(book)
}
结构体作为函数参数:
package main
import "fmt"
// 定义一个结构体
type Book struct {
title string
author string
price float32
}
// 定义一个打印书籍信息的函数
func printBook(book *Book) {
fmt.Println("书名:", book.title)
fmt.Println("作者:", book.author)
fmt.Println("价格:", book.price)
}
func main() {
book := Book{title: "Go语言教程", author: "GeekHall", price: 9.9}
printBook(&book) // 传递指针
}
接口
接口定义一组方法,任何实现了这些方法的类型都实现了该接口:
package main
import "fmt"
// 定义一个接口
type ICar interface {
drive()
}
// 定义实现接口的结构体
type Tesla struct{}
func (t Tesla) drive() {
fmt.Println("I am a Tesla")
}
func main() {
var car ICar = Tesla{}
car.drive()
}
并发
goroutine
使用 go
关键字启动一个新的并发任务:
package main
import "fmt"
func concurrentTest(s string) {
for i := 0; i < 5; i++ {
fmt.Println(s)
}
}
func main() {
go concurrentTest("Tesla")
concurrentTest("Toyota")
}
通道(Channel)
通道用于在 goroutine 之间传递数据:
package main
import "fmt"
// 定义一个求和函数,结果通过通道传递
func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
c <- sum // 发送结果到通道
}
func main() {
s := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
x, y := <-c, <-c // 从通道接收结果
fmt.Println(x, y, x+y)
}
错误处理
Go 提供了内置的 error
接口用于错误处理:
package main
import (
"errors"
"fmt"
)
func divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("division 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)
}
}
5. 常用数据结构和算法
1. 队列(Queue)
队列是一种先进先出(FIFO)的数据结构,可以使用切片(Slice)来模拟队列的操作:
package main
import "fmt"
func main() {
queue := []int{1, 2, 3}
// 入队
queue = append(queue, 4)
fmt.Println("队列状态:", queue)
// 出队
head := queue[0]
queue = queue[1:]
fmt.Println("队头元素:", head)
fmt.Println("出队后的队列:", queue)
}
2. 栈(Stack)
栈是一种后进先出(LIFO)的数据结构,也可以使用切片来模拟栈的操作:
package main
import "fmt"
func main() {
stack := []int{}
// 入栈
stack = append(stack, 1)
stack = append(stack, 2)
stack = append(stack, 3)
fmt.Println("栈状态:", stack)
// 出栈
top := stack[len(stack)-1]
stack = stack[:len(stack)-1]
fmt.Println("栈顶元素:", top)
fmt.Println("出栈后的栈:", stack)
}
3. 链表(Linked List)
Go 标准库没有直接提供链表的实现,但可以使用 container/list
包来创建双向链表:
package main
import (
"container/list"
"fmt"
)
func main() {
// 创建一个双向链表
l := list.New()
// 插入元素
l.PushBack(1)
l.PushBack(2)
l.PushBack(3)
// 遍历链表
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
// 删除第一个元素
l.Remove(l.Front())
fmt.Println("删除第一个元素后:")
for e := l.Front(); e != nil; e = e.Next() {
fmt.Println(e.Value)
}
}
4. 哈希表(Map)
Go 内置 map
类型来实现哈希表(键值对映射):
package main
import "fmt"
func main() {
// 创建一个 map
fruits := map[string]string{
"apple": "red",
"banana": "yellow",
"grape": "purple",
}
// 打印 map
for fruit, color := range fruits {
fmt.Printf("%s is %s\n", fruit, color)
}
// 查找元素
color, found := fruits["apple"]
if found {
fmt.Println("The color of apple is", color)
} else {
fmt.Println("Apple not found!")
}
// 删除元素
delete(fruits, "banana")
fmt.Println("删除后:", fruits)
}
5. 集合(Set)
Go 没有直接提供 Set
类型,但可以使用 map
来模拟集合。map
的键代表集合的元素,值可以忽略或设置为 true
。
package main
import "fmt"
func main() {
// 使用 map 模拟集合
set := make(map[string]bool)
// 添加元素
set["apple"] = true
set["banana"] = true
set["orange"] = true
// 检查元素是否存在
if set["apple"] {
fmt.Println("集合中有 apple")
}
// 删除元素
delete(set, "banana")
fmt.Println("删除 banana 后的集合:", set)
// 遍历集合
fmt.Println("集合中的元素:")
for fruit := range set {
fmt.Println(fruit)
}
}
6. 二叉树(Binary Tree)
Go 标准库没有提供树结构,但可以手动实现二叉树。以下是一个简单的二叉搜索树的实现:
package main
import "fmt"
// 定义二叉树节点
type TreeNode struct {
value int
left *TreeNode
right *TreeNode
}
// 插入元素到二叉搜索树
func insert(node *TreeNode, value int) *TreeNode {
if node == nil {
return &TreeNode{value: value}
}
if value < node.value {
node.left = insert(node.left, value)
} else {
node.right = insert(node.right, value)
}
return node
}
// 中序遍历二叉树
func inorderTraversal(node *TreeNode) {
if node != nil {
inorderTraversal(node.left)
fmt.Println(node.value)
inorderTraversal(node.right)
}
}
func main() {
var root *TreeNode
values := []int{8, 3, 10, 1, 6, 14, 4, 7, 13}
for _, value := range values {
root = insert(root, value)
}
fmt.Println("二叉树的中序遍历:")
inorderTraversal(root)
}