golang 语言基础
当前写go一些主流的微服务框架有哪些呢?
go-micro go-zero go-kit
C语言 37个关键字
C++ 11个关键字
Golang 25个关键字
Go 语言官方文档 https://golang.org/doc/fag
«GO 语言入门到实战» 学习路线图
1. 基础篇 | 2.进阶实战篇 |
---|---|
基本程序结构 | 并发编程模式 |
常用集合 | 常见并发任务 |
函数式编程 | 反射和Unsafe |
面向对象编程 | 常见架构模式的实现 |
错误处理 | 性能调优 |
模块化及依赖管理 | 高可用性服务设计 |
1. 基础篇
1.1 GO 简介
Go的三个作者分别是: Rob Pike(罗伯.派克),Ken Thompson(肯.汤普森)和Robert Griesemer(罗伯特.格利茨默)
- Rob Pike:曾是贝尔实验室(Bell Labs)的Unix团队,和Plan 9操作系统计划的成员。他与Thompson共事多年,并共创出广泛使用的UTF-8 字元编码。
- Ken Thompson:主要是B语言、C语言的作者、Unix之父。1983年图灵奖(Turing Award)和1998年美国国家技术奖(National Medal of Technology)得主。他与Dennis Ritchie是Unix的原创者。Thompson也发明了后来衍生出C语言的B程序语言。
- Robert Griesemer:在开发Go之前是Google V8、Chubby和HotSpot JVM的主要贡献者。
1.2 Go语言名字的来源
一封由 Rob Pike 在 2007 年 9 月 25 号,星期二,下午 3:12 回复给 Robert Griesemer、Ken Thompson 的有关编程语言讨论主题的邮件,邮件正文大意为:在开车回家的路上我得到了些灵感。1.给这门编程语言取名为“go”,它很简短,易书写。工具类可以命名为:goc、 gol、goa。交互式的调试工具也可以直接命名为“go”。语言文件后缀名为 .go 等等。
1.3 安装gvm|golang版本切换
安装gvm全称为「Golang Version Manager」golang环境版本切换,gvm提供了一个管理Go版本的接口,它是管理Go版本和软件包的一种直观且非侵入性的方式,使用 shell 脚本开发,它可以非常轻量的切换 Go 版本。其他语言类似的工具,如 NodeJS 的 NVM,Python 的 pyenv 等。
1.3.1 下载安装脚本
wget https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer
修改安装脚本[从git地址下载慢,已经fork到gitee上,提升效率] & 安装gvm
#把github地址修改为gitee地址:
SRC_REPO=${SRC_REPO:-https://gitee.com/hongleishen/gvm.git}
把GVM_DEST改/opt/shl目录:
#GVM_DEST="/opt/shl"
#安装完终端会提示(按提示输入)
[root@building-kubernetes shl]# sh gvm-installer
Cloning from https://gitee.com/hongleishen/gvm.git to /opt/shl/gvm
which: no go in (/sbin:/bin:/usr/sbin:/usr/bin)
No existing Go versions detected
Installed GVM v1.0.22
Please restart your terminal session or to get started right away run
`source /opt/shl/gvm/scripts/gvm`
#go 版本切换工具gvm环境变量配置
vi /etc/profile
[[ -s "/opt/shl/gvm/scripts/gvm" ]] && source "/opt/shl/gvm/scripts/gvm"
source /etc/profile
1.3.2 验证
[root@building-kubernetes shl]# gvm list
gvm gos (installed)
1.3.3 gvm 常用命令
gvm go版本管理
gvm list #列出当前已安装的 Go 版本
gvm listall #列出当前可以安装的 Go 版本
gvm install go1.15 #安装指定版本的 Go
go uninstall go1.15 #卸载 Go 版本
gvm use go1.15 #临时切换到指定的 Go 版本
gvm use go1.15 --default #永久切换到指定的 Go 版本
gvm diff #在GOROOT中列出添加/删除的文件
#查看所有命令
gvm
Usage: gvm [command]
Description:
GVM is the Go Version Manager
Commands:
version - print the gvm version number
get - gets the latest code (for debugging)
use - select a go version to use (--default to set permanently)
diff - view changes to Go root
help - display this usage text
implode - completely remove gvm
install - install go versions
uninstall - uninstall go versions
cross - install go cross compilers
linkthis - link this directory into GOPATH
list - list installed go versions
listall - list available versions
alias - manage go version aliases
pkgset - manage go packages sets
pkgenv - edit the environment for a package set
gvm 包环境管理
gvm管理包环境,相关命令是 pkgenv
和 pkgset
。如果没使用包依赖管理工具,它也是挺方便的。演示个例子,假设我们要创建一个新的项目 blog,可提前创建相应的环境。复制代码现在,我们通过 go get 安装的包都会默认在 blog 环境下。基于的原理是 go get 默认会把安装的放在 GOPATH 中的第一个目录下。
$ gvm pkgset create blog # 创建
$ gvm pkgset use blog # 启用
1.4 安装go不同版本
使用gvm 安装golang版本
注意:在«Kubernetes源码剖析»一书中提到,构建kubernetes 1.14版本,需要使用Go1.12或者更高版本。不同的Kubernetes版本对应的Go语言版本也不同
gvm install go1.14
#小提示,若安装不成功或者慢的话,同理修改git地址为gitee地址
vi ~/.gvm/scripts/install
修改 GO_SOURCE_URL 变量地址为: GO_SOURCE_URL=https://gitee.com/hongleishen/go.git
1.5 编辑器
VS Code、Vim、LitelDE、Emacs
调试功能最方便的肯定是Goland,VS Code要略作配置,vim因人而异,使用方式对于多数人可能不太习惯。
在mac下, sublime + gosublime + golint + goimporter + fswatch
liteIDE 独有的超实用的功能, 就是find callstack, 分析大型项目尤为实用, 尤其是有unit tests的情况
Goland
Goland,商业公司jetbrains 近两年推出的 Go 集成开发环境,它真的是无比强大。
我相信很多程序都用过他们家的IDE,比如Java的 Intellj IDEA、PHP的PHPStorm、Python的PyCharm、C++的CLion、前端的WebStorm等。使用JetBrains的IDE,我们可以享受到它优秀的开箱即用的体验和 jetbrains 积累十几年的插件体系。
前些年,也就是Goland发布之前,如果我们希望用jetbrain的IDE进行GO的开发,需要通过它提供的插件支持。Goland发布后,这些插件似乎已经下架了。
不得不承认,Goland的功能层面做的确实非常完美。不过有几点我想吐槽一下,首先必须要提的是,Jetbrians的IDE对配置要求比其他IDE高,使用不当会出现卡顿的毛病,资源消耗比较严重。虽然一些大牛提供了优化方案,但体验下来,和其他IDE依然没有相比。
Goland的开箱即用,使它的问题很少,很适合大型项目开发。装起来就可以开干!
VS Code
由微软开发的一款功能强大的现代化轻量级代码编辑器IDE,免费开源。通过它强大的插件扩展能力,VS Code几乎支持主流语言的项目开发。毫无例外,GO也是其中之一。
之所以尝试VS Code,并非喜欢瞎折腾,而是因为jetbrains的IDE经常会卡的心痛,而且自己经常会在不同语言间切换。一次启动多款Jetbrains的IDE,这是很痛苦的。
为VS Code加入GO的开发能力,只需安装一款插件即可,插件地址。安装时,可能遇到一些问题,常见的就是,在安装一些依赖包时会出现网络下载失败。关于原因就不说了,大家都明白。不过,问题还是要解决的。
举个具体的例子吧!在GO插件时,我们会通过go get golang.org/x/tools/xxx安装某个包,这时候大概率出现网络连接错误。我们可以通从github找到对应的仓库,golang/tools,然后使用git命令下载后,放在GOPATH指定的目录下,然后再安装即可。
最后,插个题外话,VS Code使用的是Electron开发的,Electron是用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库,NodeJS与Chromium的结合。因此,利用浏览器的特性,利用VS Code,我们能实现很多奇葩的插件,例如下面这些插件。
VS Code中GO的Debug功能需要配置一下,不像Goland等传统IDE那样,直接就能调试,
Vim GO
细究起来,vim应该是一款文本编辑器,但它却拥有了很多不该属于文本编辑器的能力,比如单词补全、ctags标签跳转、窗口分隔、崩溃文件恢复、文件diff、400多种文本高亮等。最重要的一点是,vim有一套自己的脚本语言,这为它通过插件扩展自己的能力提供了可能。
将vim扩展成一款适合自己使用的GO IDE,不仅要编写许多复杂的配置与脚本,还需要各种插件的相互配合,才能实现我们的目标。比如前面介绍的那些IDE的常见功能,在vim中都要逐一配置实现。
GO的vim环境搭建,需要用到一款非常重要的插件,vim-go。它由国外开发者提供,youtube上还有他的分享视频,有兴趣可以去看看,地址。vim-go提供了诸如代码的编译、执行、测试、代码重构、错误提示等各种功能,具体了解可查看 vim-go教程。
说明一点,虽然vim支持插件扩展,但它要集成出VS Code的体验还是非常困难的。我是不太清楚是否有这种可能,不过即使能实现,也是困难重重。当前,我正尝试用vim配置GO开发环境,效果图如下,一些功能还不完善。
当前我用的主要就是这三款IDE,Goland主要在工作中使用,而VSC和vim在平时使用。当然,还有很多其他IDE,下面也简单介绍下,但因为没怎么使用过,所以很难有经验之谈了。
Sublime Text
最初用VS Code,感觉它的使用习惯和Sublime相似。但说到Sublime,都说它是强大文本编辑器,而它的编码能力也是插件扩展来的。GoSublime就是为Sublime扩展GO功能的插件。
LiteIDE
一款轻量级的IDE,听说是由中国人开发的。可能在Goland出现之前比较流行。也或许是自己孤陋寡闻,不知道现在还有多少人在用。
Eclipse
开源的IDE,盛行了多年,有着丰富的资源和粉丝人群,应该是Java开发最喜欢的IDE吧。GoEclise是Eclipse针对Goland的插件。从github了解到,这个项目好像很久没有更新了。
Atom
与VS Code一样,都是基于Node-Webkit,即Electron,开发的。是由github开源的文本编辑器。go-plus是Atom针对Golang开发的插件
2.学习篇
2.1 基础结构和类型
2.1.1 命令规范
Go语言中,任何标识符(变量、常量、函数、自定义类型等)都应该满足以下规则:
- 连续的字符或者数字组成。
- 以字符或下划线开头。
- 不能和Go关键字冲突。
letter = unicode_letter | "_" .
decimal_digit = "0" … "9" .
binary_digit = "0" | "1" .
octal_digit = "0" … "7" .
hex_digit = "0" … "9" | "A" … "F" | "a" … "f" .
Go 关键字
The following keywords are reserved and may not be used as identifiers.
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
Operators and punctuation 运算符
The following character sequences represent operators (including assignment operators) and punctuation:
+ & += &= && == != ( )
- | -= |= || < <= [ ]
* ^ *= ^= <- > >= { }
/ << /= <<= ++ = := , ;
% >> %= >>= -- ! ... . :
&^ &^=
举例说明
#合法
foo foo1 _foo 变量 变量1 _变量
#不合法
1foo 1 type go
2.1.2 变量Variables
类型声明基本语法,在Go语言中,采用的是后置类型的声明方式,形如:
<命名> <类型>
#举例说明
x int //定义x为整数类型
变量声明,在Go语言中通常我们使用关键字var
来声明变量,例如
var x int //表示声明一个名称 x 的整数变量
var b int = 1 //表示声明一个名为 b 的整数变量,并且附上初始值为 1
var b = 1
如果有多个变量同时声明,我们可以采用var
加括号批量声明的方式
var (
a,b int //同时声明 a,b的整数
c float64
)
简短声明方式,变量在声明的时候如果有初始值,我们可以使用 :=
的简短声明方式
a :=1 //声明 a 为 1 的整数
b := int64(1) //声明 b 为 1 的 64 位整数
2.1.2 常量Constants
const (
c1 = 2
c2 = 3
)
const c4 = 1
const c5 int = 4
c4 = 2 //Cannot assign to c4,常量值是不可修改的
2.1.3 基础类型
go 语言中的基本数据类型包含三大类:布尔类型,数字类型,字符串类型。
Boolean types
布尔类型:A boolean type represents the set of Boolean truth values denoted by the predeclared constants true
and false
. The predeclared boolean type is bool
; it is a defined type
注意:
- 默认值是:false
- 取值范围:true、false
var flag0 bool
var flag1 bool = ture
flag2 := true
const flag3 = true
Numeric types
A numeric type represents sets of integer or floating-point values. The predeclared architecture-independent numeric types are:
数值类型表示整数或浮点值的集合。int, unit是基于处理器架构的。意味着会根据处理器来确定是32bit还是64bit。 使用时,常常使用int。或者使用int32保证兼容。
//字word 、字节byte 、位bit(来自英文bit,音译为“比特”,表示二进制位)
//字长是指字的长度
//1字=2字节(1word =2byte)|一个字的字长为16
//1字节=8位(1byte =8bit)|一个字节的字长是8
//1Byte =8Bits
//1KB =1024Bytes
//1MB =1024KB
//1GB =1024MB
//汉字:
//1 汉字 = 2 byte = 16 bit (这里不是很准确,当编码不同的时候,1个汉字所占的字节数也会有所不同,有些编码是占 2个字节,有些则不是,可能是 3个或者 4个)
//无符号数不可表示负数
uint8 the set of all unsigned 8-bit integers (0 to 255)//它占的存储空间是8个bit,它能取2的8次方个数
uint16 the set of all unsigned 16-bit integers (0 to 65535)
uint32 the set of all unsigned 32-bit integers (0 to 4294967295)
uint64 the set of all unsigned 64-bit integers (0 to 18446744073709551615)
//有符号数可以表示负数
int8 the set of all signed 8-bit integers (-128 to 127)
int16 the set of all signed 16-bit integers (-32768 to 32767)
int32 the set of all signed 32-bit integers (-2147483648 to 2147483647)
int64 the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)
//这里没有像java那样的隐式类型转换,只能显示,eg一个a float32,b float64: a=b(float32)
float32 the set of all IEEE-754 32-bit floating-point numbers
float64 the set of all IEEE-754 64-bit floating-point numbers
complex64 the set of all complex numbers with float32 real and imaginary parts
complex128 the set of all complex numbers with float64 real and imaginary parts
byte alias for uint8
rune alias for int32
//There is also a set of predeclared numeric types with implementation-specific sizes:
uint either 32 or 64 bits
int same size as uint
uintptr an unsigned integer large enough to store the uninterpreted bits of a pointer value
数字类型主要分有符号数和无符号数,有符号数可以表示负数,除此之外,他们还有位数的区别,不同的位数代表它们所占实际存储占用空间,以及取值的范围。
var (
i1 int //int either 32 or 64 bits
i2 int8 //
i3 int16
i4 int32
i5 int64
)
var (
i6 uint //uint either 32 or 64 bits
i7 uint8
i8 uint16
i9 uint32
i10 uint64
)
fmt.Println("打印出int实际所占存储空间长度:", unsafe.Sizeof(i1))
fmt.Println("打印出int8实际所占存储空间大小:", unsafe.Sizeof(i2))
fmt.Println("打印出int16实际所占存储空间大小:", unsafe.Sizeof(i3))
fmt.Println("打印出int32实际所占存储空间大小:", unsafe.Sizeof(i4))
fmt.Println("打印出int64实际所占存储空间大小:", unsafe.Sizeof(i5))
fmt.Println("打印出uint实际所占存储空间大小:", unsafe.Sizeof(i6))
fmt.Println("打印出uint8实际所占存储空间大小:", unsafe.Sizeof(i7))
fmt.Println("打印出uint16实际所占存储空间大小:", unsafe.Sizeof(i8))
fmt.Println("打印出uint32实际所占存储空间大小:", unsafe.Sizeof(i9))
fmt.Println("打印出uint64实际所占存储空间大小:", unsafe.Sizeof(i10))
扩展阅读:
Golang的数据类型
数据类型
基本数据类型、内置类型
无符号数:
uint8 字节:1 内存:8位(8-bit) 取值范围:
uint16 字节: 2 内存: 16位 取值范围:
uint32 字节: 4 内存: 32位 取值范围:
uint64 字节: 8 内存: 64位 取值范围:
有符号数:
int8 字节:1 内存:8位 取值范围:-128~127(-2^7 ~2^7 -1)
int16 字节: 2 内存: 16位 取值范围:
int32 字节: 4 内存: 32位 取值范围:
int64 字节: 8 内存: 64位 取值范围:
Java的八大基本数据类型
数据类型
基本数据类型、内置类型
整数类型:
byte 字节:1 内存:8位 取值范围:-128~127(-2^7 ~2^7 -1)
short 字节: 2 内存: 16位 取值范围:-32768到32767(-2^15~2^15-1)
int 字节: 4 内存: 32位 取值范围:-2147483648到2147483647(-2^31~2^31-1)
long 字节: 8 内存: 64位 取值范围:-9223372036854774808到9223372036854774807(-2^63~2^63-1)
浮点类型:
double 字节: 8 内存: 取值范围:
float 字节: 4 内存: 取值范围:
字符类型:
char 字节: 1 内存: 取值范围:
布尔类型:
boolean 字节: 1 内存: 取值范围:
引用类型
String types
A string type represents the set of string values. A string value is a (possibly empty) sequence of bytes. The number of bytes is called the length of the string and is never negative. Strings are immutable: once created, it is impossible to change the contents of a string. The predeclared string type is string
; it is a defined type.
The length of a string s
can be discovered using the built-in function len
. The length is a compile-time constant if the string is a constant. A string’s bytes can be accessed by integer indices 0 through len(s)-1
. It is illegal to take the address of such an element; if s[i]
is the i
'th byte of a string, &s[i]
is invalid.
//string
var str string = "hello , world"
fmt.Println(str)
str = "hello , \"world\"" //特殊字符转意
fmt.Println(str)
str = `hello , "world"`
fmt.Println(str)
str = `line1
line2
line3`
fmt.Println(str)
str = "hello,world,世界"
fmt.Println([]byte(str)) //把字符串转换成byte
fmt.Println(len(str)) //查看byte的大小
fmt.Println(len(([]rune(str)))) //查看多少个字符
//输出每一个字符
for _, char := range str {
//输出为range int32类型
fmt.Println(char)
//range类型是int32,需要转换成string
fmt.Println(string(char))
}