唤醒手腕 Go 语言基础语法知识点详细教程(基本简介、环境安装、基础知识)

1. Go语言简介

Go(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。Go 语言语法与 C 相近,但功能上有:内存安全,GC(垃圾回收),结构形态及 CSP-style 并发计算。

Go语言介绍、历史

Go是基于Inferno操作系统所开发的。Go于2009年11月正式宣布推出,成为开放源代码项目,并在Linux及Mac OS X平台上进行了实现,后来追加了Windows系统下的实现。在2016年,Go被软件评价公司TIOBE 选为“TIOBE 2016 年最佳语言”。

Go语言 vs C语言

Go的语法接近C语言,但对于变量的声明有所不同。Go支持垃圾回收功能。Go的并行模型是以东尼·霍尔的通信顺序进程(CSP)为基础,采取类似模型的其他语言包括Occam和Limbo,但它也具有Pi运算的特征,比如通道传输。

在1.8版本中开放插件(Plugin)的支持,这意味着现在能从Go中动态加载部分函数。

Go语言 vs C++语言

Go语言与C++相比,Go并不包括如枚举、异常处理、继承、泛型、断言、虚函数等功能,但增加了 切片(Slice) 型、并发、管道、垃圾回收、接口(Interface)等特性的语言级支持。

Go 2.0版本将支持泛型,对于断言的存在,则持负面态度,同时也为自己不提供类型继承来辩护。

Go语言 vs Java语言

不同于Java,Go内嵌了关联数组(也称为哈希表 Hashes 或字典 Dictionaries),就像字符串类型一样。

Go语言应用领域

服务器编程、开发云平台、区块链、分布式系统、网络编程

Go语言编译器

当前有两个Go编译器分支,分别为官方编译器gc和gccgo。官方编译器在初期使用C写成,后用Go重写从而实现自举。Gccgo是一个使用标准GCC作为后端的Go编译器。

官方编译器支持跨平台编译(但不支持CGO),允许将源代码编译为可在目标系统、架构上执行的二进制文件。

2. Go语言安装开发环境

下载安装并配置环境变量:下载地址:https://golang.google.cn/dl/

在这里插入图片描述

这里注意,安装路径选择一个比较好找的路径,例如:E:\Environment\go,其他安装都选择”下一步“即可。

配置 go 语言环境变量

安装完成后,把E:\Environment\go\bin目录添加到环境变量,这里就可以使用go了。

在这里插入图片描述

如果采用exe模式安装go语言的环境,是会自动配置环境变量的。

测试本地安装go版本

在命令行输入 go version 查看版本,输出结果如下所示。

C:\Users\HP>go version
go version go1.19.5 windows/amd64

go.exe 编译器 commands 命令参数

The commands are:

        bug         start a bug report
        build       compile packages and dependencies
        clean       remove object files and cached files
        doc         show documentation for package or symbol
        env         print Go environment information
        fix         update packages to use new APIs
        fmt         gofmt (reformat) package sources
        generate    generate Go files by processing source
        get         add dependencies to current module and install them
        install     compile and install packages and dependencies
        list        list packages or modules
        mod         module maintenance
        work        workspace maintenance
        run         compile and run Go program
        test        test packages
        tool        run specified go tool
        version     print Go version
        vet         report likely mistakes in packages

go 环境 env 配置

go env -json:将环境变量键值对以json形式进行展示

C:\Users\HP>go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\HP\AppData\Local\go-build
set GOENV=C:\Users\HP\AppData\Roaming\go\env
······

go 语言 env 变量

env 变量 变量说明
GO111MODULE module模式开启,在包管理那篇文章有提到
GOBIN 当我们使用go install命令编译和打包应用程序时,该命令会将编译后二进制程序打包GOBIN目录,一般我们将GOBIN设置为GOPATH下的bin目录
GOPATH 表示go的工作目录,这个目录指定了需要从哪个地方寻找GO的包、可执行程序等
GOCACHE go缓存目录,可以使用 go clean -cache 清空,如果目录变得很大的话
GOENV GO全局环境变量
GOMODCACHE go mod进行包管理时的缓存目录,一般为GOPATH下的pkg下的mod目录,在包管理那篇文章有提到
GOOS 当前操作系统
GOROOT Go语言的安装目录
GOPROXY 代理,在包管理那篇文章有提到
GOPRIVATE go get通过代理服务拉取私有仓库(企业内部module或托管站点上的private库),而代理服务不可能访问到私有仓库,会出现了404错误,于是go1.13后有了这个变量设置
GOTOOLDIR GO工具的安装目录,有cgo.exe等
GOVERSION go的版本号

配置 Proxy 代理配置(阿里)

由于国内的网络环境,我们可以通过配置GOPROXY避免DNS污染导致的模块拉取缓慢或失败的问题,加速你的构建。

# Windows
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/  
    
# macOS 或 Linux 
export GOPROXY=https://mirrors.aliyun.com/goproxy/

3. Goland开发者工具

开发者工具 Tool

链接:https://www.jetbrains.com/zh-cn/go/download/#section=windows

在这里插入图片描述
Goland 2023 Special Anniversary Edition

在这里插入图片描述

go 语言程序案例 hello world

package main

import "fmt"

func main() {
    
    
	fmt.Printf("hello world")
}

运行结果:

GOROOT=E:\Environment\go #gosetup
GOPATH=C:\Users\HP\go #gosetup
E:\Environment\go\bin\go.exe build -o C:\Users\HP\AppData\Local\Temp\GoLand\___go_build_main_go.exe C:\Users\HP\GolandProjects\awesomeProject\main.go #gosetup
C:\Users\HP\AppData\Local\Temp\GoLand\___go_build_main_go.exe
hello world
Process finished with the exit code 0

vscode 安装 go

Windows平台按下 Ctrl+Shift+P,我们在这个输入框中输入>go:install,下面会自动搜索相关命令,我们选择Go:Install/Update Tools这个命令,然后安装所有的依赖包。

安装需要一定的时间,安装完之后重启即可。

main.go:1:1: expected ‘package’, found ‘EOF’
解决方案:按 ctrl+s 保存即可,要在编辑文本 按ctr+s

Vscode 快捷键

在这里插入图片描述

4. Go语言新建项目

早期的go项目使用gopath来管理项目,不方便而且容易出错,从golang 1.11 开始使用gomod管理项目,当然还有第三方模块例如govendor

go mod init mypro

基本流程:1.创建项目 2.初始化项目 3.创建包 4.创建模块 5.相互调用

go mod init 初始化

PS C:\Users\HP\Desktop\字节跳动Go语言\basic_learn_go> go mod init mypro
go: creating new go.mod: module mypro
go: to add module requirements and sums:
        go mod tidy

Go 语言基本组成说明

属性 说明
包声明 编写源文件时,必须在非注释的第一行指明这个文件属于哪个包,如package main。
引入包 其实就是告诉Go 编译器这个程序需要使用的包,如import "fmt"其实就是引入了fmt包。
函数 和c语言相同,即是一个可以实现某一个功能的函数体,每一个可执行程序中必须拥有一个main函数。
变量 Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。
语句 / 表达式 在 Go 程序中,一行代表一个语句结束。每个语句不需要像 C 家族中的其它语言一样以分号 ; 结尾,因为这些工作都将由 Go 编译器自动完成。
注释 和c语言中的注释方式相同,可以在任何地方使用以 // 开头的单行注释。以 /* 开头,并以 */ 结尾来进行多行注释,且不可以嵌套使用,多行注释一般用于包的文档描述或注释成块的代码片段。

需要注意的是:标识符是用来命名变量、类型等程序实体。一个标识符实际上就是一个或是多个字母和数字、下划线_组成的序列,但是第一个字符必须是字母或下划线而不能是数字。

使用 build 生成可执行exe文件

go build ./main.go

5. Go语言变量、常量

声明变量的一般形式是使用 var 关键字,具体格式为:var identifier typename

如下的代码中我们定义了一个类型为int的变量。

package main
import "fmt"
func main() {
    
    
	var a int = 27
	fmt.Println(a);
} 

变量数据类型说明

在 Go 编程语言中,数据类型用于声明函数和变量。

数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存。具体分类如下:

类型 详解
布尔型 布尔型的值只可以是常量 true 或者 false。
数字类型 整型 int 和浮点型 float。Go 语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。
字符串类型 字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。
派生类型 指针类型(Pointer)、数组类型、结构化类型(struct)、Channel 类型、函数类型、切片类型、接口类型(interface)、Map 类型

在go语言中定义了一个变量,指定变量类型,如果没有初始化,则变量默认为零值。零值就是变量没有做初始化时系统默认设置的值。

数值类型 0、布尔类型 false、字符串 “”(空字符串)

变量没有指定类型

在go语言中如果没有指定变量类型,可以通过变量的初始值来判断变量类型。如下代码

package main
import "fmt"
func main() {
    
    
    var d = true
    fmt.Println(d)
}

可以同时声明多个类型相同的变量(非全局变量),如下图所示:

var x, y int
var c, d int = 1, 2
g, h := 123, "hello"

关于全局变量的声明

var ( vname1 v_type1 vname2 v_type2 )

具体举例如下:

var ( 
    a int
    b bool
)

匿名变量

匿名变量的特点是一个下画线_,这本身就是一个特殊的标识符,被称为空白标识符。它可以像其他标识符那样用于变量的声明或赋值(任何类型都可以赋值给它),但任何赋给这个标识符的值都将被抛弃,因此这些值不能在后续的代码中使用,也不可以使用这个标识符作为变量对其它变量进行赋值或运算。

使用匿名变量时,只需要在变量声明的地方使用下画线替换即可。

func GetData() (int, int) {
    
    
    return 10, 20
}
func main(){
    
    
    a, _ := GetData()
    _, b := GetData()
    fmt.Println(a, b)
}

iota常量

iota比较特殊,可以被认为是一个可被编译器修改的常量,它默认开始值是0,每调用一次加1。遇到const关键字时被重置为0。

Golang中没有枚举类型,不像Java或Python中有Enum类可以实现枚举,所以Golang通过 const来实现枚举。

变量作用域

作用域指的是已声明的标识符所表示的常量、类型、函数或者包在源代码中的作用范围,在此我们主要看一下go中变量的作用域,根据变量定义位置的不同,可以分为一下三个类型:

函数内定义的变量为局部变量,这种局部变量的作用域只在函数体内,函数的参数和返回值变量都属于局部变量。这种变量在存在于函数被调用时,销毁于函数调用结束后。

函数外定义的变量为全局变量,全局变量只需要在一个源文件中定义,就可以在所有源文件中使用,甚至可以使用import引入外部包来使用。全局变量声明必须以 var 关键字开头,如果想要在外部包中使用全局变量的首字母必须大写。

函数定义中的变量成为形式参数,定义函数时函数名后面括号中的变量叫做形式参数(简称形参)。形式参数只在函数调用时才会生效,函数调用结束后就会被销毁,在函数未被调用时,函数的形参并不占用实际的存储单元,也没有实际值。形式参数会作为函数的局部变量来使用。

Go语言基本的数据类型

在这里插入图片描述
以上就是go语言基本的数据类型,有了数据类型,我们就可以使用这些类型来定义变量,Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。

6. Go语言结构体

声明结构体

在声明结构体之前我们首先需要定义一个结构体类型,这需要使用type和struct,type用于设定结构体的名称,struct用于定义一个新的数据类型。具体结构如下:

type struct_variable_type struct {
    
    
   member definition
   member definition
   ...
   member definition
}

定义好了结构体类型,我们就可以使用该结构体声明这样一个结构体变量,语法如下:

variable_name := structure_variable_type {
    
    value1, value2...valuen}

variable_name := structure_variable_type {
    
     key1: value1, key2: value2..., keyn: valuen}

访问结构体成员

如果要访问结构体成员,需要使用点号 . 操作符,格式为:结构体变量名.成员名。举例代码如下:

package main

import "fmt"

type Books struct {
    
    
   title string
   author string
}

func main() {
    
    
	var book1 Books
	Book1.title = "Go 语言入门"
	Book1.author = "mars.hao"	
}

结构体指针

关于结构体指针的定义和申明同样可以套用前文中讲到的指针的相关定义,从而使用一个指针变量存放一个结构体变量的地址。

定义一个结构体变量的语法:var struct_pointer *Books

这种指针变量的初始化和上文指针部分的初始化方式相同struct_pointer = &Book1,但是和c语言中有所不同,使用结构体指针访问结构体成员仍然使用.操作符。格式如下:struct_pointer.title

7. Go语言循环处理语句

go中时使用for实现循环的,共有三种形式:

语法 说明
和c语言中的for相同 for init; condition; post {}
和c语言中的while相同 for condition{}
和c语言中的for(;;)相同 for{}

除此以外,for循环还可以直接使用range对slice、map、数组以及字符串等进行迭代循环,格式如下:

for key, value := range oldmap {
    
    
	newmap[key] = value
}

循环控制语句

控制语句 详解
break 中断跳出循环或者switch语句
continue 跳过当前循环的剩余语句,然后继续下一轮循环
goto语句 将控制转移到被标记的语句

goto语句主要是无条件转移到过程中指定的行。goto语句通常和条件语句配合使用,可用来实现条件转移、构成循环以及跳出循环体等功能。但是并不主张使用goto语句,以免造成程序流程混乱。

var a int = 0
LOOP: for a < 5 {
    
    
	if a == 2 {
    
    
		a = a + 1
		goto LOOP
	}
	fmt.Printf("%d\n", a)
	a++
}

代码中的LOOP就是一个标签,当运行到goto语句的时候,此时执行流就会跳转到LOOP标志的哪一行上。

8. Go语言关键词

Go语言type关键字(类型别名)

注意:本节内容涉及Go语言新版本的功能,内容上会涉及后续章节讲解的类型定义及结构体嵌入等特性。另外,本节内容适用于对Go语言很熟悉且正在关注工程升级、代码重构等问题的读者阅读。

类型别名是 Go 1.9 版本添加的新功能,主要用于解决代码升级、迁移中存在的类型兼容性问题。在 C/C++ 语言中,代码重构升级可以使用宏快速定义一段新的代码,Go语言中没有选择加入宏,而是解决了重构中最麻烦的类型名变更问题。

在 Go 1.9 版本之前定义内建类型的代码是这样写的:

type byte uint8
type rune int32

而在 Go 1.9 版本之后变为:

type byte = uint8
type rune = int32

9. Go语言特性

Go语言的特性有哪些?

Go语言也称为 Golang,是由 Google 公司开发的一种静态强类型、编译型、并发型、并具有垃圾回收功能的编程语言。

接下来从几个方面来具体介绍一下Go语言的特性。

语法简单

抛开语法样式不谈,单就类型和规则而言,Go 与 C99、C11 相似之处颇多,这也是Go语言被冠以“NextC”名号的重要原因。

Go语言的语法处于简单和复杂的两极。C语言简单到你每写下一行代码,都能在脑中想象出编译后的模样,指令如何执行,内存如何分配,等等。而 C 的复杂在于,它有太多隐晦而不着边际的规则,着实让人头疼。相比较而言,Go 从零开始,没有历史包袱,在汲取众多经验教训后,可从头规划一个规则严谨、条理简单的世界。

Go语言的语法规则严谨,没有歧义,更没什么黑魔法变异用法。任何人写出的代码都基本一致,这使得Go语言简单易学。放弃部分“灵活”和“自由”,换来更好的维护性,我觉得是值得的。

将“++”、“–”从运算符降级为语句,保留指针,但默认阻止指针运算,带来的好处是显而易见的。还有,将切片和字典作为内置类型,从运行时的层面进行优化,这也算是一种“简单”。

并发模型

时至今日,并发编程已成为程序员的基本技能,在各个技术社区都能看到诸多与之相关的讨论主题。在这种情况下Go语言却一反常态做了件极大胆的事,从根本上将一切都并发化,运行时用 Goroutine 运行所有的一切,包括 main.main 入口函数。

可以说,Goroutine 是 Go 最显著的特征。它用类协程的方式来处理并发单元,却又在运行时层面做了更深度的优化处理。这使得语法上的并发编程变得极为容易,无须处理回调,无须关注线程切换,仅一个关键字,简单而自然。

搭配 channel,实现 CSP 模型。将并发单元间的数据耦合拆解开来,各司其职,这对所有纠结于内存共享、锁粒度的开发人员都是一个可期盼的解脱。若说有所不足,那就是应该有个更大的计划,将通信从进程内拓展到进程外,实现真正意义上的分布式。

内存分配

将一切并发化固然是好,但带来的问题同样很多。如何实现高并发下的内存分配和管理就是个难题。好在 Go 选择了 tcmalloc,它本就是为并发而设计的高性能内存分配组件。

可以说,内存分配器是运行时三大组件里变化最少的部分。刨去因配合垃圾回收器而修改的内容,内存分配器完整保留了 tcmalloc 的原始架构。使用 cache 为当前执行线程提供无锁分配,多个 central 在不同线程间平衡内存单元复用。在更高层次里,heap 则管理着大块内存,用以切分成不同等级的复用内存块。快速分配和二级内存平衡机制,让内存分配器能优秀地完成高压力下的内存管理任务。

在最近几个版本中,编译器优化卓有成效。它会竭力将对象分配在栈上,以降低垃圾回收压力,减少管理消耗,提升执行性能。可以说,除偶尔因性能问题而被迫采用对象池和自主内存管理外,我们基本无须参与内存管理操作。

垃圾回收

垃圾回收一直是个难题。早年间,Java 就因垃圾回收低效被嘲笑了许久,后来 Sun 连续收纳了好多人和技术才发展到今天。可即便如此,在 Hadoop 等大内存应用场景下,垃圾回收依旧捉襟见肘、步履维艰。

相比 Java,Go 面临的困难要更多。因指针的存在,所以回收内存不能做收缩处理。幸好,指针运算被阻止,否则要做到精确回收都难。

每次升级,垃圾回收器必然是核心组件里修改最多的部分。从并发清理,到降低 STW 时间,直到 Go 的 1.5 版本实现并发标记,逐步引入三色标记和写屏障等等,都是为了能让垃圾回收在不影响用户逻辑的情况下更好地工作。尽管有了努力,当前版本的垃圾回收算法也只能说堪用,离好用尚有不少距离。

静态链接

Go 刚发布时,静态链接被当作优点宣传。只须编译后的一个可执行文件,无须附加任何东西就能部署。这似乎很不错,只是后来风气变了。连着几个版本,编译器都在完善动态库 buildmode 功能,场面一时变得有些尴尬。

暂不说未完工的 buildmode 模式,静态编译的好处显而易见。将运行时、依赖库直接打包到可执行文件内部,简化了部署和发布操作,无须事先安装运行环境和下载诸多第三方库。这种简单方式对于编写系统软件有着极大好处,因为库依赖一直都是个麻烦。

标准库

功能完善、质量可靠的标准库为编程语言提供了充足动力。在不借助第三方扩展的情况下,就可完成大部分基础功能开发,这大大降低了学习和使用成本。最关键的是,标准库有升级和修复保障,还能从运行时获得深层次优化的便利,这是第三方库所不具备的。

Go 标准库虽称不得完全覆盖,但也算极为丰富。其中值得称道的是 net/http,仅须简单几条语句就能实现一个高性能 Web Server,这从来都是宣传的亮点。更何况大批基于此的优秀第三方 Framework 更是将 Go 推到 Web/Microservice 开发标准之一的位置。

当然,优秀第三方资源也是语言生态圈的重要组成部分。近年来崛起的几门语言中,Go 算是独树一帜,大批优秀作品频繁涌现,这也给我们学习 Go 提供了很好的参照。

工具链

完整的工具链对于日常开发极为重要。Go 在此做得相当不错,无论是编译、格式化、错误检查、帮助文档,还是第三方包下载、更新都有对应的工具。其功能未必完善,但起码算得上简单易用。

内置完整测试框架,其中包括单元测试、性能测试、代码覆盖率、数据竞争,以及用来调优的 pprof,这些都是保障代码能正确而稳定运行的必备利器。

除此之外,还可通过环境变量输出运行时监控信息,尤其是垃圾回收和并发调度跟踪,可进一步帮助我们改进算法,获得更佳的运行期表现。

10. Go语言map类型

map以模板(泛型)方式实现,可以存储任意类型的数据,包括使用者自定义的数据类型。

Map主要用于资料一对一映射(one-to-one)的情況,map內部的实现自建一颗红黑树,这颗树具有对数据自动排序的功能。在map内部所有的数据都是有序的,后边我们会见识到有序的好处。比如一个班级中,每个学生的学号跟他的姓名就存在著一对一映射的关系。

11. Go语言导包

有时,你的代码需要当前程序的基础上增加更多的功能。在这些情况下,你可以使用软件包来丰富你的程序。在 Go 中, 一个包表示磁盘上单个目录中的所有文件。包可以定义可以在其他 Go 文件或包中引用的函数、类型和接口。

本教程将带你来完成软件包的安装, 导入和重命名。

在这里插入图片描述

标准库包

标准库是 Go 附带的一组软件包。这些软件包包含许多用于编写现代软件的基本模块。例如, fmt 软件包包含用于格式和打印字符串的基本功能。 net/http 软件包包含允许开发人员创建 Web 服务,通过HTTP 协议发送和检索数据的功能,等等。

为了利用软件包中的功能,你需要使用 import 语句访问软件包。import 语句由 import 关键字以及软件包的名称组成。

例如,在 GO 程序中 random.go 文件。你可以导入 math/rand 包来生成随机数:

import "math/rand"

当我们导入一个包时,我们把它在当前程序中作为一个单独 namespace 命名空间来使用。这意味着我们必须像 package.function 调用其中的函数。

实际上,math/rand 软件包的功能看起来像这些示例:

rand.Int() 
// 调用函数返回随机整数。
rand.Intn()
//调用函数将随机元素从 0 返回到所提供的指定数字。

安装软件包

虽然标准库包含了许多出色且有用的软件包,但它们的设计是通用的,本质上不是特定的。这使开发者可以根据自己的特定需求在标准库之上构建自己的软件包。

GO 工具链带有 go get 命令。此命令使你可以将第三方软件包安装到本地开发环境中,并且将这些软件包应用到你的程序中。

使用 go get 来安装第三方软件包时,通常可以通过其规范路径引用软件包。这个路径也可能是通往公共项目的途径,该项目托管在诸如 GitHub 之类的代码存储库中。

因此,如果要导入 flect 软件包,则将使用完整的规范路径:

go get github.com/gobuffalo/flect

在这种情况下,使用 go get 工具将在 GitHub 上找到软件包,并将其安装到你的 [Gopath]

更新包 -u update

原始作者通常会更新软件包,以解决 bug 或添加新功能。发生这种情况时,你可能需要使用该软件包的最新版本来利用新功能或已解决的 bug。要更新软件包,你可以使用 go get 命令使用 -u 标志:

go get -u github.com/gobuffalo/flect

如果在本地找不到该软件包,此命令也将安装该软件包。如果已经安装了它,Go 将尝试将软件包更新为最新版本。

go get 命令始终检索可用的包装的最新版本。但是,可能还会对该软件包的之前的版本进行更新,这些版本仍然比你使用的更新,并且对你的程序中的更新非常有用。要检索包装的特定版本,你需要使用一个软件包管理工具,例如Go Modules。

从 GO 1.11 开始,使用 Go Modules 来管理要导入的软件包的哪个版本。软件包管理的主题超出了本文的范围,但是你可以在on the Go Modules GitHub page:https://github.com/golang/go/wiki/Modules上阅读有关它的。

使用包别名

在此示例中,在 random.go 程序文件中修改 fmt 软件包的名称。我们将 fmt 的包名称更改为 f,以缩写它。我们的修改程序看起来像这样:

random.go

package main

import (
 f "fmt"
  "math/rand"
)

func main() {
    
    
  for i := 0; i < 10; i++ {
    
    
    f.Printf("%d) %d\n", i, rand.Intn(25))
  }
}

在程序中,我们现在将 Printf 函数称为 f.Printf,而不是 fmt.Printf

init()函数介绍

在Go语言程序执行时导入包语句会自动触发包内部init()函数的调用。需要注意的是: init()函数没有参数也没有返回值。 init()函数在程序运行时自动被调用执行,不能在代码中主动调用它。

init()函数执行顺序

Go语言包会从main包开始检查其导入的所有包,每个包中又可能导入了其他的包。Go编译器由此构建出一个树状的包引用关系,再根据引用顺序决定编译顺序,依次编译这些包的代码。

在运行时,被最后导入的包会最先初始化并调用其init()函数, 如下图示:
在这里插入图片描述

12. Go语言mod

Go mod 是 Go 1.11 提出的开发包管理工具,在此之前go发布过许多包管理方案,但都强依赖于环境变量GOPATH,存在诸多缺点,不易于项目管理。

Go 之于 mod ,好比 Java 之于 maven 、 Js 之于 npm 。

它的出现使得Go语言项目脱离了对GOPATH的强依赖,为Go语言后期快速成长提供了强有力的保障。

Go mod provides access to operations on modules.

Note that support for modules is built into all the go commands,
not just 'go mod'. For example, day-to-day adding, removing, upgrading,
and downgrading of dependencies should be done using 'go get'.
See 'go help modules' for an overview of module functionality.

Usage:

        go mod <command> [arguments]

The commands are:

        download    download modules to local cache
        edit        edit go.mod from tools or scripts
        graph       print module requirement graph
        init        initialize new module in current directory
        tidy        add missing and remove unused modules
        vendor      make vendored copy of dependencies
        verify      verify dependencies have expected content
        why         explain why packages or modules are needed

Use "go help mod <command>" for more information about a command.

开启 GO111MODULE

GO111MODULE 是 go 开启 mod 包管理工具的一个环境配置,共有三个配置项,分别是 off 、on 、auto 。开启mod包管理模式,可以使用选项 on 或 auto。

go env -w  GO111MODULE=auto

13. Go 语言运算符

位运算符

位运算符是对数据转换为二进制后某个位上的数进行的运算,各个语言中都有位运算符,Golang也不例外,由于位运算符的执行效率比较高,在实际开发过程中也都有使用,Golang的位运算符相较于C/C++貌似“少了”一种操作,这里的少了并不是真正的少了,而是非这个操作不再使用单独的位运算符。

在这里插入图片描述
关系运算符

关系运算的结果都是bool型,要么是true,要么是false,关系表达式经常用在if结构的条件中或循环结构的条件中。

在这里插入图片描述
逻辑运算符

在这里插入图片描述

指针运算符、取地址运算符

众所周知,程序运行时的数据是放在内存中的,而内存会被抽象为一系列具有连续编号的内存空间,那么每一个存储在内存中的数据都会有一个编号,这个编号就是内存地址。有了内存地址就可以找到这个内存中存储的数据,而内存地址可以被赋值给一个指针。

提示: 内存地址通常是16进制的数字表示,比如0x123b2a

在这里插入图片描述

在编程语言中,指针是一种数据类型,用来存储一个内存地址,该地址指向存储在该内存中的对象。这个对象可以使字符串、整数、函数或者自定义的结构体。

指针的声明和定义

​ 在Go语言中,获取一个变量的指针非常容易,使用取地址符 & 即可。指针类型非常廉价,只占用4个或8个字节的内存大小。

func main() {
    
    
    name := "奔跑的蜗牛"
    nameP := &name 
    fmt.Println("name变量的值:",name, "name变量的内存地址:", nameP)
}

​ 示例中nameP指针的类型是 *string,用于指向 string 类型的数据。在Go语言中使用类型名称前加 * 的方式,即可表示一个对应的指针类型。比如 int 类型的指针类型为 *int,float64 类型的指针类型是 *float64,自定义结构体A的指针类型是 *A。总之,指针类型就是对应的类型前加 * 号。

提示: 指针变量的值就是它所指向数据的内存地址,普通变量的值就是我们具体存放的值。

猜你喜欢

转载自blog.csdn.net/qq_47452807/article/details/128644726