百度百科中Go语言的介绍:
Go(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。Go 语言语法与 C 相近,但功能上有:内存安全,GC(垃圾回收),结构形态及 CSP-style 并发计算。
Go 语言出生名门,是由Google公司开发出来的。
Go(也被称为Golang)是一种开源的编程语言,由Google的Robert Griesemer、Rob Pike和Ken Thompson等人开发。Go的设计目标是提供简洁、高效、可靠的编程语言,适用于大规模软件开发。
Go语言的背景和起源可以追溯到2007年,当时Google内部的开发团队开始着手开发一门新的编程语言,旨在解决其他编程语言的一些问题,并提供更好的开发体验和性能。该项目最初被称为“20%项目”,因为开发人员在工作时间的20%用于开发该语言。
Go语言受到了C语言的影响,但也吸收了其他编程语言的一些思想,如并发模型来自CSP(通信顺序进程)和语法元素来自C和Pascal等。Go语言的设计注重简洁性、可读性和生产力,它摒弃了一些复杂的特性,注重提供清晰、直接的语法和强大的工具链。
Go语言于2009年正式对外发布,并逐渐在开发者社区中受到关注和采用。它的并发模型和轻量级线程(Goroutines)机制使得Go语言在处理高并发任务和网络编程方面具有优势。同时,Go语言还提供了良好的标准库和工具生态系统,以支持各种开发需求。
至今,Go语言已经成为一门受欢迎的编程语言,在Web开发、云计算、分布式系统、网络服务和系统编程等领域得到广泛应用。它的简洁性、性能和并发能力使其成为许多开发人员的首选语言之一。
总的来说,Go语言以其简洁性、并发性能、内存安全和跨平台支持等特点,成为一门受欢迎的编程语言,适用于构建高性能、可靠和可维护的软件系统。它在Web开发、云计算、大数据处理、网络服务和分布式系统等领域得到广泛应用,并被许多开发人员视为首选的编程语言之一。
1、打开Go官网:https://golang.google.cn/,点击Download
2、点击Microsoft Windows 开始下载Go的安装包,下面表示安装包的版本。
3、双击安装包开始安装,后面一直傻瓜式的 Next 就行了,其中有一步是安装目录,要是自己想改的话可以改一下。
1、打开资源管理器,右键此电脑,点击属性
2、往下滑找到高级系统设置进入到系统属性,点击环境变量
3、在系统变量中找到Path,双击Path打开,点击新建,将Go安装包中的bin目录复制上去(如D:\Go\bin
),
4、点击两次确定回到系统属性,点击应用,确定。
5、测试 Go 是否安装成功:win+R输入cmd打开黑窗口,输入命令go version
,输出跟下载的版本一样说明下载成功。
GOROOT和GOPATH都是环境变量,其中GOROOT是我们安装go开发包的路径,而从Go 1.8版本开始,Go开发包在安装完成后会为GOPATH设置一个默认目录,并且在Go1.14及之后的版本中启用了Go Module模式之后,不一定非要将代码写到GOPATH目录下,所以也就不需要我们再自己配置GOPATH了,使用默认的即可。
Go1.14版本之后,都推荐使用go mod模式来管理依赖环境了,也不再强制我们把代码必须写在GOPATH下面的src目录了,你可以在你电脑的任意位置编写go代码。(网上有些教程适用于1.11版本之前。)
默认GoPROXY配置是:GOPROXY=https://proxy.golang.org,direct
,由于国内访问不到https://proxy.golang.org
,所以我们需要换一个PROXY,这里推荐使用https://goproxy.io
或https://goproxy.cn
。
在黑窗口中可以执行下面的命令修改GOPROXY:
go env -w GOPROXY=https://goproxy.cn,direct
// 使用go env命令查看全部配置
Go语言有许多流行的集成开发环境(IDE)可供选择。可以到相应的官网进行下载使用。
Visual Studio Code(VS Code):VS Code是一个轻量级的跨平台代码编辑器,具有丰富的Go语言支持。通过安装Go相关的插件,如Go、Go Test、Go Doc等,可以获得语法高亮、代码自动完成、调试支持和其他实用功能。
GoLand:GoLand是由JetBrains开发的专门针对Go语言的集成开发环境。它提供了许多功能,如代码导航、智能代码补全、代码重构、调试和性能分析等,以提高开发效率。
LiteIDE:LiteIDE是一个简单且易于使用的Go语言IDE,特别适合那些喜欢简洁界面和快速上手的开发人员。它提供了基本的代码编辑和调试功能,并具有Go语言特定的功能,如代码自动补全和文档查看。
IntelliJ IDEA:IntelliJ IDEA是另一个由JetBrains开发的强大的多语言IDE,它也提供了Go语言的插件支持。它具有丰富的功能集,包括代码导航、代码重构、版本控制集成等。
Sublime Text:Sublime Text是一款轻量级的文本编辑器,也可以通过安装Go相关的插件来提供Go语言的支持。它具有快速启动和响应、强大的搜索和替换功能,以及丰富的插件生态系统。
在 Goland 中新建一个新的项目(go.mod文件自动生成),新建main.go文件,运行以下代码
package main //声明main包,表示当前程序是一个可执行程序
import "fmt" //导入内置 fmt 包
func main() { //main函数,程序的入口函数
fmt.Println("Hello World!") //在控制台打印 "Hello World"
}
Go的文件是以 .go
为扩展名存储在计算机当中,文件名由小写字母组成,如student.go
,如果文件名有多个单词组成,使用下划线_
对他们进行分隔,如student_test.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 var
标识符是用来命名变量、常量、函数、类型、结构体、接口和包等实体的名称,标识符由字母、数字和下划线组成,且必须以字母或下划线开头。
_
组成在Go语言中,变量是用来存储和操作数据的基本单元。在Go中,可以使用关键字var或短变量声明:=来声明变量。
Go 和许多编程语言不同,它在声明变量时将变量的类型放在变量的名称之后。
使用var关键字声明变量:
var name string
var age int
var isStudent bool
使用var关键字声明并初始化变量:
var name string = "John"
var age int = 25
var isStudent bool = true
使用短变量声明:=声明并初始化变量(仅在函数内部有效):
name := "John"
age := 25
isStudent := true
批量声明变量:
var (
name string = "John"
age int = 25
isStudent bool = true
)
在Go中,变量的类型可以显式指定,也可以根据初始化的值进行自动推断。对于显式类型声明的变量,可以省略类型名称,只保留类型。例如:
var name = "John" // 类型自动推断为 string
需要注意的是,通过var声明的变量必须使用相应的类型赋值,而短变量声明:=会根据右侧的值进行类型推断。
变量在使用之前必须先进行初始化,否则将使用其对应类型的零值。例如,int类型的零值为0,string类型的零值为空字符串 “”,bool类型的零值为false。
在Go语言中,变量的作用域可以是全局的(在函数之外声明)或局部的(在函数内部声明)。变量的作用域定义了变量的可见性和生命周期。
在Go中,未使用的变量会导致编译错误,如果不打算使用某个变量,可以使用下划线_
将其忽略
在Go语言中,常量是指在程序执行期间不可更改的值。常量使用关键字const进行声明,通常用于表示程序中的固定值,如数学常数、配置参数等。
声明变量
const pi = 3.14159
const appName = "MyApp"
声明多个变量
const (
statusOK = 200
statusNotFound = 404
)
显式指定常量类型
const size int64 = 1024
常量表达式
const (
secondsInMinute = 60
minutesInHour = 60
secondsInHour = secondsInMinute * minutesInHour
)
常量在声明时必须进行初始化,并且不能被重新赋值。它们在程序执行期间保持不变。常量的命名遵循与变量相同的命名规则。
在Go语言中,基本数据类型用于存储不同种类的数据。
布尔类型(bool):表示逻辑值,只能是true或false。
整数类型:
无符号整数类型:
浮点数类型:
复数类型:
字符串类型(string):表示一系列的字符,用双引号括起来。
字符类型(rune):表示一个Unicode字符的32位整数值。
错误类型(error):表示错误的接口类型。
在Go语言中,可以使用类型转换操作符将一个类型的值转换为另一个类型。类型转换可以在兼容的类型之间进行,例如数字类型之间的转换、字符串与字节切片之间的转换等。
类型转换的基本语法如下:
destinationType(expression)
其中,destinationType
是目标类型,expression
是要转换的表达式或变量。
将整数类型转换为浮点数类型:
var num int = 10
var floatNum float64 = float64(num)
将浮点数类型转换为整数类型(截断小数部分):
var floatNum float64 = 10.5
var num int = int(floatNum)
将整数类型转换为字符串类型:
var num int = 10
var str string = strconv.Itoa(num)
将字符串类型转换为整数类型:
var str string = "10"
var num int, err = strconv.Atoi(str)
类型转换可能导致数据丢失或溢出。例如,将一个大范围的整数转换为一个较小的整数类型时,可能会发生溢出。
类型转换只能在兼容的类型之间进行,否则会导致编译错误。例如,将字符串类型转换为布尔类型是不允许的。
在进行类型转换时,建议使用类型转换函数或方法,如float64()
、strconv.Itoa()
、strconv.Atoi()
等。
Go语言提供了一些常见的控制流程语句,包括条件语句、循环语句和分支语句。
条件语句(if-else):
if condition {
// 条件为真时执行的代码块
} else if condition2 {
// 第一个条件为假且第二个条件为真时执行的代码块
} else {
// 所有条件均为假时执行的代码块
}
选择语句(switch):
switch expression {
case value1:
// 表达式等于 value1 时执行的代码块
case value2:
// 表达式等于 value2 时执行的代码块
default:
// 所有情况均不匹配时执行的代码块
}
循环语句:
for
循环:
for initialization; condition; increment {
// 循环体
}
for
循环的简化形式:
for condition {
// 循环体
}
for
循环的无限循环形式:
for {
// 循环体
}
range
循环(用于遍历数组、切片、映射、通道等):
for index, value := range collection {
// 使用 index 和 value 进行迭代
}
跳转语句:
break
:终止当前循环或switch语句的执行。continue
:跳过当前循环的剩余代码,开始下一次循环迭代。goto
:将控制转移到标签所在的代码行。fallthrough
:在switch
语句中,继续执行下一个case
块的代码。在Go语言中,数组(Array)和切片(Slice)是用于存储和操作一组元素的数据结构。
数组(Array)是一个固定长度的数据结构,用于存储具有相同类型的元素。在Go中,数组的长度是在声明时指定的,并且在运行时不可更改。数组的声明方式为:
var arr [length]Type
其中,length
表示数组的长度,Type
表示数组元素的类型。以下是一个示例:
var arr [3]int
在数组中,可以通过索引来访问和修改元素的值,索引从0开始。例如,arr[0]
表示数组的第一个元素。
切片(Slice)是对数组的一种抽象,它提供了一种动态长度的、灵活的数据结构。切片是由一个指向数组的指针、长度和容量组成的,它可以自动扩展和收缩以适应数据的变化。切片的声明方式为:
var slice []Type
以下是一个示例:
var slice []int
切片可以通过数组或其他切片来初始化。例如,可以使用数组来初始化切片:
arr := [3]int{1, 2, 3}
slice := arr[:]
切片提供了一些方便的操作方法,如追加元素、截取片段、复制切片等。由于切片是对底层数组的引用,所以对切片的修改会影响到底层数组。切片的长度可以使用len()
函数获取,容量可以使用cap()
函数获取。
在Go语言中,函数(Function)是一种独立的代码块,用于执行特定的任务或操作。函数可以接收参数并返回一个或多个值。
函数声明的语法:
func functionName(parameter1 type1, parameter2 type2) returnType {
// 函数体
// 可以包含多条语句
return result
}
其中,functionName
是函数的名称,parameter1
和parameter2
是函数的参数,type1
和type2
是参数的类型,returnType
是函数返回值的类型,result
是函数返回的结果。
函数的声明和使用:
func add(a, b int) int {
return a + b
}
func main() {
result := add(3, 5)
fmt.Println(result) // 输出:8
}
函数可以有零个或多个参数,每个参数由参数名称和类型组成。当多个参数的类型相同时,可以省略类型,并将类型定义在最后一个参数之后。
函数可以返回一个或多个值。在函数体中,使用return
语句返回结果。如果函数没有返回值,则可以省略return
语句。
Go语言还支持多个返回值的函数,可以通过逗号分隔的方式指定多个返回值的类型。例如:
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
函数可以是程序中的独立代码块,也可以作为其他函数的参数和返回值。函数可以递归调用自身,以实现循环和复杂的算法。
在Go语言中,结构体(Struct)是一种用户定义的数据类型,用于封装一组相关的数据字段。结构体可以包含不同类型的字段,并且可以根据需要定义自定义的方法。
定义一个结构体的示例:
type Person struct {
Name string
Age int
Gender string
}
定义了一个名为Person
的结构体,它有三个字段:Name
、Age
和Gender
,分别表示人的姓名、年龄和性别。
结构体的字段可以通过点操作符.
来访问和修改。例如:
p := Person{Name: "Alice", Age: 25, Gender: "Female"}
fmt.Println(p.Name) // 输出:Alice
fmt.Println(p.Age) // 输出:25
fmt.Println(p.Gender) // 输出:Female
p.Age = 26
fmt.Println(p.Age) // 输出:26
方法(Method)是与结构体关联的函数,它可以通过结构体的实例调用。方法定义在结构体类型上,可以访问和操作该类型的字段。
给结构体定义方法的示例:
type Rectangle struct {
Width float64
Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func main() {
rect := Rectangle{Width: 3, Height: 4}
area := rect.Area()
fmt.Println(area) // 输出:12
}
给Rectangle
结构体定义了一个名为Area
的方法。方法的接收者(Receiver)是结构体类型Rectangle
,通过在方法名前加上接收者的类型,将方法与结构体关联起来。方法可以在结构体实例上被调用,这里调用了rect.Area()
来计算矩形的面积。
方法可以有接收者是值类型或指针类型,取决于是否需要修改接收者的值。如果接收者是指针类型,那么在方法内部对接收者的修改将影响原始结构体的值。
结构体和方法的结合使得可以创建自定义的数据类型,并在其上定义行为和操作。这提供了一种面向对象编程的方式,使代码更具可读性、可维护性和可扩展性。
在Go语言中,接口(Interface)是一种抽象类型,用于定义一组方法的集合。接口定义了一组方法的签名,而不包含实现细节。类型可以通过实现接口中定义的方法来满足接口的要求。
接口的声明语法如下:
type MyInterface interface {
Method1()
Method2()
// ...
}
定义了一个名为MyInterface
的接口,该接口包含了两个方法Method1
和Method2
。
要实现接口,需要在具体类型上定义相同的方法,以满足接口的要求。如果一个类型的方法集合与接口定义的方法一致,那么该类型被视为实现了该接口。
实现接口的示例:
type MyType struct {
// MyType 的字段
}
func (t MyType) Method1() {
// Method1 的实现
}
func (t MyType) Method2() {
// Method2 的实现
}
func main() {
var i MyInterface
i = MyType{} // MyType 实现了 MyInterface
i.Method1()
i.Method2()
}
定义了一个名为MyType
的结构体,并为其定义了Method1
和Method2
两个方法。由于MyType
的方法集合与MyInterface
定义的方法一致,因此可以将MyType
的实例赋值给MyInterface
类型的变量。
接口的实现是隐式的,不需要显式地声明实现了哪个接口。只要类型的方法集合与接口定义的方法匹配,就被视为实现了该接口。这种灵活性使得接口在多态性和代码复用方面非常有用。
一个类型可以同时实现多个接口,只需要满足各个接口的方法要求即可。通过接口的组合和嵌入,还可以创建更复杂的接口结构。
在使用接口时,通常通过接口类型来引用实现了该接口的具体类型。这种用法提供了一种通用的方式来操作和处理不同的具体类型,而无需关心具体的实现细节。
类型断言(Type Assertion)用于检查接口值的实际类型,并将其转换为对应的具体类型。在Go语言中,类型断言的语法为:
value, ok := interfaceValue.(Type)
其中,interfaceValue
是接口类型的值,Type
是具体的类型。如果类型断言成功,value
将获得被断言的值,而ok
将为true
;如果类型断言失败,value
将获得该类型的零值,而ok
将为false
。
使用类型断言的示例:
func processValue(value interface{}) {
if str, ok := value.(string); ok {
fmt.Println("String:", str)
} else if num, ok := value.(int); ok {
fmt.Println("Number:", num)
} else {
fmt.Println("Unknown type")
}
}
func main() {
processValue("Hello") // 输出:String: Hello
processValue(42) // 输出:Number: 42
processValue(true) // 输出:Unknown type
}
定义了一个processValue
函数,它接收一个空接口类型的值。在函数内部,使用类型断言检查值的实际类型,并根据类型执行不同的逻辑。
接口和类型断言是Go语言中实现多态性和灵活性的重要机制。通过接口,可以定义通用的行为和规范,而不关心具体的类型。通过类型断言,可以在需要时将接口值转换为具体的类型,以便进行特定的操作。
在Go语言中,并发编程是一种使用轻量级线程(Goroutine)和通信操作(Channel)来实现并发执行的编程模型。Go语言通过提供内置的并发原语,使得编写并发程序更加简单和高效。
Go语言中实现并发的主要特性和机制:
Goroutine(轻量级线程):Goroutine 是由 Go 运行时系统调度的独立执行的函数或方法。通过关键字go
,可以启动一个新的 Goroutine 来并发执行函数。
Channel(通道):Channel 是 Goroutine 之间进行通信和同步的机制。它可以在 Goroutine 之间传递数据,以及用于同步 Goroutine 的执行。通过通道,可以安全地进行数据共享和通信。
Select 语句:Select 语句用于处理多个通道的并发操作。它可以监听多个通道的发送和接收操作,并在其中任意一个通道就绪时执行相应的操作。
Mutex(互斥锁):Mutex 是一种互斥的锁机制,用于在多个 Goroutine 之间对共享资源进行访问控制。通过使用 Mutex,可以确保在任意时刻只有一个 Goroutine 可以访问共享资源。
WaitGroup(等待组):WaitGroup 是一种同步原语,用于等待一组 Goroutine 的完成。它可以阻塞主 Goroutine,直到所有的 Goroutine 完成任务。
通过结合以上的特性和机制,可以实现并发编程。例如,可以使用 Goroutine 和通道来并发执行任务,使用互斥锁来保护共享资源的访问,使用等待组来同步 Goroutine 的完成。
Go语言提供了简洁且强大的并发编程模型,使得编写高效且安全的并发程序变得相对容易。这种并发模型的设计使得开发人员能够充分利用多核处理器和异步操作,提高程序的性能和响应能力。
在Go语言中,包(Package)是组织和管理代码的基本单元。每个Go源代码文件都属于一个包,而包可以由多个文件组成。包提供了封装和代码重用的机制,同时也是导入的单位。
Go语言使用模块(Module)和包管理器来管理依赖关系和版本控制。以下是Go语言中的包管理和导入的相关概念和操作:
模块(Module):模块是Go语言中的版本化代码单元。一个模块是由一组相关的包构成的集合,这些包的版本是一致的。模块通常是一个代码库或一个应用程序。
go.mod 文件:go.mod 文件是模块的定义文件,用于描述模块的依赖关系和版本约束。它记录了模块的名称、版本号以及依赖的其他模块。
包导入路径:包导入路径是标识包的唯一字符串,通常以模块的根目录开始。例如,导入路径github.com/user/repo/pkg
指向名为pkg
的包。
包导入:使用import
关键字来导入其他包。导入的包可以通过包名访问其中的函数、变量和类型。
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
包别名:可以使用别名来为导入的包创建一个短的名称,以避免名称冲突或提高代码可读性。
import fm "fmt"
func main() {
fm.Println("Hello, World!")
}
包的可见性:Go语言中的包对外部代码的可见性是通过首字母大小写来控制的。以大写字母开头的标识符是可导出的,可以在其他包中访问;以小写字母开头的标识符是私有的,只能在包内部访问。
package main
import "fmt"
func main() {
fmt.Println("Hello, World!") // fmt.Println 是可导出的函数
}
go get 命令:go get 命令用于从远程代码库中获取并安装依赖的包。
go get github.com/user/repo
go mod 命令:go mod 命令用于管理模块和包的依赖关系。
go mod init
:初始化一个新的模块。go mod tidy
:整理模块的依赖关系并更新 go.mod 文件。go mod vendor
:将模块的依赖复制到项目的 vendor 目录下。包管理和导入是Go语言中重要的概念和操作,通过良好的包管理和导入实践,可以提
高代码的可维护性、可复用性和可测试性。通过模块和包的管理,可以管理依赖关系、版本控制和模块化开发,使得开发和维护大型项目更加便捷和高效。
在Go语言中,文件操作是一种常见的任务,用于读取和写入文件、创建和删除文件、文件重命名等操作。Go语言提供了丰富的标准库来支持文件操作。
常见的文件操作示例:
打开文件:
file, err := os.Open("file.txt")
if err != nil {
// 处理打开文件失败的错误
}
defer file.Close() // 在操作完成后关闭文件
读取文件内容:
data := make([]byte, 1024)
n, err := file.Read(data)
if err != nil && err != io.EOF {
// 处理读取文件失败的错误
}
content := string(data[:n]) // 将读取的数据转换为字符串
写入文件内容:
content := "Hello, World!"
_, err := file.WriteString(content)
if err != nil {
// 处理写入文件失败的错误
}
创建新文件:
newFile, err := os.Create("newfile.txt")
if err != nil {
// 处理创建文件失败的错误
}
defer newFile.Close()
删除文件:
err := os.Remove("file.txt")
if err != nil {
// 处理删除文件失败的错误
}
文件重命名:
err := os.Rename("oldname.txt", "newname.txt")
if err != nil {
// 处理重命名文件失败的错误
}
除了上述基本的文件操作,Go语言的标准库还提供了其他功能丰富的文件操作方法,例如文件拷贝、目录操作、文件权限设置等。开发人员可以根据具体的需求,选择适合的文件操作方法来处理文件相关的任务。
需要注意的是,在进行文件操作时,应该适当处理可能出现的错误,如文件打开失败、读写错误等。同时,为了确保文件在使用完毕后被正确关闭,可以使用 defer 关键字来延迟文件的关闭操作。