1. 安装和配置Go环境
- 安装Go:访问Go官网下载对应操作系统的安装包,并按照指引完成安装。
- 配置环境变量:确保
GOPATH和GOROOT环境变量已正确设置。可在命令行中输入go version进行检查。 - 豆包MarsCode IDE:在豆包MarsCode中可以创建云上的虚拟环境,更快启动项目进行学习与测试。
2.Go程序基本框架
我们以Hello world为例子概述go程序的结构,首先导入一个包package main,package main 是一个包声明语句,用于表明当前 Go 源文件所属的包名。在 Go 语言里,代码是通过包(package)来组织和模块化管理的。所有的 Go 代码都必须属于某个包,包就像是代码的容器,把相关的类型、函数、变量等元素组织在一起,方便复用、维护以及代码的逻辑划分。
package main
import "fmt"
func main() {
fmt.Println("Hello world")
}
Go语言可以导入其他的 Go 包来使用它们提供的功能,同时其他包也可以被其他项目中的不同包复用。使用import关键字导入相关包,其中fmt包用于格式化输入输出,go应用程序的函数主体为func main,是程序的主入口即程序代码开始执行的地方,上面的示例程序会输出一行“Hello world”。
3.Go语言的编译和运行
-
使用
go build命令编译:- 这是最常用的编译方式。在命令行中,进入包含 Go 源文件(通常是
package main文件)的目录,然后执行go build命令。例如,如果你的 Go 源文件名为main.go,执行go build后,会在当前目录下生成一个可执行文件(在 Linux 和 macOS 下默认没有文件扩展名,在 Windows 下是.exe文件)。如果项目中有多个源文件,go build会自动查找并编译所有相关的文件。
- 这是最常用的编译方式。在命令行中,进入包含 Go 源文件(通常是
-
使用
go run命令编译并执行:- 当你只是想快速测试一段 Go 代码时,可以使用
go run命令。例如,go run main.go会先编译main.go文件(以及它所依赖的其他文件),然后立即执行生成的可执行文件。这种方式不会在当前目录下留下编译后的可执行文件,适合用于开发过程中的快速验证。
- 当你只是想快速测试一段 Go 代码时,可以使用
-
跨平台编译:
- Go 语言支持跨平台编译。通过设置环境变量
GOOS(目标操作系统)和GOARCH(目标架构),可以在一个平台上编译出用于其他平台的可执行文件。例如,要在 Linux 平台上编译一个用于 Windows 的可执行文件,可以执行GOOS = windows GOARCH = amd64 go build命令。
- Go 语言支持跨平台编译。通过设置环境变量
4.变量的声明与定义
var age int
var name string = "John"
var a,b,c int
var x,y,z = 1,"two",true
age := 25
a,b := 1,2
-
变量声明
-
单一变量声明:
- 在 Go 语言中,使用
var关键字来声明变量。例如,var age int声明了一个名为age的整数类型变量。此时变量被声明,但还没有初始化,它会被赋予该类型的零值。对于整数类型,零值是0。 - 也可以在声明变量的同时进行初始化,如
var name string = "John",这里声明了一个名为name的字符串变量,并初始化为"John"。
- 在 Go 语言中,使用
-
多个变量声明:
- 可以使用
var一次声明多个变量,变量之间用逗号隔开。例如,var a, b, c int声明了三个整数类型变量a、b和c,它们的初始值都是0。 - 也可以在声明多个变量时进行不同的初始化,如
var x, y, z = 1, "two", true,这里x被初始化为1(类型为整数),y被初始化为"two"(类型为字符串),z被初始化为true(类型为布尔值)。Go 语言会根据初始化的值自动推断变量的类型。
- 可以使用
-
-
变量定义(简短变量声明)
- Go 语言提供了简短变量声明的方式,使用
:=操作符。例如,age := 25,这里不仅声明了变量age,还同nil:在 Go 语言中,nil是一个特殊的值,用于表示指针、接口、映射(map)、切片(slice)和通道(channel)等类型的零值或未初始化状态。例如,对于指针类型,当声明一个指针变量但未对其赋值时,它的值为nil。这里,i := 0是初始化语句,用于初始化循环变量i;i < 5是条件表达式,只要这个条件为真,循环就会继续;i++是后置语句,在每次循环体执行完后执行,通常用于更新循环变量。这个循环会输出0到4。
- Go 语言提供了简短变量声明的方式,使用
for - range循环(用于遍历容器类型) :在Go语言中,for - range循环用于遍历数组、切片、字符串、映射(map)等容器类型。例如,遍历切片:
slice := []string{"apple", "banana", "cherry"}
for index, value := range slice {
println(index, value)
}
这里,index表示元素的索引(对于数组、切片等),value表示元素的值。在每次循环中,index和value会被更新为下一个元素的索引和值。对于映射,index表示键(key),value表示值。如果只需要值,可以使用for _, value := range slice的形式,其中_表示忽略索引。
- 分支结构
if - else语句
num :=9
if num < 0 {
fmt.Println(num, "is negative")
} else if num < 10 {
fmt.Println(num, "has 1 digit")
} else {
fmt.Println(num, "has multiple digits")
}
上述代码中首先声明并创建了一个整体变量num 并赋值为9,其不满足第一个if分支,往下检查发现满足if-else分支,那么就执行此代码块,如果不满足则执行else分支里面的代码块。
switch语句
switch语句用于多分支选择。基本形式为switch表达式 { case值1: 执行代码块1; case值2: 执行代码块2;... default: 执行代码块n }。例如:
day := 3
switch day {
case 1:
println("星期一")
case 2:
println("星期二")
case 3:
println("星期三")
//...
default:
println("其他")
}
当switch后面的表达式(这里是day)的值与某个case后面的值匹配时,就会执行对应的代码块。如果没有匹配的case,就会执行default代码块(default部分是可选的)。
6.数组,slice,映射MAP
数组
-
定义与初始化:
- 在 Go 语言中,数组是具有固定长度的同类型元素的序列。定义数组时需要指定元素类型和数组长度。例如,
var numbers [5]int定义了一个包含 5 个整数元素的数组,数组中的元素初始值为 0(因为int类型的零值是 0)。 - 也可以在定义数组时进行初始化,如
var fruits = [3]string{"apple", "banana", "cherry"},这里定义了一个长度为 3 的字符串数组,并初始化为三个水果名称。
- 在 Go 语言中,数组是具有固定长度的同类型元素的序列。定义数组时需要指定元素类型和数组长度。例如,
-
访问元素:
- 通过索引来访问数组中的元素,索引从 0 开始。例如,对于上面定义的
numbers数组,numbers[0]表示访问第一个元素,numbers[4]表示访问最后一个元素。可以对数组元素进行读取和赋值操作,如numbers[2] = 10,将数组中索引为 2 的元素赋值为 10。
- 通过索引来访问数组中的元素,索引从 0 开始。例如,对于上面定义的
-
数组的长度:
- 使用
len()函数来获取数组的长度。例如,对于fruits数组,len(fruits)会返回 3。数组的长度是其类型的一部分,这意味着[3]int和[5]int是不同的类型,不能直接相互赋值。
- 使用
-
数组的遍历:
- 可以使用
for循环来遍历数组。例如:
- 可以使用
for i := 0; i < len(numbers); i++ {
println(numbers[i])
}
也可以使用for - range循环来遍历数组,这种方式更加简洁,并且在不需要索引时可以忽略索引变量。例如:
for _, number := range numbers {
println(number)
}
切片(Slice)
-
定义与初始化:
- 切片是对数组的一个引用片段,它本身不存储数据,而是通过引用底层数组来提供数据访问。可以通过多种方式创建切片。例如,从数组创建切片:
numbers := [5]int{1, 2, 3, 4, 5},slice := numbers[1:4],这里slice是一个切片,它引用了numbers数组中索引从 1(包含)到 4(不包含)的元素,即{2, 3, 4}。 - 还可以使用
make函数来创建切片,如slice := make([]int, 3, 5),这创建了一个int类型的切片,长度为 3(即切片中当前有 3 个元素),容量为 5(切片底层数组的长度为 5,容量决定了切片可以扩展的最大长度)。
- 切片是对数组的一个引用片段,它本身不存储数据,而是通过引用底层数组来提供数据访问。可以通过多种方式创建切片。例如,从数组创建切片:
-
访问元素和修改元素:
- 切片元素的访问方式和数组类似,通过索引访问。例如,对于上面创建的
slice,slice[0]访问第一个元素。可以对切片元素进行修改,修改会反映到底层数组中。例如,slice[1] = 10会修改切片中的第二个元素,同时也会修改底层数组中对应的元素。
- 切片元素的访问方式和数组类似,通过索引访问。例如,对于上面创建的
-
切片的长度和容量:
- 切片的长度可以使用
len()函数获取,容量可以使用cap()函数获取。例如,对于slice := make([]int, 3, 5),len(slice)返回 3,cap(slice)返回 5。切片的长度小于等于容量,当切片长度小于容量时,可以通过append操作来添加新元素,直到切片长度达到容量。
- 切片的长度可以使用
-
切片的操作:
append操作:用于向切片添加新元素。例如,slice = append(slice, 6)会在切片末尾添加一个元素 6。如果切片的长度达到容量,append操作会自动分配一个更大的底层数组,并将原来的数据复制过去。copy操作:用于将一个切片中的元素复制到另一个切片中。例如,slice1 := []int{1, 2, 3},slice2 := make([]int, 3),copy(slice2, slice1)会将slice1中的元素复制到slice2中。- 切片的切片(子切片) :可以从一个切片中再创建子切片,方式和从数组创建切片类似。例如,
slice := []int{1, 2, 3, 4, 5},subSlice := slice[1:4],这里subSlice是slice的一个子切片,包含{2, 3, 4}。
映射(Map)
-
定义与初始化:
- 映射(在其他编程语言中也称为字典、哈希表等)是一种无序的键 - 值对(key - value)数据结构。在 Go 语言中,使用
map关键字来定义映射。例如,var ages map[string]int声明了一个映射,键是字符串类型,值是整数类型,但此时这个映射还没有初始化,它的值是nil,不能直接使用,需要使用make函数进行初始化,如ages = make(map[string]int)。 - 也可以在定义映射时进行初始化,如
students := map[string]int{"Alice": 20, "Bob": 22},这里创建了一个键为学生名字(字符串),值为学生年龄(整数)的映射,并初始化为两个学生的信息。
- 映射(在其他编程语言中也称为字典、哈希表等)是一种无序的键 - 值对(key - value)数据结构。在 Go 语言中,使用
-
访问和修改元素:
- 通过键来访问映射中的值。例如,对于
students映射,students["Alice"]可以获取Alice对应的年龄。如果键不存在,会返回值类型的零值。可以通过赋值来修改映射中的值,如students["Alice"] = 21,修改Alice对应的年龄为 21。
- 通过键来访问映射中的值。例如,对于
-
元素的插入和删除:
- 插入元素可以通过赋值操作实现,如
students["Charlie"] = 23,在students映射中插入一个新的学生Charlie的年龄信息。删除元素可以使用delete函数,如delete(students, "Bob"),会删除students映射中键为Bob的元素。
- 插入元素可以通过赋值操作实现,如
-
映射的遍历:
- 使用
for - range循环来遍历映射。例如:
- 使用
for key, value := range students {
println(key, value)
}
7.函数与返回值
- 函数定义 ◦ 在 Go 语言中,函数使用
func关键字来定义。函数定义的基本格式为func 函数名(参数列表) 返回值类型 { 函数体 }。例如,func add(num1, num2 int) int { return num1 + num2 }定义了一个名为add的函数,它接受两个整数参数num1和num2,并返回它们的和,返回值类型也是整数。 ◦ 函数名遵循 Go 语言的标识符命名规则,参数列表中的参数可以是不同类型的变量,多个参数之间用逗号隔开。如果函数没有参数,参数列表可以为空,如func printHello() { println("Hello") }。 - 返回值 在Go语言中,函数的返回值可以有多个,比如如下的例子
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
多个返回值的定义在函数名和形参后面的括号内进行声明即可,这时候调用者会获得多个返回值。