Go入门教程 - 从零开始学习Go语言编程
Go入门教程 - 从零开始学习Go语言编程
目录
1. Go语言简介
Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。Go语言于2009年正式发布,由Robert Griesemer、Rob Pike和Ken Thompson设计。
核心特点:
✅ 简洁高效:语法简洁,学习曲线平缓
✅ 编译快速:编译速度快,适合大型项目
✅ 并发支持:原生支持goroutine,并发编程简单
✅ 垃圾回收:自动内存管理,无需手动释放
✅ 静态类型:编译时类型检查,减少运行时错误
✅ 跨平台:支持Windows、Linux、macOS等
✅ 标准库丰富:内置强大的标准库
后端服务:Web服务、API服务、微服务
云原生:Docker、Kubernetes等
分布式系统:分布式存储、消息队列
网络编程:网络服务器、代理服务器
DevOps工具:CI/CD工具、监控工具
区块链:以太坊等区块链项目
- 开发效率高:语法简洁,代码量少
- 性能优秀:接近C语言的性能
- 部署简单:编译成单个可执行文件
- 并发模型:goroutine轻量级,易于使用
- 工具链完善:go fmt、go test等工具
| 特性 | Go | Java | Python | C++ |
|---|---|---|---|---|
| 编译速度 | 快 | 中等 | 解释型 | 慢 |
| 运行速度 | 快 | 中等 | 慢 | 很快 |
| 并发支持 | 原生 | 需要线程 | GIL限制 | 需要线程 |
| 内存管理 | GC | GC | GC | 手动 |
| 学习曲线 | 平缓 | 中等 | 平缓 | 陡峭 |
2. 环境搭建
Windows系统
下载Go安装包
- 访问官网:https://golang.org/dl/
- 下载Windows版本(.msi文件)
安装Go
- 运行下载的.msi文件
- 按照提示完成安装
- 默认安装路径:
C:\Program Files\Go
验证安装
go version # 应该显示:go version go1.21.x windows/amd64
macOS系统
方式1:使用Homebrew(推荐)
brew install go方式2:手动安装
- 访问官网下载macOS版本
- 运行.pkg安装包
- 按照提示完成安装
验证安装:
go versionLinux系统
Ubuntu/Debian:
# 下载最新版本
wget https://go.dev/dl/go1.21.5.linux-amd64.tar.gz
# 解压到/usr/local
sudo tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz
# 添加到PATH(添加到~/.bashrc或~/.zshrc)
export PATH=$PATH:/usr/local/go/bin
# 重新加载配置
source ~/.bashrc # 或 source ~/.zshrcCentOS/RHEL:
# 使用yum安装
sudo yum install golang验证安装:
go versionGOPATH(可选,Go 1.11+推荐使用Go Modules)
# 设置GOPATH(可选)
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/binGOROOT(通常不需要手动设置)
Go安装后会自动设置GOROOT。
# 设置Go代理(加速下载)
go env -w GOPROXY=https://goproxy.cn,direct
# 验证配置
go env | grep GOPROXY创建测试文件验证:
# 创建工作目录
mkdir -p ~/go-workspace
cd ~/go-workspace
# 创建测试文件
cat > hello.go << 'EOF'
package main
import "fmt"
func main() {
fmt.Println("Hello, Go!")
}
EOF
# 运行
go run hello.go
# 输出:Hello, Go!2.5 安装IDE
推荐使用以下IDE之一:
- VS Code:安装Go扩展
- GoLand:JetBrains出品的Go IDE
- Vim/Neovim:配置Go插件
- Sublime Text:安装Go插件
3. 第一个Go程序
创建文件 hello.go:
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}package main // 包声明,main包表示可执行程序
import "fmt" // 导入fmt包,用于格式化输出
func main() { // main函数是程序入口
fmt.Println("Hello, World!") // 输出Hello, World!
}关键点:
package main:main包是程序的入口包import:导入需要的包func main():main函数是程序执行的入口fmt.Println:打印输出
方式1:直接运行
go run hello.go
# 输出:Hello, World!方式2:编译后运行
# 编译
go build hello.go
# 运行(Windows)
hello.exe
# 运行(Linux/macOS)
./hello方式3:安装到GOPATH/bin
go install hello.go
# 会在$GOPATH/bin目录生成可执行文件3.4 Go程序的基本结构
package main // 1. 包声明
import ( // 2. 导入包
"fmt"
"os"
)
const ( // 3. 常量声明(可选)
Pi = 3.14159
)
var ( // 4. 变量声明(可选)
name = "Go"
)
func init() { // 5. init函数(可选,在main之前执行)
// 初始化代码
}
func main() { // 6. main函数(必需)
// 程序代码
}4. Go基础语法
Go支持两种注释方式:
// 单行注释
/*
* 多行注释
* 可以写多行
*/
// 文档注释(用于生成文档)
// Package main 是程序的入口包标识符规则
- 必须以字母或下划线开头
- 后续可以是字母、数字、下划线
- 区分大小写
- 不能使用Go关键字
Go关键字(25个)
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return varGo有严格的代码风格要求:
// ✅ 正确:左大括号不能换行
func main() {
fmt.Println("Hello")
}
// ❌ 错误:左大括号换行
func main()
{
fmt.Println("Hello")
}使用go fmt格式化:
go fmt hello.go5. 数据类型
整数类型
var (
i8 int8 = 127 // -128 到 127
i16 int16 = 32767 // -32768 到 32767
i32 int32 = 2147483647 // -2^31 到 2^31-1
i64 int64 = 9223372036854775807 // -2^63 到 2^63-1
u8 uint8 = 255 // 0 到 255
u16 uint16 = 65535 // 0 到 65535
u32 uint32 = 4294967295 // 0 到 2^32-1
u64 uint64 = 18446744073709551615 // 0 到 2^64-1
i int = 9223372036854775807 // 平台相关,32或64位
u uint = 18446744073709551615 // 平台相关,32或64位
)浮点类型
var (
f32 float32 = 3.14
f64 float64 = 3.141592653589793
)复数类型
var (
c64 complex64 = 1 + 2i
c128 complex128 = 1 + 2i
)布尔类型
var (
b1 bool = true
b2 bool = false
)字符串类型
var (
s1 string = "Hello"
s2 string = `多行
字符串
可以换行`
)字节类型
var (
b byte = 'A' // byte是uint8的别名
r rune = '中' // rune是int32的别名,用于Unicode字符
)Go是强类型语言,需要显式类型转换:
var i int = 42
var f float64 = float64(i) // int转float64
var u uint = uint(f) // float64转uint
// 字符串转换
import "strconv"
s := "123"
i, err := strconv.Atoi(s) // 字符串转int
f, err := strconv.ParseFloat("3.14", 64) // 字符串转float64
s2 := strconv.Itoa(123) // int转字符串// 使用 := 可以自动推断类型
i := 42 // int
f := 3.14 // float64
s := "Hello" // string
b := true // bool6. 变量和常量
方式1:var声明
// 声明单个变量
var name string
var age int
// 声明并初始化
var name string = "Go"
var age int = 10
// 类型推断
var name = "Go"
var age = 10
// 批量声明
var (
name string = "Go"
age int = 10
isOk bool = true
)方式2:短变量声明(推荐)
// 只能在函数内使用
name := "Go"
age := 10
isOk := true
// 批量声明
name, age, isOk := "Go", 10, true方式3:多变量声明
var a, b, c int = 1, 2, 3
x, y, z := 1, 2, 3
// 交换变量
a, b = b, a// 单个常量
const Pi = 3.14159
// 类型常量
const Pi float64 = 3.14159
// 批量常量
const (
StatusOK = 200
StatusError = 500
)
// iota常量生成器
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)
// iota高级用法
const (
_ = iota // 忽略第一个值
KB = 1 << (10 * iota) // 1024
MB // 1048576
GB // 1073741824
TB // 1099511627776
)package main
var globalVar = "全局变量" // 包级别变量
func main() {
var localVar = "局部变量" // 函数级别变量
{
var blockVar = "块变量" // 块级别变量
fmt.Println(blockVar)
}
// fmt.Println(blockVar) // 错误!超出作用域
}7. 控制流程
// 基本if
if age > 18 {
fmt.Println("成年人")
}
// if-else
if age > 18 {
fmt.Println("成年人")
} else {
fmt.Println("未成年人")
}
// if-else if-else
if score >= 90 {
fmt.Println("优秀")
} else if score >= 80 {
fmt.Println("良好")
} else if score >= 60 {
fmt.Println("及格")
} else {
fmt.Println("不及格")
}
// if语句可以包含初始化语句
if err := doSomething(); err != nil {
fmt.Println("错误:", err)
}// 基本switch
switch day {
case 1:
fmt.Println("星期一")
case 2:
fmt.Println("星期二")
case 3:
fmt.Println("星期三")
default:
fmt.Println("其他")
}
// 多值匹配
switch day {
case 1, 2, 3, 4, 5:
fmt.Println("工作日")
case 6, 7:
fmt.Println("周末")
}
// 无表达式的switch(类似if-else)
switch {
case score >= 90:
fmt.Println("优秀")
case score >= 80:
fmt.Println("良好")
default:
fmt.Println("其他")
}
// fallthrough(继续执行下一个case)
switch day {
case 1:
fmt.Println("星期一")
fallthrough
case 2:
fmt.Println("星期二")
}// 传统for循环
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// 类似while循环
i := 0
for i < 10 {
fmt.Println(i)
i++
}
// 无限循环
for {
fmt.Println("无限循环")
break // 需要break退出
}
// range循环(遍历数组、切片、map等)
numbers := []int{1, 2, 3, 4, 5}
for index, value := range numbers {
fmt.Printf("索引:%d, 值:%d\n", index, value)
}
// 只要值
for _, value := range numbers {
fmt.Println(value)
}
// 只要索引
for index := range numbers {
fmt.Println(index)
}// break:跳出循环
for i := 0; i < 10; i++ {
if i == 5 {
break // 跳出循环
}
fmt.Println(i)
}
// continue:跳过本次循环
for i := 0; i < 10; i++ {
if i%2 == 0 {
continue // 跳过偶数
}
fmt.Println(i)
}
// 标签和break/continue
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if j == 1 {
break outer // 跳出外层循环
}
fmt.Println(i, j)
}
}8. 函数
// 基本函数
func add(a int, b int) int {
return a + b
}
// 参数类型简写
func add(a, b int) int {
return a + b
}
// 多返回值
func divide(a, b int) (int, error) {
if b == 0 {
return 0, fmt.Errorf("除数不能为0")
}
return a / b, nil
}
// 命名返回值
func calculate(a, b int) (sum int, product int) {
sum = a + b
product = a * b
return // 自动返回sum和product
}// 可变参数函数
func sum(numbers ...int) int {
total := 0
for _, num := range numbers {
total += num
}
return total
}
// 调用
result := sum(1, 2, 3, 4, 5) // 15
// 传递切片
numbers := []int{1, 2, 3}
result := sum(numbers...) // 使用...展开切片// 函数作为变量
var add = func(a, b int) int {
return a + b
}
result := add(10, 20)
// 函数作为参数
func calculate(a, b int, op func(int, int) int) int {
return op(a, b)
}
result := calculate(10, 20, add)// 匿名函数
func() {
fmt.Println("匿名函数")
}()
// 闭包
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
c := counter()
fmt.Println(c()) // 1
fmt.Println(c()) // 2
fmt.Println(c()) // 3// defer用于延迟执行,在函数返回前执行
func readFile() {
file, err := os.Open("file.txt")
if err != nil {
return
}
defer file.Close() // 函数返回前关闭文件
// 处理文件
}
// 多个defer按LIFO顺序执行
func test() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
}
// 输出:3, 2, 19. 数组和切片
// 数组声明
var arr1 [5]int // [0 0 0 0 0]
var arr2 [5]int = [5]int{1, 2, 3, 4, 5}
var arr3 = [5]int{1, 2, 3, 4, 5}
arr4 := [5]int{1, 2, 3, 4, 5}
// 自动推断长度
arr5 := [...]int{1, 2, 3, 4, 5}
// 指定索引初始化
arr6 := [5]int{1: 10, 3: 30} // [0 10 0 30 0]
// 访问元素
fmt.Println(arr2[0]) // 1
arr2[0] = 100
// 数组长度
fmt.Println(len(arr2)) // 5
// 遍历数组
for i := 0; i < len(arr2); i++ {
fmt.Println(arr2[i])
}
for index, value := range arr2 {
fmt.Printf("索引:%d, 值:%d\n", index, value)
}切片是动态数组,是Go中常用的数据结构。
// 切片声明
var s1 []int // nil切片
var s2 []int = []int{1, 2, 3} // 初始化切片
s3 := []int{1, 2, 3}
// 从数组创建切片
arr := [5]int{1, 2, 3, 4, 5}
s4 := arr[1:3] // [2 3],左闭右开
// 使用make创建切片
s5 := make([]int, 5) // 长度为5,容量为5
s6 := make([]int, 5, 10) // 长度为5,容量为10
// 切片操作
s := []int{1, 2, 3, 4, 5}
fmt.Println(s[0]) // 1
fmt.Println(s[1:3]) // [2 3]
fmt.Println(s[:3]) // [1 2 3]
fmt.Println(s[2:]) // [3 4 5]
fmt.Println(s[:]) // [1 2 3 4 5]
// 切片长度和容量
fmt.Println(len(s)) // 5
fmt.Println(cap(s)) // 5
// 追加元素
s = append(s, 6) // [1 2 3 4 5 6]
s = append(s, 7, 8, 9) // [1 2 3 4 5 6 7 8 9]
// 追加切片
s1 := []int{1, 2}
s2 := []int{3, 4}
s1 = append(s1, s2...) // [1 2 3 4]
// 复制切片
s3 := make([]int, len(s1))
copy(s3, s1)
// 删除元素(通过切片实现)
s := []int{1, 2, 3, 4, 5}
index := 2
s = append(s[:index], s[index+1:]...) // 删除索引2的元素// 切片是对数组的引用
arr := [5]int{1, 2, 3, 4, 5}
s1 := arr[1:4] // [2 3 4]
s2 := arr[2:5] // [3 4 5]
// s1和s2共享底层数组
s1[0] = 100
fmt.Println(arr) // [1 100 3 4 5]
fmt.Println(s2) // [3 4 5]10. Map映射
// Map声明
var m1 map[string]int // nil map
var m2 map[string]int = make(map[string]int)
m3 := make(map[string]int)
// Map初始化
m4 := map[string]int{
"apple": 5,
"banana": 3,
"orange": 2,
}
// 使用make指定容量
m5 := make(map[string]int, 10)m := make(map[string]int)
// 添加/更新元素
m["apple"] = 5
m["banana"] = 3
// 获取元素
value := m["apple"] // 5
// 检查键是否存在
value, exists := m["apple"]
if exists {
fmt.Println("存在,值:", value)
}
// 删除元素
delete(m, "apple")
// 获取Map长度
fmt.Println(len(m))
// 遍历Map
for key, value := range m {
fmt.Printf("键:%s, 值:%d\n", key, value)
}
// 只要键
for key := range m {
fmt.Println(key)
}
// 只要值
for _, value := range m {
fmt.Println(value)
}// Map是引用类型
m1 := map[string]int{"a": 1}
m2 := m1
m2["b"] = 2
fmt.Println(m1) // map[a:1 b:2]
// nil Map
var nilMap map[string]int
// nilMap["key"] = 1 // panic: assignment to entry in nil map
// 需要先初始化
nilMap = make(map[string]int)
nilMap["key"] = 111. 结构体
// 定义结构体
type Person struct {
Name string
Age int
City string
}
// 创建结构体实例
var p1 Person
p1.Name = "Alice"
p1.Age = 25
// 初始化结构体
p2 := Person{
Name: "Bob",
Age: 30,
City: "Beijing",
}
// 按顺序初始化
p3 := Person{"Charlie", 35, "Shanghai"}
// 部分初始化
p4 := Person{Name: "David"}type Rectangle struct {
Width float64
Height float64
}
// 值接收者方法
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
// 指针接收者方法
func (r *Rectangle) Scale(factor float64) {
r.Width *= factor
r.Height *= factor
}
// 使用
rect := Rectangle{Width: 10, Height: 5}
area := rect.Area() // 50
rect.Scale(2) // rect变为{20, 10}type Animal struct {
Name string
}
func (a Animal) Speak() {
fmt.Println(a.Name, "makes a sound")
}
type Dog struct {
Animal // 嵌入Animal
Breed string
}
// 使用
dog := Dog{
Animal: Animal{Name: "Buddy"},
Breed: "Golden Retriever",
}
dog.Speak() // Buddy makes a soundtype User struct {
ID int `json:"id" db:"user_id"`
Name string `json:"name" db:"user_name"`
Email string `json:"email" db:"user_email"`
}
// 使用反射读取标签
import "reflect"
t := reflect.TypeOf(User{})
field, _ := t.FieldByName("Name")
fmt.Println(field.Tag.Get("json")) // name12. 接口
// 接口定义
type Shape interface {
Area() float64
Perimeter() float64
}
// 实现接口(隐式实现)
type Rectangle struct {
Width float64
Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14159 * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * 3.14159 * c.Radius
}
// 使用接口
func printArea(s Shape) {
fmt.Println("面积:", s.Area())
}
rect := Rectangle{Width: 10, Height: 5}
circle := Circle{Radius: 5}
printArea(rect) // 面积: 50
printArea(circle) // 面积: 78.53975// 空接口可以表示任何类型
var i interface{}
i = 42
i = "hello"
i = []int{1, 2, 3}
// 类型断言
var i interface{} = "hello"
s := i.(string) // 类型断言
s, ok := i.(string) // 安全类型断言
if ok {
fmt.Println(s)
}
// 类型开关
switch v := i.(type) {
case int:
fmt.Println("整数:", v)
case string:
fmt.Println("字符串:", v)
default:
fmt.Println("其他类型")
}type Reader interface {
Read([]byte) (int, error)
}
type Writer interface {
Write([]byte) (int, error)
}
// 接口组合
type ReadWriter interface {
Reader
Writer
}13. 错误处理
import "errors"
// 创建错误
err := errors.New("这是一个错误")
// 格式化错误
err := fmt.Errorf("错误: %s", "详细信息")
// 错误检查
result, err := divide(10, 0)
if err != nil {
fmt.Println("错误:", err)
return
}type MyError struct {
Code int
Message string
}
func (e *MyError) Error() string {
return fmt.Sprintf("错误代码:%d, 消息:%s", e.Code, e.Message)
}
func doSomething() error {
return &MyError{Code: 500, Message: "操作失败"}
}// panic:程序异常终止
func test() {
panic("发生严重错误")
}
// recover:恢复panic
func safeCall() {
defer func() {
if r := recover(); r != nil {
fmt.Println("恢复panic:", r)
}
}()
panic("测试panic")
}14. 并发编程
Goroutine是Go的轻量级线程。
import (
"fmt"
"time"
)
// 启动goroutine
go func() {
fmt.Println("在goroutine中执行")
}()
// 带参数的goroutine
go func(name string) {
fmt.Println("Hello,", name)
}("Go")
// 等待goroutine完成
time.Sleep(time.Second)Channel用于goroutine间通信。
// 创建channel
ch := make(chan int)
// 发送数据
go func() {
ch <- 42
}()
// 接收数据
value := <-ch
fmt.Println(value) // 42
// 带缓冲的channel
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
// 关闭channel
close(ch)
// 遍历channel
for value := range ch {
fmt.Println(value)
}ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
ch1 <- "来自ch1"
}()
go func() {
time.Sleep(2 * time.Second)
ch2 <- "来自ch2"
}()
select {
case msg1 := <-ch1:
fmt.Println("收到:", msg1)
case msg2 := <-ch2:
fmt.Println("收到:", msg2)
case <-time.After(3 * time.Second):
fmt.Println("超时")
}import "sync"
// WaitGroup:等待goroutine完成
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Println("Goroutine", id)
}(i)
}
wg.Wait()
fmt.Println("所有goroutine完成")
// Mutex:互斥锁
var mu sync.Mutex
var counter int
for i := 0; i < 1000; i++ {
go func() {
mu.Lock()
counter++
mu.Unlock()
}()
}15. 包管理
# 初始化模块
go mod init myproject
# 添加依赖
go get github.com/gin-gonic/gin
# 更新依赖
go get -u github.com/gin-gonic/gin
# 整理依赖
go mod tidy
# 查看依赖
go list -m allmodule myproject
go 1.21
require (
github.com/gin-gonic/gin v1.9.1
)// mathutil/math.go
package mathutil
func Add(a, b int) int {
return a + b
}
func Multiply(a, b int) int {
return a * b
}
// main.go
package main
import "myproject/mathutil"
func main() {
sum := mathutil.Add(10, 20)
fmt.Println(sum)
}16. 文件操作
import (
"io/ioutil"
"os"
"bufio"
)
// 方式1:ioutil.ReadFile(简单)
content, err := ioutil.ReadFile("file.txt")
if err != nil {
fmt.Println("错误:", err)
return
}
fmt.Println(string(content))
// 方式2:os.Open + bufio(大文件)
file, err := os.Open("file.txt")
if err != nil {
fmt.Println("错误:", err)
return
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}// 方式1:ioutil.WriteFile
content := []byte("Hello, Go!")
err := ioutil.WriteFile("output.txt", content, 0644)
if err != nil {
fmt.Println("错误:", err)
}
// 方式2:os.Create + WriteString
file, err := os.Create("output.txt")
if err != nil {
fmt.Println("错误:", err)
return
}
defer file.Close()
file.WriteString("Hello, Go!")17. 网络编程
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}import (
"io/ioutil"
"net/http"
)
resp, err := http.Get("https://api.example.com/data")
if err != nil {
fmt.Println("错误:", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("错误:", err)
return
}
fmt.Println(string(body))18. 实际项目案例
package main
import (
"flag"
"fmt"
)
func main() {
name := flag.String("name", "World", "名称")
age := flag.Int("age", 0, "年龄")
flag.Parse()
fmt.Printf("Hello, %s! 年龄: %d\n", *name, *age)
}package main
import (
"encoding/json"
"net/http"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
func getUser(w http.ResponseWriter, r *http.Request) {
user := User{ID: 1, Name: "Alice"}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(user)
}
func main() {
http.HandleFunc("/user", getUser)
http.ListenAndServe(":8080", nil)
}19. 最佳实践与总结
代码风格
- 使用
go fmt格式化代码 - 遵循Go命名约定
- 使用有意义的变量名
- 使用
错误处理
- 总是检查错误
- 不要忽略错误
- 提供有意义的错误信息
并发编程
- 使用channel进行通信
- 避免共享内存
- 合理使用goroutine
性能优化
- 使用切片而不是数组
- 合理使用指针
- 避免不必要的内存分配
基础阶段:语法、数据类型、控制流程
进阶阶段:函数、结构体、接口
高级阶段:并发编程、包管理
实战阶段:项目开发、框架学习
- 官方文档:https://golang.org/doc/
- Go Tour:https://go.dev/tour/
- Effective Go:https://go.dev/doc/effective_go
- Go by Example:https://gobyexample.com/
Q: Go和Golang有什么区别?
A: Go是官方名称,Golang是社区常用名称,两者指同一门语言。
Q: Go适合做什么?
A: Go适合后端服务、微服务、云原生应用、网络编程等。
Q: Go的并发模型是什么?
A: Go使用CSP(Communicating Sequential Processes)模型,通过goroutine和channel实现。
Q: Go有垃圾回收吗?
A: 是的,Go有自动垃圾回收机制。
结语
恭喜你完成了Go语言入门教程的学习!Go是一门简洁、高效、强大的编程语言,特别适合现代软件开发。
通过本教程,你已经掌握了:
- ✅ Go语言基础语法
- ✅ 数据类型和变量
- ✅ 控制流程
- ✅ 函数和结构体
- ✅ 接口和错误处理
- ✅ 并发编程基础
- ✅ 包管理和文件操作
接下来,建议你:
- 多写代码练习,巩固基础知识
- 完成一些实际项目
- 深入学习Go的高级特性
- 关注Go社区,持续学习
记住:编程是一门实践性很强的技能,只有通过不断的练习和项目实践,才能真正掌握Go语言。
祝你学习愉快,编程顺利! 🚀
本教程由Java突击队学习社区编写,如有问题欢迎反馈。