【声明】

非完全原创,部分内容来自于学习其他人的理论和B站视频。如果有侵权,请联系我,可以立即删除掉。

一、Go语言简介

1、 发展史

2009年11月10日,Go语言正式发布,它是一种强静态类型、编译型语言,它专对多处理器系统应用程序的编程进行了优化,对于对于高并发,多线程的开发场景具有天然的优势

1.1 优势

  • 可以直接编译成机器码,不依赖其他库
  • 丰富的标准库,特别是网络库非常强大
  • 内置runtime,支持垃圾回收

1.2 应用场景

  • 服务器编程,例如处理日志、数据打包、虚拟机处理、文件系统等
  • 网络编程,包括Web应用、API应用、下载应用
  • 内存数据库,如google开发的groupcache,couchbase的部分组建
  • 云平台,例如现目前很火爆的k8s 也是利用go语言进行开发完成
  • 分布式系统,数据库代理器等
二、环境搭建

1、 安装Go语言

1.1 下载安装包

官网下载网址: https://www.golangtc.com/download
国内下载地址: https://studygolang.com/dl
中文在线文档: https://studygolang.com/pkgdoc

1.2 win版本安装

一般有zip压缩包和msi的安装方式:

  • zip解压就可以使用,但是需要自行配置go语言环境
  • msi安装之后,会自动设置环境变量

安装的路径中不应该有中文,否则会导致程序找不到路径
在这里插入图片描述

1.3 确认安装成功

go versiongo env

2、 go语言标准命令

安装了go语言之后,就直接可以使用其标准命令来处理Go语言代码,常见的go语言代码的命令和工具有:

build:用于编译给定的代码包或Go语言源码文件及其依赖包。
clean:用于清除执行其他go命令后遗留的目录和文件。
doc:用于执行godoc命令以打印指定代码包。
env:用于打印Go语言环境信息。
fix:用于执行go tool fix命令以修正给定代码包的源码文件中包含的过时语法和代码调用。
fmt:用于执行gofmt命令以格式化给定代码包中的源码文件。
get:用于下载和安装给定代码包及其依赖包(提前安装git或hg)。
list:用于显示给定代码包的信息。
run:用于编译并运行给定的命令源码文件。
install:编译包文件并编译整个程序。
test:用于测试给定的代码包。
tool:用于运行Go语言的特殊工具。
version:用于显示当前安装的Go语言的版本信息。

3、 安装IDE

go语言安装包安装之后,编译代码时,需要通过命令提示符进入代码所在路径下进行编译,不方便代码的管理。为了便于开发,一般需要选择一款开发工具,常见的有:

  • LiteIDE:一款开源、跨平台的轻量级 Go 语言集成开发环境(IDE)
  • eclipse:需要下载插件
  • Goland:由 JetBrains 公司开发的一个新的商业 IDE,提供了针对Go语言的编码辅助和工具集成。

一般来说,使用免费的liteIDE可以满足日常使用,下载网址:http://liteide.org/cn/。windows版本直接安装即可。

4、 go语言的Hello world

如下,是go语言版本的Hello World。由于此处只有一个go文件,因此文件的开头package必须声明一个main的包名,并且在该包中包含一个叫main()的函数作为go语言可执行程序的起点。

//HelloWorld.go
package main
import ("fmt")

func main() {
    fmt.Println("Hello World")
}
Printlnfmt
funcmain

进入到对应的目录下即可编译和运行
在这里插入图片描述

三、Go语言基础知识

1、 命名

命名规则:必须以一个字母或下划线开头,后面可以跟任意数量的字母、数字或下划线,且不能与关键字重名。命名的规则和C语言、Java一样。

Go语言的关键字有25个:

breakdefaultfuncinterfaceselect
casedefergomapstruct
chanelsegotopackageswitch
constfallthroughifrangetype
continueforimportreturnvar

另外还有30多个预定义的名字:

内建常量: 
		true false iota nil
内建类型: 
    	int int8 int16 int32 int64
    	uint uint8 uint16 uint32 uint64 uintptr
    	float32 float64 complex128 complex64
    	bool byte rune string error
内建函数: 
    	make len cap new append copy close delete
    	complex real imag
    	panic recover

2、 变量

变量是程序运行期间可以改变的量,相当于是对一块数据存储空间的命名,程序可以通过定义一个变量来申请一块数据存储空间,之后可以通过引用变量名来使用这块存储空间。

2.1 变量的声明

var类型 变量名
	//定义单个变量
	var v1 int

    //同时定义多个变量:只能同一种类型
    var v2, v3 int 

	//同时定义多个变量:变量可以不同类型
    var (
        v4 int
        v5 bool
    )

2.2 变量初始化

var:=
package main
import (
	"fmt"
	"reflect"
)

func main() {
	var v1 int = 1		// 普通初始化的方式
    var v2 = 2			// 编译器自动推导类型的初始化方式
    v3 := 3				//编译器自动推导类型的初始化方式:不用写var关键字
    v4 := 4.0
    v5 := false
    fmt.Println("v3 type is ", reflect.TypeOf(v3))
    fmt.Println("v4 type is ", reflect.TypeOf(v4))
    fmt.Printf("v5 type is %T\n", v5)
	fmt.Printf("v1+v2 type is %T\n", v1+v2)
}

在这里插入图片描述

var v1 intv1:=1:=

2.3 变量赋值

go语言赋值类似于python,可以多重赋值,如下:

	var v1 int = 1		//初始化时赋值
	
	//先声明后赋值
	var v2, v3, v4 int
	v2 = 2
	v3, v4 = 3, 4		//多重赋值
	
	v5 := 5				//使用:=声明且赋值
	v3, v5 = v5, v3		//多重赋值实现值交换
	
	_, v2 = 3, 4		//匿名变量`_`是个特殊的变量名,其值会被丢弃

3、 常量

常量是指编译期间就已知且不可改变的值。常量可以是数值类型(包括整型、浮点型和复数类型)、布尔类型、字符串类型等。

3.1 字面常量

直接写在代码中的数字,文字等代码文本。如下示例在C语言中可直接独立存在的字面常量,但该写法在go语言中会报错(定义未使用)

int main()
{
	true;	//布尔类型的字面常量
	'a';	//字符字面常量,本质上是整数对应的ASCII编码
	"123abc你好";	//字符串字面常量,本质是一个地址
	666uL;		//unsigned long字面常量
	3.14F;		//float字面常量
	return 0;
}

字面常量经常出现在硬编码中。硬编码是指,将数据直接写入到代码中进行编译开发的方式,如没有mybatits前,将sql语句写入到jdbc代码里。其主要的缺陷在于,如果需要变更,则需要修改源代码。
非硬编码,也指软编码,是指将数据与源代码解耦,使代码更加合理的方式,如将参数使用变量来表达便于修改等等

const
varconst
	//定义单个常量
	const v1 = 3.14		//浮点常量, 自动推导类型

    //同时定义多个常量:只能同一种类型
    const v2, v3 int = 2, 3

	//同时定义多个常量:常量可以不同类型
    const (
        v4 float64 = 1.56
        v5 bool = true
    )
iota
iotaconst
package main
import (
	"fmt"
)

func main() {
	const (
		i = iota	//i = 0
		j = iota	//j = 1
	)
	
	//每遇到const, iota将会重置为0
	const (
		a = iota + 11		//a = 0 +11
		b = iota * 10		//b = 1 *10
		c = iota * 5 + 1	//c = 2	*5+1
	)
	
	const m = iota	//m = 0

	fmt.Printf("i = %d, j = %d\n", i, j)
	fmt.Printf("a = %d, b = %d, c = %d\n", a, b, c)
	fmt.Printf("m = %d\n", m)
}

在这里插入图片描述

4、 基础数据类型

Go语言内置以下这些基础类型

类型名称长度零值说明
bool布尔类型1false其值不为真即为家,不可以用数字代表true或false
byte字节型10uint8别名
rune字符类型40专用于存储unicode编码,等价于uint32
int, uint整型4或8032位或64位
int8, uint8整型10-128 ~ 127, 0 ~ 255
int16, uint16整型20-32768 ~ 32767, 0 ~ 65535
int32, uint32整型40-21亿 ~ 21 亿, 0 ~ 42 亿
int64, uint64整型80
float32浮点型40.0小数位精确到7位
float64浮点型80.0小数位精确到15位
complex64复数类型8
complex128复数类型16
uintptr整型4或8⾜以存储指针的uint32或uint64整数
string字符串“”utf-8字符串

4.1 布尔类型

truefalse
var v1 bool
v1 = true
v2 := (1 == 2) // v2也会被推导为bool类型

//布尔类型不能接受其他类型的赋值,不支持自动或强制的类型转换
var b bool
b = 1 // err, 编译错误
b = bool(1) // err, 编译错误

4.2 整型

使用自动推导时,整数会自动推导为int类型

package main
import (
	"fmt"
)

func main() {
	var v1 int32
    v1 = 123
    v2 := 64 // v1将会被自动推导为int类型
	fmt.Printf("v1 type is %T\n", v1)
	fmt.Printf("v2 type is %T\n", v2)
}

在这里插入图片描述

4.3 浮点型

使用自动推导时,小数会自动推导为float64类型

package main //必须有一个main包
import "fmt"

func main() {
	//声明变量
	var f1 float32
	f1 = 3.14
	fmt.Println("f1 = ", f1)

	//自动推导类型
	f2 := 3.14
	fmt.Printf("f2 type is %T\n", f2) //f2 type is float64

	//float64存储小数比float32更准确
}

在这里插入图片描述

4.4 字符类型

charCharacterbyterune
'\n'
package main //必须有一个main包
import "fmt"

func main() {
	var ch byte //声明字符类型
	ch = 97
	//fmt.Println("ch = ", ch)
	//格式化输出,%c以字符方式打印,%d以整型方式打印
	fmt.Printf("%c, %d\n", ch, ch)

	ch = 'a' //字符, 单引号
	fmt.Printf("%c, %d\n", ch, ch)

	//大写转小写,小写转大写, 大小写相差32,小写大
	fmt.Printf("大写:%d, 小写:%d\n", 'A', 'a')
	fmt.Printf("大写转小写:%c\n", 'A'+32)
	fmt.Printf("小写转大写:%c\n", 'a'-32)
}

在这里插入图片描述

4.5 字符串类型

string'\0'
package main //必须有一个main包
import "fmt"

func main() {
	var str1 string //声明变量
	str1 = "abc"	// 由'a'、'b'、'c'和'\0'组成了一个字符串
	fmt.Println("strl = ", str1)

	//自动推导类型
	str2 := "mike"
	fmt.Printf("str2 类型是 %T\n", str2)

	//内建函数,len()可以测字符串的长度,有多少个字符
	fmt.Println("len(str2) = ", len(str2))
}

在这里插入图片描述

4.6 字符和字符串的区别

""\0
package main //必须有一个main包

import "fmt"

func main() {
	var ch byte
	var str string

	ch = 'a'
	fmt.Println("ch =", ch)

	str = "a" // 由'a'和'\0'组成了一个字符串
	fmt.Println("str = ", str)

	str = "hello go"
	//只想操作字符串的某个字符,从0开始操作
	fmt.Printf("str[0] = %c, str[1] = %c\n", str[0], str[1])

}

在这里插入图片描述

4.7 复数类型

复数实际上由两个实数(在计算机中用浮点数表示)构成,一个表示实部(real),一个表示虚部(imag)

package main //必须有一个main包
import "fmt"

func main() {
	var t complex128 //声明
	t = 2.1 + 3.14i  //赋值
	fmt.Println("t = ", t)

	//自动推导类型
	t2 := 3.3 + 4.4i
	fmt.Printf("t2 type is %T\n", t2)

	//通过内建函数,取实部和虚部
	fmt.Println("real(t2) = ", real(t2), ", imag(t2) = ", imag(t2))

}

在这里插入图片描述

5、 类型转换、类型别名

5.1 类型转换

Go语言中不允许隐式转换,所有类型转换必须显式声明,而且转换只能发生在两种相互兼容的类型之间。

package main //必须有一个main包
import "fmt"

func main() {
	var flag bool
	flag = true
	fmt.Printf("flag = %t\n", flag)

	//bool类型不能转换为int,这种不能转换的类型,叫不兼容类型
	//fmt.Printf("flag = %d\n", int(flag))

	//0就是假,非0就是真
	//整型也不能转换为bool
	//flag = bool(1)

	var ch byte
	ch = 'a' //字符类型本质上就是整型
	var t int
	t = int(ch) //类型转换,把ch的值取出来后,转成int再给t赋值
	fmt.Println("t = ", t)
}

在这里插入图片描述

5.2 类型别名

package main //必须有一个main包
import "fmt"

func main() {
	//给int64起一个别名叫bigint
	type bigint int64

	var a bigint // 等价于var a int64
	fmt.Printf("a type is %T\n", a)

	type (
		long int64
		char byte
	)

	var b long = 11
	var ch char = 'a'
	fmt.Printf("b = %d, ch = %c\n", b, ch)
}

在这里插入图片描述

fmt

6.1 格式说明

printf
格式含义
%%一个%字面量
%b一个二进制整数值(基数为2),或者是一个(高级的)用科学计数法表示的指数为2的浮点数
%c字符型。可以把输入的数字按照ASCII码相应转换为对应的字符
%d一个十进制数值(基数为10)
%e以科学记数法e表示的浮点数或者复数值
%E以科学记数法E表示的浮点数或者复数值
%f以标准记数法表示的浮点数或者复数值
%g以%e或者%f表示的浮点数或者复数,任何一个都以最为紧凑的方式输出
%G以%E或者%f表示的浮点数或者复数,任何一个都以最为紧凑的方式输出
%o一个以八进制表示的数字(基数为8)
%p以十六进制(基数为16)表示的一个值的地址,前缀为0x,字母使用小写的a-f表示
%q使用Go语法以及必须时使用转义,以双引号括起来的字符串或者字节切片[]byte,或者是以单引号括起来的数字
%s字符串。输出字符串中的字符直至字符串中的空字符(字符串以’\0‘结尾,这个’\0’即空字符)
%t以true或者false输出的布尔值
%T使用Go语法输出的值的类型
%U一个用Unicode表示法表示的整型码点,默认值为4个数字字符
%v使用默认格式输出的内置或者自定义类型的值,或者是使用其类型的String()方式输出的自定义值,如果该方法存在的话
%x以十六进制表示的整型值(基数为十六),数字a-f使用小写表示
%X以十六进制表示的整型值(基数为十六),数字A-F使用小写表示

6.2 输出

package main //必须有一个main包
import "fmt"

func main() {
	a := 10
	b := "abc"
	c := 'a'
	d := 3.14
	//%T操作变量所属类型
	fmt.Printf("%T, %T, %T, %T\n", a, b, c, d)

	//%d 整型格式
	//%s 字符串格式
	//%c 字符个数
	//%f 浮点型个数
	fmt.Printf("a = %d, b = %s, c = %c, d = %f\n", a, b, c, d)
	//%v自动匹配格式输出
	fmt.Printf("a = %v, b = %v, c = %v, d = %v\n", a, b, c, d)
}

在这里插入图片描述

6.3 输入

package main //必须有一个main包
import "fmt"

func main() {
	var a int //声明变量
	fmt.Printf("请输入变量a: ")

	//阻塞等待用户的输入
	//fmt.Scanf("%d", &a) //别忘了&
	fmt.Scan(&a)
	fmt.Println("a = ", a)
}

在这里插入图片描述

四、运算符

1、 算术运算符

运算符术语示例结果
+10 + 515
-10 - 55
*10 * 550
/10 / 52
%取模(取余)10 % 31
++后自增,没有前自增a=0
a++
a=1
后自减,没有前自减a=1
a–
a=0

2、 关系运算符

运算符术语示例结果
==相等于4 == 3false
!=不等于4 != 3true
<小于4 < 3false
>大于4 > 3true
<=小于等于4 <= 3false
>=大于等于4 >= 1true

3、 逻辑运算符

运算符术语示例结果
!!a如果a为假,则!a为真;
&&a && b如果a和b都为真,则结果为真,否则为假。
||a || b如果a和b有一个为真,则结果为真,二者都为假时,结果为假。

4、 位运算符

运算符术语说明示例
&按位与参与运算的两数各对应的二进位相与7 & 8 结果为 0
|按位或参与运算的两数各对应的二进位相或7 | 8 结果为 15
^异或参与运算的两数各对应的二进位相异或,当两对应的二进位数字不同时,结果为17 ^ 8 结果为 15
<<左移左移n位就是乘以2的n次方。 左边丢弃,右边补0。1 << 3 结果为 8 (1*2^3)
>>右移右移n位就是除以2的n次方。 右边丢弃,左边补位。8 >> 3 结果为1

5、 赋值运算符

运算符说明示例
=普通赋值c = a + b 将 a + b 表达式结果赋值给 c
+=相加后再赋值c += a 等价于 c = c + a
-=相减后再赋值c -= a 等价于 c = c - a
*=相乘后再赋值c *= a 等价于 c = c * a
/=相除后再赋值c /= a 等价于 c = c / a
%=求余后再赋值c %= a 等价于 c = c % a
<<=左移后赋值c <<= 2 等价于 c = c << 2
>>=右移后赋值c >>= 2 等价于 c = c >> 2
&=按位与后赋值c &= 2 等价于 c = c & 2
^=按位异或后赋值c ^= 2 等价于 c = c ^ 2
|=按位或后赋值c |= 2 等价于 c = c | 2

6、 其他运算符

运算符术语示例说明
&取地址运算符&a变量a的地址
*取值运算符*a指针变量a所指向内存的值

7、 运算符优先级

在Go语言中,一元运算符拥有最高的优先级,二元运算符的运算方向均是从左至右。

下表列出了所有运算符以及它们的优先级,由上至下代表优先级由高到低:

优先级运算符
7^ !
6* / % << >> & &^
5+ -
4== != < <= >= >
3<-
2&&
1||
package main //必须有一个main包

import "fmt"

func main() {
	fmt.Println("4 > 3 结果:", 4 > 3)
	fmt.Println("4 != 3 结果:", 4 != 3)

	fmt.Println("!(4 > 3) 结果:", !(4 > 3))
	fmt.Println("!(4 != 3) 结果:", !(4 != 3))

	//&& 与, 并且,左边右边都为真,结果才为真, 其它都为假
	fmt.Println("true && true 结果:", true && true)
	fmt.Println("true && false 结果:", true && false)

	// ||, 或者, 左边右边都为假,结果才为假,其它都为真
	fmt.Println("true || false 结果:", true || false)
	fmt.Println("false || false 结果:", false || false)

	a := 11
	fmt.Println("0 <= a && a <= 10 结果为:", 0 <= a && a <= 10)

}

在这里插入图片描述