【Go语言快速上手】第一部分:Go 语言基础
文章目录
- 引言
- Go 语言的历史
- Go 语言的特点与优势
- 学习 Go 语言的意义
- 1. Go 语言基础
- 1.1 环境搭建
- 下载和安装 Go 语言 SDK
- 配置环境变量 (GOROOT, GOPATH)
- 选择合适的 IDE 或编辑器
- 1.2 Go 语言基本语法
- 变量声明与赋值
- 变量作用域和生命周期
- `var` vs `:=` (变量)
- 常量的定义与使用
- 总结
- 1.3 数据类型
- 基本类型
- 复合类型 与 控制流
- 1.3 面向对象编程
- 结构体和方法
- 结构体
- 方法接收者
- 值接收者
- 指针接收者
- 1.4 错误处理
- `error` 类型
- `panic` 和 `recover`
- 1.5 包管理
- `go mod` 管理依赖
- 导入和使用第三方包
引言
在当今快速发展的技术世界中,选择合适的编程语言对于开发者来说至关重要。Go 语言,自 2009 年由 Google 推出以来,凭借其简洁、高效和强大的并发处理能力,迅速在开发者社区中获得了广泛的认可和喜爱。Go 语言的设计哲学是“少即是多”,它摒弃了复杂的语法和冗余的特性,致力于提供一种简单而强大的编程体验。
Go 语言的历史
Go 语言的诞生源于 Google 对现有编程语言的不满。在 2000 年代初期,Google 面临着大规模分布式系统开发的挑战,而当时的主流语言(如 C++ 和 Java)在开发效率、编译速度和并发处理方面存在诸多不足。为了解决这些问题,Google 的三位资深工程师——Robert Griesemer、Rob Pike 和 Ken Thompson(Unix 和 C 语言的共同创始人)——于 2007 年开始设计一门新的编程语言,这就是 Go 语言的雏形。
2009 年,Go 语言正式对外发布,并迅速吸引了全球开发者的关注。它的设计目标是成为一种适合大规模系统开发的语言,同时保持简洁性和高效性。Go 语言的诞生不仅填补了编程语言领域的空白,也为现代软件开发带来了新的思路和工具。
Go 语言的特点与优势
- 简洁高效:Go 语言的语法清晰简洁,易于学习和使用。它的编译速度极快,执行效率高,使得开发过程更加流畅,产品迭代更加迅速。
- 并发编程:Go 语言内置了 goroutine 和 channel,使得并发编程变得简单而直观。开发者可以轻松地编写出高效的并发程序,充分利用多核处理器的计算能力。
- 垃圾回收:Go 语言拥有自动垃圾回收机制,有效管理内存,减少内存泄漏的风险,让开发者能够更专注于业务逻辑的实现。
- 丰富的标准库:Go 语言的标准库功能全面,涵盖了网络编程、加密解密、数据库操作等多个领域,为开发者提供了强大的支持。
学习 Go 语言的意义
- 云计算和微服务:随着云计算和微服务架构的普及,Go 语言因其出色的性能和简洁的并发模型,成为了构建云服务和微服务的理想选择。
- 新兴技术:在区块链和人工智能等新兴技术领域,Go 语言也展现出了其独特的优势,成为了开发这些前沿技术的热门语言。
- 职业发展:掌握 Go 语言不仅能够提升个人的技术竞争力,还能够为职业发展开辟更广阔的道路。无论是初创公司还是科技巨头,对 Go 语言开发者的需求都在不断增长。
1. Go 语言基础
1.1 环境搭建
首先,开始 Go 语言编程需要先完成环境的安装与配置。
Go 语言的安装和环境变量配置
下载和安装 Go 语言 SDK
- 访问 Go 官网 下载对应操作系统的安装包。(如果访问下载比较慢可以去下面的镜像站:阿里云 GO SDK)
- Windows 系统运行 .msi 安装包,Mac 用户使用 .pkg,Linux 系统可以通过 tar.gz 手动解压。
- 按照安装指南完成安装。
配置环境变量 (GOROOT, GOPATH)
- GOROOT: 指定 Go 语言的安装路径。
- GOPATH: 指定 Go 代码的工作目录,通常包含 src(源代码)、bin(可执行文件)和 pkg(编译缓存)。
这里建议,安装完go语言后,将其目录下的src(源代码)、bin(可执行文件)和 pkg(编译缓存),复制一份到代码工作目录,这个目录根据自己的需求写在哪里都行,如下图:
随后我们将项目代码也写到这个路径下。
之后,我们将其加到环境变量中:
之后我们在Goland中的设置中设置好GOROOT与GOPATH即可:
选择合适的 IDE 或编辑器
- GoLand(JetBrains 出品,强大的 Go 语言 IDE)
- VSCode + gopls 插件(轻量级开发体验)
- 命令行编辑器:vim + vim-go 插件
验证安装:
运行 go version 检查 Go 是否安装成功。
运行 go env 查看 Go 语言的环境配置。
1.2 Go 语言基本语法
变量和常量
变量声明与赋值
Go 语言支持显式类型声明和类型推导,下面的代码展示了GO中都有哪些声明方式,之后会详细讲解:
var name string = "Go" // 显式声明类型 age := 10 // 类型推导 const pi = 3.14 // 常量声明
- var 关键字用于显式声明变量类型。
- := 让 Go 语言自动推导变量类型(仅限于函数内部)。
- const 定义不可变的常量。
变量作用域和生命周期
- 局部变量:在函数或代码块内部声明,仅在该作用域内有效。
- 全局变量:在 package 级别声明,整个包都可以访问。
- 生命周期:局部变量随函数执行结束而销毁,全局变量存在整个程序运行期间。
示例:
package main import "fmt" var globalVar = "我是全局变量" // 在整个包范围内有效 func main() { localVar := "我是局部变量" // 仅在 main 函数内有效 fmt.Println(globalVar) fmt.Println(localVar) }
var vs := (变量)
var 关键字
var 是 Go 中声明变量的关键字,我们可以使用 var 声明一个或多个变量,并显式地指定变量类型。
1. 声明单个变量
var x int x = 10
2. 声明多个变量
var x, y int x = 10 y = 20
3. 声明并初始化变量
var x int = 10
4. 自动推导类型
var x = 10
:= 简短变量声明
:= 是 Go 语言中的简短变量声明形式。它用于函数内部,声明并初始化一个或多个变量。:= 不能用于函数外部(即只能在函数体内使用)。这种声明方式是 Go 语言的特色之一,可以简化代码。
// 单个变量的声明和初始化 x := 10 // 多个变量的声明和初始化 x, y := 10, "hello"
- := 会自动根据右侧的值推断类型,不需要显式声明类型。
- 在同一个作用域内,变量只能声明一次(即不能重复使用 := 声明同一个变量),如果变量已经声明过,则需要使用 = 来赋值。
常量的定义与使用
Go 语言中的常量使用 const 关键字定义,常量的值在编译时已经确定,不能改变。
常量定义
const Age int = 21 // 显式指定变量类型 const Pi = 3.14 const Greet = "Hello, Go!"
常量组
我们可以使用常量组来定义多个常量,常量组通常用于定义一系列相关的常量。
const ( x = 10 y = 20 z = 30 )
在常量组中,除了第一个常量外,后续常量会自动继承前一个变量的值。
如果我们想为某个常量赋一个新的值,可以显示的指定它。
常量的使用
常量可以像普通变量一样使用,但其值不能在运行时改变:
const maxLimit = 100 func checkLimit(value int) bool { if value > maxLimit { return false; } return true; }
常量在 Go 语言中的应用场景包括定义数值限制、状态标识、控制值等。
总结
- var 是 Go 中声明变量的标准方式,可以显式声明变量类型,也可以不声明类型让 Go 自动推断。
- := 是 Go 的简短变量声明方式,适用于函数内部,自动推断类型,并同时声明和初始化变量。
- const 用于定义常量,常量一旦定义就无法改变。常量组和显式类型声明提供了更灵活的方式来组织常量。
1.3 数据类型
Go 语言的数据类型包括基本类型和复合类型。
基本类型
1. 整数类型
Go 语言提供了多种整数类型,包括有符号和无符号整数。
- int:默认整数类型,大小取决于系统(32 位或 64 位)。
- int8:8 位有符号整数,范围 -128 到 127。
- int16:16 位有符号整数,范围 -32,768 到 32,767。
- int32:32 位有符号整数,范围 -2,147,483,648 到 2,147,483,647。
- int64:64 位有符号整数,范围 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807。
示例:
var a int = 42 var b int8 = 127 var c int16 = -32000 fmt.Println(a, b, c)
2. 无符号整数类型
无符号整数没有负数,仅用于存储非负整数。
- uint:默认无符号整数类型,大小取决于系统(32 位或 64 位)。
- uint8:8 位无符号整数,范围 0 到 255。
- uint16:16 位无符号整数,范围 0 到 65,535。
- uint32:32 位无符号整数,范围 0 到 4,294,967,295。
- uint64:64 位无符号整数,范围 0 到 18,446,744,073,709,551,615。
示例:
var d uint = 42 var e uint8 = 255 var f uint16 = 60000 fmt.Println(d, e, f)
3. 浮点数类型
Go 语言支持两种浮点类型:
- float32:32 位浮点数,精度较低。
- float64:64 位浮点数,精度较高。
示例:
var g float32 = 3.14 var h float64 = 2.1145141919810 fmt.Println(g, h)
4. 布尔类型
布尔类型 (bool) 只有两个值:true 和 false。
示例:
var i bool = true var j bool = false fmt.Println(i, j)
5. 字符串类型
字符串类型 (string) 用于存储 UTF-8 编码的文本。
示例:
var k string = "Hello, Golang" fmt.Println(k)
复合类型 与 控制流
【Go语言快速上手】第一部分:数据类型(数组、切片、映射)与控制语句
1.3 面向对象编程
结构体和方法
Go 语言没有传统的类和继承概念,但通过结构体(struct)和方法(method)可以实现面向对象的编程风格。结构体用于组合多个字段,而方法则是绑定到结构体上的函数。
结构体
结构体是 Go 中用于组合数据的复合类型,可以将多个不同类型的字段组合到一起。下面是定义和使用结构体的示例:
// 定义一个结构体 Person type Person struct { Name string Age int } func (p Person) SayHello() { fmt.Println("Hello, my name is", p.Name) } func main() { p := Person{Name: "李田所", Age: 24} p.SayHello() }
对于上面的示例代码,Person 是一个结构体,包含 Name 和 Age 两个字段。SayHello 是结构体的一个方法,用来打印出结构体中的 Name 字段。
方法接收者
方法接收者是定义方法时,决定该方法属于哪个类型的关键。Go 支持值接收者和指针接收者两种方式。
值接收者
值接收者是指方法接收的是该类型的副本,这意味着方法中修改的只是副本,而不会影响原对象。
// 使用值接收者定义一个方法 func (p Person) GetAge() int { return p.Age }
指针接收者
指针接收者是指方法接收的是类型的指针,这使得方法可以直接修改原对象的字段值。指针接收者更常用于需要修改接收者的情况。
// 定义结构体 Animal type Animal struct { Name string } // 使用指针接收者来修改 Name 字段 func (a *Animal) SetName(name string) { a.Name = name } // 使用指针接收者的方法 func main() { a := Animal{Name: "Dog"} a.SetName("Cat") fmt.Println(a.Name) // 输出 Cat }
对于上面的示例代码,SetName 使用了指针接收者 *Animal,使得方法可以修改结构体 Animal 的 Name 字段。
1.4 错误处理
error 类型
在 Go 中,错误是通过返回一个 error 类型来处理的。error 是一个内建的接口类型,定义了一个 Error() 方法。通过检查 error 的值,程序可以决定是否需要进一步处理。
以下是一个简单的示例,演示了如何使用 error 类型来处理除法中的除数为零的情况:
// divide 函数执行除法运算,返回一个整数和一个 error func divide(a, b int) (int, error) { if b == 0 { // 返回自定义错误 return 0, errors.New("除数不能为0") } return a / b, nil // 返回结果和 nil 错误 } func main() { result, err := divide(10, 0) if err != nil { fmt.Println("错误:", err) } else { fmt.Println("结果:", result) } }
对于上面的示例代码,当除数为零时,divide 函数返回一个错误。调用方可以检查返回的 error 值,并作出相应的错误处理。
panic 和 recover
Go 提供了 panic 和 recover 来处理运行时错误。panic 用于引发一个程序崩溃的事件,而 recover 用于捕获 panic 引发的崩溃并恢复程序执行。
- panic 用于发生致命错误时终止程序的执行。
- recover 用于从 panic 中恢复,并防止程序崩溃。
以下是一个简单的示例,演示了如何使用 panic 和 recover:
// 使用 defer 和 recover 来捕获 panic // 下面的代码写在函数内部 defer func() { if r := recover(); r != nil { fmt.Println("程序崩溃,恢复成功:", r) } }() // 发生 panic,程序会崩溃,但会被 recover 恢复 panic("发生错误!")
对于上面的示例代码,当程序执行到 panic("发生错误!") 时,panic 会引发程序崩溃,但由于在 defer 中使用了 recover,崩溃被捕获并恢复,程序继续执行。
1.5 包管理
go mod 管理依赖
Go 1.11 引入了模块支持,使用 go mod 命令来管理依赖和版本。通过 go mod,可以轻松初始化 Go 项目并管理外部依赖。
- 初始化 Go 模块:
go mod init myproject
- 安装第三方依赖包:
go get github.com/gin-gonic/gin
go mod 会在项目根目录生成 go.mod 文件,记录项目的依赖信息,便于版本控制和依赖管理。
导入和使用第三方包
一旦依赖被添加到 go.mod 文件中,可以通过 import 语句来导入和使用这些包。例如,使用 github.com/gin-gonic/gin 包来构建一个简单的 Web 应用:
import "github.com/gin-gonic/gin" func main() { r := gin.Default() r.GET("/", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "Hello, World!", }) }) r.Run() }
对于上面的示例代码,gin 包被导入并用来构建一个简单的 HTTP 路由。