go筑基篇(一)--入门
【1】基础知识
一、简介
Go是一个快速的静态类型编译型语言,Go语言具有很强的表达能力,它简洁、清晰而高效。Go语言(或 Golang)起源于 2007 年,并在 2009 年正式对外发布。Go语言有时候被描述为“C 类似语言”,或者是“21 世纪的C语言”。
Go 从C语言继承了相似的表达式语法、控制流结构、基础数据类型、调用参数传值、指针等很多思想,还有C语言一直所看中的编译后机器码的运行效率以及和现有操作系统的无缝适配。
Go语言没有类和继承的概念,它通过接口(interface)的概念来实现多态性。Go语言有一个清晰易懂的轻量级类型系统,在类型之间也没有层级之说。因此可以说Go语言是一门混合型的语言。
很多重要的开源项目都是使用Go语言开发的,其中包括 Docker、 Kubernetes。
Go 使用编译器来编译代码。编译器将源代码编译成二进制(或字节码)格式;
在编译代码时,编译器检查错误、优化性能并输出可在不同平台上运行的二进制文件。要创建并运行 Go 程序,程序员必须执行如下步骤。
- 编辑 Go 程序;
- 保存文件;
- 编译程序;
- 运行编译得到的可执行文件。
这不同于 Python、Ruby 和 JavaScript 等语言,它们不包含编译步骤。Go 自带了编译器,因此无须单独安装编译器。
二、为什么会有go语言?
go语言的所有设计者都说,设计Go语言是因为 C++ 给他们带来了挫败感。在 Google I/O 2012 的 Go 设计小组见面会上,Rob Pike 是这样说的:我们做了大量的 C++ 开发,厌烦了等待编译完成,尽管这是玩笑,但在很大程度上来说也是事实。
在Go语言出现之前,开发者们总是面临非常艰难的抉择,究竟是使用执行速度快但是编译速度并不理想的语言(如:C++),还是使用编译速度较快但执行效率不佳的语言(如:.NET、Java),
或者说开发难度较低但执行速度一般的动态语言呢?
显然,Go语言在这 3 个条件之间做到了最佳的平衡:快速编译,高效执行,易于开发。
Go语言支持交叉编译,比如说你可以在运行 Linux 系统的计算机上开发可以在 Windows 上运行的应用程序。
这是第一门完全支持 UTF-8 的编程语言,这不仅体现在它可以处理使用 UTF-8 编码的字符串,就连它的源码文件格式都是使用的 UTF-8 编码。
Go语言做到了真正的国际化。
三、go语言优势
容易学习
go语言语法特性简单,容易上手
效率
go语言编译非常快速,而且开发的效率、运行的效率也都非常的高。相较与java、c++这些比较呆滞的编译速度,go的编译速度是一个主要的效率优势。
C语言的理念是信任程序员,保持语言的小巧,不屏蔽底层,并且底层友好,关注语言的执行效率和性能。而python的姿态是使用尽量少的代码完成尽量多的事。
go语言想要把c和python统一起来,所以go语言有着接近c的运行效率和接近python的开发效率
出生名门、血统纯正
go语言出自google公司,设计者都是大佬
并行和异步编程几乎无痛点
go语言的goroutine和channel这2个神器简直就是并发和异步编程的福音,不像c、c++、java、python、javascript等并发和异步方式比较复杂,而且容易出错,go解决了这个问题,而且非常优雅和刘畅。
goroutine以及基于channel的并发性方法使其非常容易使用所有可用的cpu内核,并且处理并发的IO
go是为大数据、微服务、并发而生的一种编程语言。
自由高效
go可以利用组合的思想实现无侵入式的接口设计。go语言支持当前所有的编程范式:过程式编程、面向对象编程、面向接口编程、函数式编程,程序员可以各取所需,自由组合
强大的标准库
包括互联网应用、系统编程、网络编程,go里面标准库基本上已经非常稳定了
部署方便
go通过二进制文件拷贝进行部署,部署很方便,所以现在有很多人使用go语言开发运维程序
稳定性
go拥有强大的编译检查、严格的编码规范和完整的软件生命周期工具,具有很强的稳定性。
go提供了各个环节的软件生命周期工具:go tool、gofmt、go test等等,可以进行开发、测试、部署、维护等等
四、go语言特性
并发编程
go语言并发编程方面比其它语言要简洁不少,这一点是其进入高并发、高性能场景的重要筹码。go的并发执行单元是一种称为gorountine的协程。
协程又称微线程,比线程更轻量,开销更小,性能更高,操作起来非常简单。在同一台机器上可以使用关键字go启动成千上万个协程,协程之间一般由应运程序显示实现调用,上下文切换无需下到内核层,高效不少。协程间通信靠独有的channel机制实现。
内存分配
在初始化阶段先分配一块大内存区域,大内存被切分成各个大小等级的块,放入不同的空闲list中。对象分配空间时从空闲list中取出大小合适的内存块,内存回收时会把不用的内存重新放回空闲list,空闲内存会按照一定策略合并以减少碎片
内存回收(GC)
内存自动回收,再也不需要开发人员管理内存;
GC过程:先扫描所有对象判活,把可回收对象在一段bitmap区中标记下来,接着立即恢复服务,同时启一个专门的gorountine,回收内存到空闲list中以备复用,物理释放由专门的线程定期执行。GC瓶颈在于每次都要扫描所有对象来判活,遮掩会导致待收集的对象越多速度越慢,但GC的性能会随着版本的不断更新而不断优化
编译
go语言编译速度非常快,目前go语言具有2种编译器:一种是建立在Gcc基础上的Gccgo,另一种是分别针对x64、x86计算机的一套编译器。由于go语言绝大多数第三方开源库都在github上,在代码的import中加上对应的github路径就可以使用了,库会默认下载到工程的pkg目录下。编译时会检查代码中所有实体使用情况,凡是没有使用到的package或变量都会编译不通过,这是go语言比较严谨的一面。
网络编程
由于go语言诞生在互联网时代,因此它天生具备了去中心化、分布式等特性,具体表现之一就是提供了丰富便捷的网络编程接口:
socket用net.Dial(基于tcp/udp,封装了传统的connect、listen、accept等接口)
http用http.Get/Post()
rpc用client.Call('类名.方法名',args,&reply)
自带高性能httpServer,只需要几行代码就能得到一个基于协程的高性能web服务
函数多返回值
在c、c++,包括其它一些高级语言 是 不支持多返回值的,在c语言中一般将返回值定义成一个结构体或通过函数参数引用的形式进行返回,而在go语言中支持函数多返回值
语言交互性
语言交互性指本语言是否能和其他语言进行交互,比如可以调用其它编程语言的库。
go语言可以和c程序交互,在go语言中直接重用了大部分c的模块,这也成为Cgo,Cgo允许开发者混合编写C语言代码,然后Cgo工具可以将这些混合的c代码提取并生成对于c功能的调用包装代码,开发者可以完全忽略c语言和go语言的边界是如何跨越的
异常处理
go语言不止try....catch..这样的异常解决方式,因为觉着会增加代码量,而且会被滥用,不管多小的异常都抛出。go语言提供的异常处理方式是:
如果是普通异常,查看被调用方法返回的error对象;如果是严重异常,指的是中断性panic(比如除0),使用defer.....recover....panic机制来捕获处理,严重异常一般由go语言内部自动抛出,避免传统try....catch...写的导出都是的情况,
当然用户也可以使用panic('xxxxxxx')主动抛出,只是这样就使这一套机制退化成结构化异常机制了
类型推导
在定义变量时支持var age=10这样的语法,让go语言看上去有点像动态类型语言,但go语言实际上是强类型的,前面的定义会被自动推导出是int类型。
inerface接口
一个类型只要实现了某个interface的所有方法,无需显示去继承即可实现该interface
defer机制
通过该关键字可以指定需要延迟持执行的逻辑体,在函数体return前或者出现panic时执行,这种机制非常适合善后逻辑处理,比如可以尽早避免可能出现的资源泄露问题。defer在很大程度上可以简化编程,并且在语言描述上显得更为自然,极大的增强了代码的可读性
包
把相同功能的代码放到一个目录,称之为包。包可以被其它包import引用,main包是用来生成可执行文件,每个程序只有一个main包。包的主要用途是提高代码的可复用性。
Go语言是使用包来组织源代码的,包(package)是多个 Go 源码的集合,是一种高级的代码复用方案。Go语言中为我们提供了很多内置包,如 fmt、os、io 等。
交叉编译
可以在运行linux系统的计算机上,开发运行windows下运行的应用程序
五、技术发展的核心要素
一个技术能否发展起来主要看三点:
有没有一个比较好的社区
像c、c++、java、python等的生态圈都是非常丰富和火爆的,尤其是有许多商业机构参与的社区,比如linux社区就更加人气爆棚了
有没有一个工业化的标准
像c、c++、java都有标准化组织的,尤其是java,它在架构上还搞出了像J2EE这样企业级标准
有没有一个或多个杀手级应运
比如php是linux时代第一个杀手级解决方案lnmp中的关键技术。go语言杀手级应运是docker,而docker的生态圈这几年完全爆棚了
学习曲线是否低,上手是否快
有没有一个不错的提高开发效率的框架
有没有一个或多个巨型公司作为后盾
比如java和linux后面的IBM和sun。go语言有google这个世界一流公司在后面
有没有解决软件开发中的痛点
比如java,解决了c、c++中的内存管理问题。go语言解决了并发编程和写底层应运开发效率的痛点
【2】go环境搭建与基本使用
一、下载安装包并安装
正规下载地址:https://golang.org/dl/,但需要FQ
可访问下载地址:https://golang.google.cn/dl/。
下载完执行安装即可,我是把go安装到了d盘

把D:\Go\bin添加到全局环境编排path中
编辑test.go
package main import "fmt" func main() { fmt.Println("Hello, World!") }
执行命令go run test.go

二、安装go集成开发工具(IDE)
go继承开发工具有,GoLand、LiteIDE、Eclipse等,以下讲解如何安装GoLand开发工具
官网下载地址(打不开,需要FQ):https://www.jetbrains.com/go/download/other.html;
(推荐)直接复制本条链接到迅雷中下载:https://download.jetbrains.com/go/goland-2019.2.3.exe。
下载破解补丁:http://c.biancheng.net/uploads/course/go/Goland_Crack_Sinicization.zip

安装完后,打开工具

到这一步退出,把Goland_Crack_Sinicization.zip里解压文件jetbrains-agent.jar拷到C:\Program Files\JetBrains\GoLand 2019.2.3\bin目录,在bin 目录下“goland.exe.vmoptions”和“goland64.exe.vmoptions”两个文件末尾加上
-javaagent:C:\Program Files\JetBrains\GoLand 2019.2.3\bin\jetbrains-agent.jar
然后打开JetBrains GoLand 2019.2.3 x64,Licesnse server输入https://fls.jetbrains-agent.com即可
汉化
把Goland_Crack_Sinicization.zip里resources_cn.jar复制到 Goland 安装目录下的 lib 目录中(C:\Program Files\JetBrains\GoLand 2019.2.3\lib),
在 lib 目录中找到“resources_en.jar”文件,它是 Goland 内置的一个英文补丁,这里需要将它删除或者重命名(resources_en.jar-),建议大家选择重命名的方式,因为想要恢复英文的话还需要用到它,
运行 Goland ,你会发现 Goland 中的菜单已经变成我们熟悉的中文了

或者直接激活使用:
在Licence server输入http://idea.iblue.me
三、IDE配置
在设置里配置go的安装目录和项目目录

编辑器配置为黑色背景

设置字体大小

【3】执行go程序
一、go目录
$GOPATH 目录约定有三个子目录:
1.src 存放源代码(比如:.go .c .h .s等,此目录需要手动创建)
2.pkg 编译后生成的文件(比如:.a,此目录不需要手动创建,编译时会自动生成)
3.bin 编译后生成的可执行文件(此目录不需要手动创建,编译时会自动生成。为了方便,可以把此目录加入到 $PATH 变量中,如果有多个gopath,那么使用${GOPATH//://bin:}/bin添加所有的bin目录)
以后自己新建应用或者一个代码包都是在src目录下新建一个文件夹,文件夹名称一般是代码包名称,当然也允许多级目录,例如在src下面新建了目录$GOPATH/src/github.com/astaxie/beedb 那么这个包路径就是“github.com/astaxie/beedb”,包名称是最后一个目录beedb。beedb里所有go文件的package名称必须一致
注意:一般建议package的名称和目录名保持一致
二、GOPATH配置
GOPATH 是 Go语言中使用的一个环境变量,它使用绝对路径提供项目的工作目录。GOPATH 适合处理大量 Go语言源码、多个包组合而成的复杂工程。
在 Go 1.8 版本之前,GOPATH 环境变量默认是空的。从 Go 1.8 版本开始,Go 开发包在安装完成后,将 GOPATH 赋予了一个默认的目录,参见下表。

在 GOPATH 指定的工作目录下,代码总是会保存在 $GOPATH/src 目录下,bin 和 pkg 目录的内容都可以由 src 目录生成。
在工程经过 go build、go install 或 go get 等指令后,会将产生的二进制可执行文件放在 $GOPATH/bin 目录下,生成的中间缓存文件会被保存在 $GOPATH/pkg 下
GOPATH分类:
全局GOPATH( Global GOPATH):
如我的项目名叫test,在D:\go_www\test下,则GOPATH的全局环境变量设置为D:\go_www\test
通过
export GOPATH=`pwd`
设置

如果在这个项目test的src源文件下有个文件hello需要编译

这样我可以在任何位置执行go install hello,或在D:\go_www\test\src\hello下直接执行go install,即可在src的同级目录bin下生成hello.exe可执行文件

go build与go install类似,只是go build在哪个目录执行,生成的可执行文件就会生成在哪个目录,而不会存于与src同级的bin目录
缺点:某项目路径在 /home/davy/projectA ,将该目录设置为 全局GOPATH。
随着开发进行,需要再次获取一份工程项目的源码,此时源码保存在 /home/davy/projectB ,如果此时需要编译 projectB 的项目,又需要重新设置全局GOPATH,比较麻烦,
若开发者忘记设置 GOPATH 而直接使用命令行编译,编译完成后,开发者就会将错误的工程版本发布到外网。
因此建议大家无论是使用命令行或者使用集成开发环境编译 Go 源码时,GOPATH 跟随项目设定
项目GOPATH(Project GOPATH):
Project GOPATH 代表项目所使用的 GOPATH,该设置会被保存在工作目录的 .idea 目录下,不会被设置到环境变量的 GOPATH 中,但会在编译时使用到这个目录。
建议在开发时只填写项目 GOPATH,每一个项目尽量只设置一个 GOPATH,不使用多个 GOPATH 和全局的 GOPATH。

建议开发者不要设置全局的 GOPATH,而是随项目设置 GOPATH
三、简单使用
在/src/test/hello目录下,新建hello.go
package main //声明包main import "fmt" //导入包fmt,实现I/O格式化输入输出 func main() { //main函数。main函数所在包package的声明必须是main fmt.Println("hello world") }
编译生成二进制文件
go install hello
注意:
1、一个文件夹下的所有源码文件只能属于同一个包。在同一个包下的文件都属于同一个工程的文件,彼此之间不需要使用import引入就能直接使用
2、包名为 main 的包为应用程序的入口包,编译不包含 main 包的源码文件时不会得到可执行文件。main函数所在包的声明必须是main
3、一般包的名称就是其源文件所在目录的名称,虽然Go语言没有强制要求包名必须和其所在的目录名同名,但还是建议包名和所在目录同名,这样结构更清晰。
4、导入的包名需要使用双引号包裹起来
5、包名是从GOPATH/src/后开始计算的,使用/进行路径分隔
参考资料:
千锋教育100集在线视频教程
https://www.bilibili.com/video/BV1Db411s7in?p=8
千锋go语言全套视频教程
https://www.bilibili.com/read/cv3742048
go语言入门教程文档
浙公网安备 33010602011771号