go语言快速入门,基础语法一学就会

  • “go”

  • “编程语言”
    tags:

  • go
    coverImage: “photo-1642367340318-96fdbc5d30f5-scaled.jpg”


Go 语言特点与优势

Go(又称 Golang)是 Google 于 2009 年推出的开源编程语言,由 Robert Griesemer、Rob Pike 和 Ken Thompson 设计。

核心特点

1. 简洁高效

  • 语法简洁,关键字仅 25 个

  • 编译速度极快,接近解释型语言的开发效率

  • 代码可读性强,易于维护

2. 原生并发支持

  • 内置 goroutine(轻量级线程)

  • channel 实现优雅的并发通信

  • 单机可轻松支持数万并发

3. 垃圾回收

  • 自动内存管理,无需手动释放

  • GC 性能持续优化,停顿时间极短

4. 静态类型 + 类型推断

  • 编译期类型检查,减少运行时错误

  • 支持类型推断,减少冗余代码

5. 丰富的标准库

  • 网络、HTTP、JSON、加密等开箱即用

  • 跨平台支持(Windows/Linux/macOS)

6. 部署简单

  • 编译生成单一可执行文件

  • 无需依赖外部运行时环境

  • 跨平台编译支持

应用场景

  • 云原生基础设施:Docker、Kubernetes、Etcd

  • 微服务架构:高性能 API 网关、RPC 服务

  • Web 后端:高并发 Web 应用

  • DevOps 工具:命令行工具、自动化脚本

  • 数据处理:日志分析、数据采集

与其他语言对比

特性 Go Java Python C++
性能 ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐⭐
并发支持 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐ ⭐⭐⭐
学习曲线 ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐
开发效率 ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐
部署难度 ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐ ⭐⭐

前言

Go语言以简洁、高效著称。本文从零开始,系统梳理 Go 核心语法,涵盖变量、类型、流程控制、函数等核心知识点,助你快速上手 Go 编程。


1. Hello World 与基础结构

第一个程序

  • 首先需要在go的官网上去下载安装包

下载完成之后选择自己想要安装的路径傻瓜式安装即可,下载完之后需添加环境变量,重启电脑之后在命令行终端运行

1
go version

这样go运行的基础环境就已经搭建好了 🌈

  • 市面上已经有很多较为成熟的go ide 这里我还是使用我们的老朋友vscode,配合golang的插件来编写我们的第一个go程序吧 🤗

打开vscode之后安装这两个插件即可

然后就可以打开一个文件夹,新建一个main.go的文件:

刚才的两个插件拥有极其强大的语法提示,在开始构建运行体时,只需要 ‘pk’就可以自动生成默认的执行体

现在我们就可以编写第一个go语言程序了

1
2
3
4
5
6
7
package main
<div></div>
import "fmt"
<div></div>
func main() {
fmt.Println("Hello, World!")
}
1
2
3
4
5
6
7
package main

import "fmt"

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

运行

1
go run ./main.go

关键点:

  • package main:可执行程序的入口包

  • import:导入标准库或第三方包

  • func main():程序执行起点

  • 语句结尾无需分号


2. 变量声明

2.1 标准声明

1
2
3
var name string = "张三"
var age int = 20
var isOk bool

2.2 批量声明

1
2
3
4
5
var (
username string = "李四"
age int = 25
isActive bool = true
)

2.3 类型推导

1
2
var name = "王五"  // 自动推断为 string
var age = 30 // 自动推断为 int

2.4 短变量声明(常用)

1
2
name := "赵六"
age := 28

注意: := 只能在函数内部使用,不能用于全局变量。

2.5 匿名变量

1
2
3
4
5
func getInfo() (int, string) {
return 10, "张三"
}
<div></div>
_, username := getInfo() // 使用 _ 忽略不需要的返回值
1
2
3
4
5
func getInfo() (int, string) {
return 10, "张三"
}

_, username := getInfo() // 使用 _ 忽略不需要的返回值

3. 常量声明

3.1 基本声明

1
2
const pi = 3.1415
const e = 2.7182

3.2 批量声明

1
2
3
4
const (
StatusOK = 200
StatusError = 500
)

3.3 iota 计数器

1
2
3
4
5
6
7
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
)
<div></div>
// iota在这里会进行累加和其他的语言的枚举相似
1
2
3
4
5
6
7
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
)

// iota在这里会进行累加和其他的语言的枚举相似

4. 基本数据类型

4.1 整型

类型 范围 说明
int8 -128 ~ 127 1字节
int16 -32768 ~ 32767 2字节
int32 -2^31 ~ 2^31-1 4字节
int64 -2^63 ~ 2^63-1 8字节
uint8 0 ~ 255 无符号1字节
int 平台相关 32位系统4字节,64位系统8字节
1
2
var age int = 25
var count int64 = 1000000

4.2 浮点型

1
2
var price float32 = 99.99
var pi float64 = 3.1415926535

默认类型: Go中浮点数默认为 float64

4.3 布尔型

1
2
var isActive bool = true
var isDeleted bool = false

注意: 布尔值不能与数值类型互相转换。

4.4 字符串

1
2
3
4
5
6
7
8
9
10
11
// 普通字符串
str1 := "Hello, Go!"
<div></div>
// 多行字符串(原始字符串)
str2 := `第一行
第二行
第三行`
<div></div>
// 字符串拼接
name := "张" + "三"
result := fmt.Sprintf("%s,年龄:%d", "李四", 25)
1
2
3
4
5
6
7
8
9
10
11
// 普通字符串
str1 := "Hello, Go!"

// 多行字符串(原始字符串)
str2 := `第一行
第二行
第三行`

// 字符串拼接
name := "张" + "三"
result := fmt.Sprintf("%s,年龄:%d", "李四", 25)

常用操作:

1
2
3
4
5
6
import "strings"
<div></div>
len("hello") // 5 - 长度
strings.Contains("hello", "ll") // true - 包含判断
strings.Split("a-b-c", "-") // ["a", "b", "c"] - 分割
strings.Join([]string{"a", "b"}, "-") // "a-b" - 拼接
1
2
3
4
5
6
import "strings"

len("hello") // 5 - 长度
strings.Contains("hello", "ll") // true - 包含判断
strings.Split("a-b-c", "-") // ["a", "b", "c"] - 分割
strings.Join([]string{"a", "b"}, "-") // "a-b" - 拼接

4.5 byte 和 rune

1
2
var b byte = &#x27;a&#x27;   // byte = uint8,表示ASCII字符
var r rune = &#x27;中&#x27; // rune = int32,表示Unicode字符

遍历字符串:

1
2
3
4
5
6
7
8
9
10
11
str := "hello中国"
<div></div>
// 按字节遍历
for i := 0; i < len(str); i++ {
fmt.Printf("%c ", str[i])
}
<div></div>
// 按字符遍历(推荐处理中文)
for _, char := range str {
fmt.Printf("%c ", char)
}
1
2
3
4
5
6
7
8
9
10
11
str := "hello中国"

// 按字节遍历
for i := 0; i < len(str); i++ {
fmt.Printf("%c ", str[i])
}

// 按字符遍历(推荐处理中文)
for _, char := range str {
fmt.Printf("%c ", char)
}

5. 类型转换

5.1 数值类型转换

1
2
3
var a int8 = 20
var b int16 = 40
var c = int16(a) + b // 必须显式转换

重要: Go没有隐式类型转换,必须显式转换。

5.2 转换为字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
import "strconv"
<div></div>
// int → string
str1 := strconv.Itoa(123)
<div></div>
// float → string
str2 := strconv.FormatFloat(3.14, &#x27;f&#x27;, 2, 64)
<div></div>
// bool → string
str3 := strconv.FormatBool(true)
<div></div>
// 使用 fmt.Sprintf
str4 := fmt.Sprintf("%d", 456)
1
2
3
4
5
6
7
8
9
10
11
12
13
import "strconv"

// int → string
str1 := strconv.Itoa(123)

// float → string
str2 := strconv.FormatFloat(3.14, &#x27;f&#x27;, 2, 64)

// bool → string
str3 := strconv.FormatBool(true)

// 使用 fmt.Sprintf
str4 := fmt.Sprintf("%d", 456)

5.3 字符串转数值

1
2
3
4
5
6
7
8
9
10
11
12
// string → int
num, _ := strconv.Atoi("123")
<div></div>
// string → int64
num64, _ := strconv.ParseInt("123", 10, 64)
// 10表示十进制, 64表示int64 即 8byte长整型, 也可以选用32
<div></div>
// string → float
floatNum, _ := strconv.ParseFloat("3.14", 64)
<div></div>
// string → bool
boolVal, _ := strconv.ParseBool("true")
1
2
3
4
5
6
7
8
9
10
11
12
// string → int
num, _ := strconv.Atoi("123")

// string → int64
num64, _ := strconv.ParseInt("123", 10, 64)
// 10表示十进制, 64表示int64 即 8byte长整型, 也可以选用32

// string → float
floatNum, _ := strconv.ParseFloat("3.14", 64)

// string → bool
boolVal, _ := strconv.ParseBool("true")

6. 运算符

6.1 算术运算符

1
2
3
4
5
6
+ - * / %
<div></div>
// 注意:Go没有 ++ -- 作为表达式
count := 10
count++ // 正确:独立语句
// x := count++ // 错误!
1
2
3
4
5
6
+ - * / %

// 注意:Go没有 ++ -- 作为表达式
count := 10
count++ // 正确:独立语句
// x := count++ // 错误!

6.2 关系运算符

1
2
3
4
5
== != > >= < <=
<div></div>
if age >= 18 {
fmt.Println("成年")
}
1
2
3
4
5
== != > >= < <=

if age >= 18 {
fmt.Println("成年")
}

6.3 逻辑运算符

1
2
3
4
5
&& || !
<div></div>
if age > 18 && age < 60 {
fmt.Println("工作年龄")
}
1
2
3
4
5
&& || !

if age > 18 && age < 60 {
fmt.Println("工作年龄")
}

6.4 赋值运算符

1
2
3
4
= += -= *= /= %=
<div></div>
x := 10
x += 5 // x = x + 5
1
2
3
4
= += -= *= /= %=

x := 10
x += 5 // x = x + 5

7. 流程控制

7.1 if-else

1
2
3
4
5
6
7
8
9
score := 85
<div></div>
if score >= 90 {
fmt.Println("优秀")
} else if score >= 60 {
fmt.Println("及格")
} else {
fmt.Println("不及格")
}
1
2
3
4
5
6
7
8
9
score := 85

if score >= 90 {
fmt.Println("优秀")
} else if score >= 60 {
fmt.Println("及格")
} else {
fmt.Println("不及格")
}

特殊写法(变量作用域限定):

1
2
3
4
5
6
if score := 56; score >= 90 {
fmt.Println("优秀")
} else {
fmt.Println("一般")
}
// score 在此处不可用, 这样可以减少作用域中的命名冗余

7.2 for 循环

基本形式:

1
2
3
for i := 0; i < 10; i++ {
fmt.Println(i)
}

类似 while:

1
2
3
4
5
i := 0
for i < 10 {
fmt.Println(i)
i++
}

无限循环:

1
2
3
4
5
for {
if condition {
break
}
}

7.3 for range(遍历)

1
2
3
4
5
6
7
8
9
str := "hello"
for index, char := range str {
fmt.Printf("%d: %cn", index, char)
}
<div></div>
// 只要值
for _, char := range str {
fmt.Printf("%c ", char)
}
1
2
3
4
5
6
7
8
9
str := "hello"
for index, char := range str {
fmt.Printf("%d: %cn", index, char)
}

// 只要值
for _, char := range str {
fmt.Printf("%c ", char)
}

7.4 switch

1
2
3
4
5
6
7
8
9
10
11
12
day := 3
<div></div>
switch day {
case 1:
fmt.Println("周一")
case 2:
fmt.Println("周二")
case 3, 4, 5:
fmt.Println("工作日")
default:
fmt.Println("周末")
}
1
2
3
4
5
6
7
8
9
10
11
12
day := 3

switch day {
case 1:
fmt.Println("周一")
case 2:
fmt.Println("周二")
case 3, 4, 5:
fmt.Println("工作日")
default:
fmt.Println("周末")
}

特点: Go的switch自动break,无需手动添加。

无表达式的switch:

1
2
3
4
5
6
7
8
9
10
age := 25
<div></div>
switch {
case age < 18:
fmt.Println("未成年")
case age >= 18 && age < 60:
fmt.Println("成年")
default:
fmt.Println("老年")
}
1
2
3
4
5
6
7
8
9
10
age := 25

switch {
case age < 18:
fmt.Println("未成年")
case age >= 18 && age < 60:
fmt.Println("成年")
default:
fmt.Println("老年")
}

7.5 break 和 continue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// break:跳出循环
for i := 0; i < 10; i++ {
if i == 5 {
break
}
}
<div></div>
// continue:跳过本次循环
for i := 0; i < 10; i++ {
if i%2 == 0 {
continue
}
fmt.Println(i) // 只打印奇数
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// break:跳出循环
for i := 0; i < 10; i++ {
if i == 5 {
break
}
}

// continue:跳过本次循环
for i := 0; i < 10; i++ {
if i%2 == 0 {
continue
}
fmt.Println(i) // 只打印奇数
}

带标签的跳转:

1
2
3
4
5
6
7
8
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if j == 2 {
break outer // 跳出外层循环
}
}
}

7.6 goto(慎用)

1
2
3
4
5
6
7
8
9
func main() {
i := 0
loop:
if i < 5 {
fmt.Println(i)
i++
goto loop
}
}

8. 函数(Function)

函数是 Go 程序的基本组成单元。Go 支持多返回值、命名返回值、可变参数等特性。

8.1 函数声明

基本语法:

1
2
3
func 函数名(参数列表) 返回值类型 {
函数体
}

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 无参数无返回值
func sayHello() {
fmt.Println("Hello")
}
<div></div>
// 有参数有返回值
func add(a int, b int) int {
return a + b
}
<div></div>
// 相同类型参数简写
func add(a, b int) int {
return a + b
}
<div></div>
// 多个返回值
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("除数不能为0")
}
return a / b, nil
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 无参数无返回值
func sayHello() {
fmt.Println("Hello")
}

// 有参数有返回值
func add(a int, b int) int {
return a + b
}

// 相同类型参数简写
func add(a, b int) int {
return a + b
}

// 多个返回值
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("除数不能为0")
}
return a / b, nil
}

8.2 多返回值

Go 函数可以返回多个值,常用于返回结果和错误信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func getUserInfo(id int) (string, int, error) {
if id <= 0 {
return "", 0, fmt.Errorf("无效的用户ID")
}
return "张三", 25, nil
}
<div></div>
// 使用
name, age, err := getUserInfo(1)
if err != nil {
fmt.Println("错误:", err)
return
}
fmt.Printf("用户: %s, 年龄: %dn", name, age)
<div></div>
// 忽略部分返回值
name, _, _ := getUserInfo(1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func getUserInfo(id int) (string, int, error) {
if id <= 0 {
return "", 0, fmt.Errorf("无效的用户ID")
}
return "张三", 25, nil
}

// 使用
name, age, err := getUserInfo(1)
if err != nil {
fmt.Println("错误:", err)
return
}
fmt.Printf("用户: %s, 年龄: %dn", name, age)

// 忽略部分返回值
name, _, _ := getUserInfo(1)

8.3 命名返回值

返回值可以预先命名,函数体内直接赋值,return 可省略返回值列表。

1
2
3
4
5
6
7
8
9
func calculate(a, b int) (sum int, diff int) {
sum = a + b
diff = a - b
return // 等价于 return sum, diff
}
<div></div>
// 使用
sum, diff := calculate(10, 5)
fmt.Println(sum, diff) // 15 5
1
2
3
4
5
6
7
8
9
func calculate(a, b int) (sum int, diff int) {
sum = a + b
diff = a - b
return // 等价于 return sum, diff
}

// 使用
sum, diff := calculate(10, 5)
fmt.Println(sum, diff) // 15 5

注意: 命名返回值会自动初始化为零值。

1
2
3
4
func test() (count int, name string, ok bool) {
// 未赋值时:count=0, name="", ok=false
return
}

8.4 可变参数

使用 ... 接收任意数量的同类型参数,可变参数在函数内部是切片。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 求和函数
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
<div></div>
// 使用
fmt.Println(sum(1, 2, 3)) // 6
fmt.Println(sum(1, 2, 3, 4, 5)) // 15
<div></div>
// 切片展开
numbers := []int{10, 20, 30}
fmt.Println(sum(numbers...)) // 60
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 求和函数
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}

// 使用
fmt.Println(sum(1, 2, 3)) // 6
fmt.Println(sum(1, 2, 3, 4, 5)) // 15

// 切片展开
numbers := []int{10, 20, 30}
fmt.Println(sum(numbers...)) // 60

混合参数:

1
2
3
4
5
6
7
8
9
func printInfo(prefix string, values ...int) {
fmt.Print(prefix, ": ")
for _, v := range values {
fmt.Print(v, " ")
}
fmt.Println()
}
<div></div>
printInfo("数字", 1, 2, 3, 4, 5) // 数字: 1 2 3 4 5
1
2
3
4
5
6
7
8
9
func printInfo(prefix string, values ...int) {
fmt.Print(prefix, ": ")
for _, v := range values {
fmt.Print(v, " ")
}
fmt.Println()
}

printInfo("数字", 1, 2, 3, 4, 5) // 数字: 1 2 3 4 5

注意: 可变参数必须是函数参数列表的最后一个。

8.5 匿名函数与闭包

匿名函数:

1
2
3
4
5
6
7
8
9
10
// 直接调用
func() {
fmt.Println("匿名函数")
}()
<div></div>
// 赋值给变量
add := func(a, b int) int {
return a + b
}
fmt.Println(add(3, 5)) // 8
1
2
3
4
5
6
7
8
9
10
// 直接调用
func() {
fmt.Println("匿名函数")
}()

// 赋值给变量
add := func(a, b int) int {
return a + b
}
fmt.Println(add(3, 5)) // 8

闭包(Closure):

闭包是引用了外部变量的匿名函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 计数器闭包
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
<div></div>
c1 := counter()
fmt.Println(c1()) // 1
fmt.Println(c1()) // 2
fmt.Println(c1()) // 3
<div></div>
c2 := counter() // 新的闭包实例
fmt.Println(c2()) // 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 计数器闭包
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}

c1 := counter()
fmt.Println(c1()) // 1
fmt.Println(c1()) // 2
fmt.Println(c1()) // 3

c2 := counter() // 新的闭包实例
fmt.Println(c2()) // 1

闭包的典型应用 - 函数工厂:

1
2
3
4
5
6
7
8
9
10
11
12
// 生成加法器
func adder(base int) func(int) int {
return func(x int) int {
return base + x
}
}
<div></div>
add10 := adder(10)
add100 := adder(100)
<div></div>
fmt.Println(add10(5)) // 15
fmt.Println(add100(5)) // 105
1
2
3
4
5
6
7
8
9
10
11
12
// 生成加法器
func adder(base int) func(int) int {
return func(x int) int {
return base + x
}
}

add10 := adder(10)
add100 := adder(100)

fmt.Println(add10(5)) // 15
fmt.Println(add100(5)) // 105

8.6 defer 延迟调用

defer 用于延迟函数调用,在函数返回前执行(常用于资源清理)。

基本用法:

1
2
3
4
5
6
7
8
9
10
11
func main() {
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("3")
fmt.Println("开始")
}
// 输出:
// 开始
// 3
// 2
// 1

执行顺序: defer 遵循 后进先出(LIFO) 原则。

典型应用 - 文件操作:

1
2
3
4
5
6
7
8
9
10
11
func readFile(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close() // 确保文件关闭

// 读取文件内容
// ...
return nil
}

典型应用 - 锁释放:

1
2
3
4
5
6
7
8
9
var mu sync.Mutex
<div></div>
func criticalSection() {
mu.Lock()
defer mu.Unlock() // 确保锁被释放

// 临界区代码
// ...
}
1
2
3
4
5
6
7
8
9
var mu sync.Mutex

func criticalSection() {
mu.Lock()
defer mu.Unlock() // 确保锁被释放

// 临界区代码
// ...
}

defer 与返回值:

1
2
3
4
5
6
7
8
func test() (result int) {
defer func() {
result++ // defer 可以修改命名返回值
}()
return 10
}
<div></div>
fmt.Println(test()) // 11
1
2
3
4
5
6
7
8
func test() (result int) {
defer func() {
result++ // defer 可以修改命名返回值
}()
return 10
}

fmt.Println(test()) // 11

8.7 函数作为参数(高阶函数)

函数可以作为参数传递给其他函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 定义函数类型
type operation func(int, int) int
<div></div>
// 接受函数作为参数
func calculate(a, b int, op operation) int {
return op(a, b)
}
<div></div>
// 使用
add := func(x, y int) int { return x + y }
multiply := func(x, y int) int { return x * y }
<div></div>
fmt.Println(calculate(5, 3, add)) // 8
fmt.Println(calculate(5, 3, multiply)) // 15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 定义函数类型
type operation func(int, int) int

// 接受函数作为参数
func calculate(a, b int, op operation) int {
return op(a, b)
}

// 使用
add := func(x, y int) int { return x + y }
multiply := func(x, y int) int { return x * y }

fmt.Println(calculate(5, 3, add)) // 8
fmt.Println(calculate(5, 3, multiply)) // 15

实用示例 - 过滤函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func filter(nums []int, test func(int) bool) []int {
result := []int{}
for _, num := range nums {
if test(num) {
result = append(result, num)
}
}
return result
}
<div></div>
// 筛选偶数
isEven := func(n int) bool { return n%2 == 0 }
nums := []int{1, 2, 3, 4, 5, 6}
fmt.Println(filter(nums, isEven)) // [2 4 6]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func filter(nums []int, test func(int) bool) []int {
result := []int{}
for _, num := range nums {
if test(num) {
result = append(result, num)
}
}
return result
}

// 筛选偶数
isEven := func(n int) bool { return n%2 == 0 }
nums := []int{1, 2, 3, 4, 5, 6}
fmt.Println(filter(nums, isEven)) // [2 4 6]

8.8 函数类型与方法

定义函数类型:

1
2
3
4
5
6
7
8
9
10
11
12
type Calculator func(int, int) int
<div></div>
func (c Calculator) Description() string {
return "这是一个计算器函数"
}
<div></div>
var add Calculator = func(a, b int) int {
return a + b
}
<div></div>
fmt.Println(add(1, 2)) // 3
fmt.Println(add.Description()) // 这是一个计算器函数
1
2
3
4
5
6
7
8
9
10
11
12
type Calculator func(int, int) int

func (c Calculator) Description() string {
return "这是一个计算器函数"
}

var add Calculator = func(a, b int) int {
return a + b
}

fmt.Println(add(1, 2)) // 3
fmt.Println(add.Description()) // 这是一个计算器函数

8.9 递归函数

函数可以调用自身实现递归。

示例1:阶乘

1
2
3
4
5
6
7
8
func factorial(n int) int {
if n <= 1 {
return 1
}
return n * factorial(n-1)
}
<div></div>
fmt.Println(factorial(5)) // 120
1
2
3
4
5
6
7
8
func factorial(n int) int {
if n <= 1 {
return 1
}
return n * factorial(n-1)
}

fmt.Println(factorial(5)) // 120

示例2:斐波那契数列

1
2
3
4
5
6
7
8
func fibonacci(n int) int {
if n <= 1 {
return n
}
return fibonacci(n-1) + fibonacci(n-2)
}
<div></div>
fmt.Println(fibonacci(7)) // 13
1
2
3
4
5
6
7
8
func fibonacci(n int) int {
if n <= 1 {
return n
}
return fibonacci(n-1) + fibonacci(n-2)
}

fmt.Println(fibonacci(7)) // 13

注意: 递归需要明确终止条件,避免无限递归导致栈溢出。

8.10 init 函数

init() 是特殊函数,在 main() 之前自动执行,用于初始化操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main
<div></div>
import "fmt"
<div></div>
var globalVar int
<div></div>
func init() {
fmt.Println("init 函数执行")
globalVar = 100
}
<div></div>
func main() {
fmt.Println("main 函数执行")
fmt.Println(globalVar) // 100
}
// 输出:
// init 函数执行
// main 函数执行
// 100
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import "fmt"

var globalVar int

func init() {
fmt.Println("init 函数执行")
globalVar = 100
}

func main() {
fmt.Println("main 函数执行")
fmt.Println(globalVar) // 100
}
// 输出:
// init 函数执行
// main 函数执行
// 100

特点:

  • 不能被显式调用

  • 一个包可以有多个 init() 函数

  • 执行顺序:常量 → 变量 → init()main()

8.11 函数练习

练习1:实现一个泛型 Max 函数(使用接口)

1
2
3
4
5
6
func max(a, b int) int {
if a > b {
return a
}
return b
}

练习2:实现 Map 高阶函数

1
2
3
4
5
6
7
8
9
10
11
12
func mapInt(nums []int, fn func(int) int) []int {
result := make([]int, len(nums))
for i, num := range nums {
result[i] = fn(num)
}
return result
}
<div></div>
// 使用
double := func(n int) int { return n * 2 }
nums := []int{1, 2, 3, 4, 5}
fmt.Println(mapInt(nums, double)) // [2 4 6 8 10]
1
2
3
4
5
6
7
8
9
10
11
12
func mapInt(nums []int, fn func(int) int) []int {
result := make([]int, len(nums))
for i, num := range nums {
result[i] = fn(num)
}
return result
}

// 使用
double := func(n int) int { return n * 2 }
nums := []int{1, 2, 3, 4, 5}
fmt.Println(mapInt(nums, double)) // [2 4 6 8 10]

练习3:实现带超时的重试函数

1
2
3
4
5
6
7
8
9
10
func retry(attempts int, fn func() error) error {
for i := 0; i < attempts; i++ {
err := fn()
if err == nil {
return nil
}
fmt.Printf("尝试 %d 失败: %vn", i+1, err)
}
return fmt.Errorf("超过最大重试次数")
}

9. fmt 包常用函数

8.1 Print 系列

1
2
3
fmt.Print("hello")      // 不换行
fmt.Println("world") // 换行
fmt.Printf("age=%d", 25) // 格式化输出

8.2 常用占位符

占位符 说明 示例
%v 默认格式 fmt.Printf(“%v”, 123)
%T 类型 fmt.Printf(“%T”, 123)
%d 十进制整数 fmt.Printf(“%d”, 123)
%f 浮点数 fmt.Printf(“%.2f”, 3.14)
%s 字符串 fmt.Printf(“%s”, “hello”)
%t 布尔值 fmt.Printf(“%t”, true)
%c 字符 fmt.Printf(“%c”, ‘A’)

10. 命名规则与代码风格

9.1 命名规则

  1. 组成: 字母、数字、下划线,首字符不能是数字

  2. 大小写敏感: ageAge 是不同变量

  3. 关键字禁用: 不能使用 foriffunc 等保留字

  4. 驼峰式命名: userNamegetUserInfo

  5. 见名知意: 变量用名词,函数用动词

可见性规则:

  • 大写字母开头: 公开(可导出)

  • 小写字母开头: 私有(包内可见)

1
2
var PublicVar = "可导出"  // 其他包可访问
var privateVar = "私有" // 仅包内可访问

9.2 代码风格

  1. 无需分号: 行尾不写 ;

  2. 左括号不换行:

1
2
3
4
5
6
7
8
9
10
// 正确
if x > 0 {
fmt.Println("positive")
}
<div></div>
// 错误
if x > 0
{
fmt.Println("positive")
}
1
2
3
4
5
6
7
8
9
10
// 正确
if x > 0 {
fmt.Println("positive")
}

// 错误
if x > 0
{
fmt.Println("positive")
}
  1. 可以使用这个指令实现快速格式化代码
1
go fmt main.go

11. 注释

1
2
3
4
5
6
// 单行注释
<div></div>
/*
多行注释
可以跨越多行
*/
1
2
3
4
5
6
// 单行注释

/*
多行注释
可以跨越多行
*/

快捷键: Win: Ctrl+/ | Mac: Cmd+/


12. 实战练习

综合练习1:用户管理系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main
<div></div>
import "fmt"
<div></div>
type User struct {
ID int
Name string
Age int
}
<div></div>
// 创建用户
func createUser(id int, name string, age int) User {
return User{ID: id, Name: name, Age: age}
}
<div></div>
// 验证用户年龄
func validateAge(age int) error {
if age < 0 || age > 150 {
return fmt.Errorf("年龄无效: %d", age)
}
return nil
}
<div></div>
// 打印用户信息
func printUser(u User) {
fmt.Printf("ID: %d, 姓名: %s, 年龄: %dn", u.ID, u.Name, u.Age)
}
<div></div>
func main() {
user := createUser(1, "张三", 25)
if err := validateAge(user.Age); err != nil {
fmt.Println("错误:", err)
return
}
printUser(user)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main

import "fmt"

type User struct {
ID int
Name string
Age int
}

// 创建用户
func createUser(id int, name string, age int) User {
return User{ID: id, Name: name, Age: age}
}

// 验证用户年龄
func validateAge(age int) error {
if age < 0 || age > 150 {
return fmt.Errorf("年龄无效: %d", age)
}
return nil
}

// 打印用户信息
func printUser(u User) {
fmt.Printf("ID: %d, 姓名: %s, 年龄: %dn", u.ID, u.Name, u.Age)
}

func main() {
user := createUser(1, "张三", 25)
if err := validateAge(user.Age); err != nil {
fmt.Println("错误:", err)
return
}
printUser(user)
}

综合练习2:简易计算器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
func calculator() {
var num1, num2 float64
var operator string

fmt.Print("请输入第一个数字: ")
fmt.Scan(&num1)

fmt.Print("请输入运算符 (+, -, *, /): ")
fmt.Scan(&operator)

fmt.Print("请输入第二个数字: ")
fmt.Scan(&num2)

switch operator {
case "+":
fmt.Printf("%.2f + %.2f = %.2fn", num1, num2, num1+num2)
case "-":
fmt.Printf("%.2f - %.2f = %.2fn", num1, num2, num1-num2)
case "*":
fmt.Printf("%.2f * %.2f = %.2fn", num1, num2, num1*num2)
case "/":
if num2 == 0 {
fmt.Println("错误:除数不能为0")
return
}
fmt.Printf("%.2f / %.2f = %.2fn", num1, num2, num1/num2)
default:
fmt.Println("无效的运算符")
}
}

练习5:九九乘法表

1
2
3
4
5
6
for i := 1; i <= 9; i++ {
for j := 1; j <= i; j++ {
fmt.Printf("%d×%d=%dt", i, j, i*j)
}
fmt.Println()
}

练习6:判断成绩等级

1
2
3
4
5
6
7
8
9
10
func getGrade(score int) string {
switch {
case score >= 90:
return "优秀"
case score >= 60:
return "及格"
default:
return "不及格"
}
}

13. 易错点总结

  1. 变量声明后必须使用,否则编译报错

  2. **:=** 只能在函数内使用

  3. 没有隐式类型转换,必须显式转换

  4. **++** **--** 只能作为独立语句

  5. Go 没有三元运算符

  6. switch 默认自动 break

  7. 左括号必须与语句在同一行


总结

Go语法简洁高效,核心要点:

  • 变量声明: 优先使用 :=

  • 类型转换: 必须显式转换

  • 流程控制: for 是唯一循环,switch 自动 break

  • 代码风格: 使用 go fmt 保持一致

  • 命名规范: 驼峰式,大写公开、小写私有

学习路径建议:

  1. 基础巩固:变量、类型、流程控制、函数(本文内容)

  2. 进阶特性:数组、切片、Map、结构体

  3. 面向对象:方法、接口、组合

  4. 并发编程:goroutine、channel、sync 包

  5. 标准库:io、net/http、database/sql

  6. 项目实战:Web 服务、RESTful API、微服务

推荐资源: