一、初识GO语言
1.GO语言介绍
1.1 GO语言是什么
2009年11月10日,GO语言正式成为开源编程语言家庭一员。GO语言是云计算时代的c语言。GO语言专门针对多处理器系统应用程序的编程进行优化,使用go编译的程序可以媲美C或者C++代码的速度,而且更加安全、支持并行进程。
1.2 GO语言优势
- 可以直接编译成机器码,不需要依赖其他库。部署就是扔一个文件上去就完成了
- 静态类型语言,但是有动态语言的感觉,开发效率高
- 语言层面支持并发,可以充分利用多核,很容易使用的并发
- 内置runtime,支持垃圾回收,特别是GO 1.1之后的GC功能很强大
- 跨平台编译,如果你写的GO代码不包括CGO,那么就可以做到Windows系统编译Linux的应用。
- 内嵌C支持,GO里面也可以直接包含C代码,利用现有丰富的C库
1.3 GO 适合来做什么
- 服务器编程,例如处理日志、数据打包、虚拟机处理、文件系统等
- 分布式系统,数据库代理器等
- 网络编程,这一方面目前应用最广,包括web应用、API应用、下载应用
- 云平台
学习资料
首页 - Go语言中文网 - Golang中文社区
Go语言标准库文档中文版 | Go语言中文网 | Golang中文社区 | Golang中国
2.GO语言环境搭建
2.1 window版本GO语言环境搭建
-
Go下载 - Go语言中文网 - Golang中文社区选择适合下载项(推荐 .msi文件默认下载)
安装后我们可以再cmd中查询GO环境是否搭建成功
- 部署LiteIDE
-
文件解压缩后就可以直接使用了
-
设置文件存储目录以及测试go语言运行情况
书写GO语言时,请牢记把程序类比成商场。
在GO语言中有且只有一个入口就是 main
实现目的就是调用函数
package main
//GO语言是以包作为管理单位
//每个文件必须先声明包
//程序必须有一个main包(极度重要)
import "fmt" //导入函数包
//入口函数
func main() { //左函数必须与main函数同行
//打印
//“hello go”打印到屏幕上,println()会自动换行
//调用函数,大部分都需要导入包
fmt.Println("hello go") //go语言结尾是没有分号的
}
Ctrl +R 执行文件
使用LiteIDE也存在一定的缺点,例如main的唯一性
方法一:每个目录下只生成一个go文件。以保证main函数的唯一性
方法二:在同样目录下建立go文件,使用cmd终端进行验证操作
go build ***.go
执行 ***.go
go run ***。go
二 、GO基础类型
1.变量
变量是几乎所有编程语言中基本的组成元素。从根本上说,变量相当于是对一块数据存储 空间的命名,程序可以通过定义一个变量来申请一块数据存储空间,之后可以通过引用变量名来 使用这块存储空间。Go语言中的变量使用方式与C语言接近,但具备更大的灵活性。
数据类型的作用:告诉编译器我们设定变量应该以多大的内存存储
1.1变量声明
Go语言的变量明方式与C和C++语言有明显的不同。对于纯的变量明,Go语言引入了 关键字var,而类型信息放在变量名之后,示例如下:
var v1 int
var v2 string
package main //必须有一个main包
import "fmt" //导入包,必须要使用
func main() {
//变量的本质:程序运行期间,可以改变的量
//1.声明格式:var 变量名 类型 (声明变量名后必须要使用)
//2.只有声明没有初始化的变量默认值为0
//3.同一个{ }中,声明的变量是唯一的
var a int
fmt.Println("a=", a)
//4.可以同时声明多个变量 var b,c int
a = 10 //变量赋值
fmt.Println("a=", a)
}
---------------结果------------------
go run 03_text.go
a=0
a=10
1.2变量初始化
对于声明变量时需要进行始化的场景,var关键字可以保留,但不再是必要的元素,如下所示:
var v1 int = 10 // 正确使用方法1
var v2 = 10 // 正确使用方法2
v3 := 10 // 正确使用方法3
以上三种用法的效果是完全一样的。与第一种用法相比,第三种用法需要输入的字符数大大减少,是程序员和明程序员的最佳选择。这里Go语言也引入了另一个C和C++中没有的符号 (号和等号的组合:=),用于明确表达同时进行变量声明和初始化的工作。
指定类型已不再是必需的,Go编译器可以从初始化表达式的右值推导出该变量应该声明为哪种类型,这让Go语言看起来有点动态类型语言,尽管Go语言实际上是不折不扣的强类型语言(静态类型语言)。
当然,出现在:=的变量不应该是已经被明过的,否则会导编译错误,比如下面这个写法:
会导类似如下的编译错误:
no new variables on left side of :
1.3变量赋值
在GO语言中,变量初始化和变量赋值是两个不同的概念。下面为声明一个变量之后的赋值过程
var v10 int
v10 = 123
案例展示
//存在着两种方式【func main()内的代码段】
var b int = 10 //初始化 声明变量时,同时赋值(一步到位)
b = 20 //复制 先声明后付制
fmt.Println("b=", b)
//自动推到类型,必须初始化,通过初始化的值确定类型
c := 30
//%T打印变量所属类型
fmt.Printf("c type is %T\n", c)
- printf和printlin的区别
Println 与Printf 都是fmt 包中的公共方法
Println :可以打印出字符串,和变量。
Printf : 只可以打印出格式化的字符串,可以输出字符串类型的变量,不可以输出整形变量和整形。
package main
import "fmt"
func main() {
a := 10
fmt.Printf("a type is %T\n", a)
fmt.Println(a)
fmt.Println("abc")
fmt.Printf("%d", a)
}
-----------结果-----------
a type is int
10
abc
10
除了以上区别,在对变量赋值时,也存在不小的差异。同时对多变量赋值时,推荐使用printf
package main
import "fmt"
func main() {
a := 10
fmt.Println("a = ", a)
fmt.Printf("a = %d\n", a)
b := 120
c := 340
fmt.Println("a =", a, ", b = ", b, ",c = ", c)
//同时对多个变量进行赋值时使用printf效果更好
fmt.Printf("a = %d, b = %d , c =%d\n", a, b, c)
}
Go语言的变量赋值与多数语言一致,但Go语言中提供了C/C++程序员期多年的多重赋值功能,比如下面这个交换i和j变量的语句:
i , j = j , i
- 将j赋值给i,然后再将i赋值给j
多重赋值的特性在Go语言库的实现中也被使用得相当分,在函数的多重返回值时,将对其进行更加深入的。总而言之,多重赋值功能让Go语言与C/C++语言相比可以非常明显地少代码行数。
案例展示
package main
import "fmt"
func main() {
//a :=10
//b :=20
//c :=30
//多重初始化
a, b := 10, 20
fmt.Printf("a = %d, b = %d\n", a, b)
//传统方法交换两个变量的值
var tmp int
tmp = a
a = b
b = tmp
fmt.Printf("a = %d , b = %d\n", a, b)
//GO语言的多重赋值
i, j := 10, 20
i, j = j, i
fmt.Printf("i = %d , j = %d\n", i, j)
}
1.4匿名变量
我们在使用传统的强类型语言编程时,经常会出现这种情况,即在调用函数时为了获取一个值,却因为该函数返回多个值而不得不定义一堆没用的变量。在Go中这种情况可以通过结合使用多重返回和匿名变量来避免这种丑陋的写法,让代码看起来更加优雅
这种用法可以让代码非常清楚,基本上屏蔽掉掉了可能混淆代码阅读者视线的内容,从而大大减低沟通的复杂度和代码维护的难度。
案例展示
package main
import "fmt"
//go函数可以返回多个值
func test() (a, b, c int) {
return 1, 2, 3
}
func main() {
//匿名变量,丢弃数据不处理。
//匿名变量配合函数返回值使用才有优势
i, j := 10, 20
var tmp int
i = 16
j = 27
tmp, _ = i, j
fmt.Println("tmp=", tmp)
var c, d, e int
c, d, e = test()
fmt.Printf("c=%d,d=%d,e=%d\n", c, d, e)
2.常量
在Go语言中,常量是指编译期间就已知且不可改变的值。常量可以是数值类型(包括整型、浮点型和复数类型)、布尔类型、字符串类型等。
2.1常量的定义
- 对单个常量进行定义
package main
import "fmt"
func main() {
//变量:程序运行期间,可以改变的量,变量声明需要var
//常量:程序运行期间,不可以改变的量。常量声明需要const
const a int = 10
// a = 20 这种赋值方式是错误的。不允许给常量赋值
fmt.Println("a=", a)
const b = 10
//在变量赋值时格式为 b :=10
fmt.Printf("b type is %T\n", b)
fmt.Println("b=", b)
}
- 对多个变量或者常量进行定义
package main
import "fmt"
func main() {
var (
a float64 = 3.4
b = 2
)
fmt.Println("a=", a)
fmt.Println("b=", b)
const (
i = 10.246
j int = 10
)
fmt.Println("i=", i)
fmt.Println("j=", j)
}
2.2 枚举
枚举指一系列相关的常量,关键字iota定义常量组中从0开始按行计数的自增枚举值。
package main
import "fmt"
func main() {
//1.iota常量自动生成器,每一行自动累加1
//2.iota给常量赋值使用
const (
a = iota // 值为0
b = iota // 值为1
c = iota // 值为2
)
fmt.Printf("a = %d , b=%d ,c =%d\n", a, b, c)
//3.iota每次 遇到const均重新赋值为0
const d = iota
fmt.Printf("d =%d\n", d)
//4.可以只书写一个iota,后续电脑自行推到
const (
a1 = iota
b1
c1
)
fmt.Printf("a1 = %d , b1=%d ,c1 =%d\n", a1, b1, c1)
//5.iota如果在同一行,其值均相等
const (
i = iota
j1, j2, j3 = iota, iota, iota
k = iota
)
fmt.Printf("i = %d , j1=%d , j2=%d, j3=%d,k =%d\n", i, j1, j2, j3, k)
}
3.数据类型
3.1基本数据类型
3.2布尔类型
func main() {
//1.声明变量
var a bool
fmt.Println("a0=",a) //判断布尔类型零值
a = true
fmt.Println("a=", a)
//2.自动推到类型
var b = false
fmt.Println("b=", b)
c := false
fmt.Println("c=", c)
}
3.3浮点数类型
- float 64 比float 32精度更加准确
//声明变量
var f1 float32
f1 = 3.1415926
fmt.Println("f1=", f1)
//自动推到类型
f2 := 3.99
fmt.Printf("f2 type is %T\n", f2)
3.4字符(串)类型
- 字符类型
在go语言中支持两个字符类型,一个是byte,代表utf-8字符串的单个字节的值,另一种是rune,代表单个Unicode字符
var ch byte //声明字符类型
ch = 97
fmt.Println("ch =", ch)
//格式化输出,%c是以字符方式打印,%d是以整型方式打印,%T是以格式类型打印
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)
// ‘\’以反斜杠开头的字符是转移符
fmt.Printf("hrllo word%c", '\n')
fmt.Printf("hello 比卡丘")
- 字符串类型
字符串是不可变值类型,内部用指针指向UTF-8字节数组
var str1 string //声明变量
str1 = "abc" // 字符为单引号,而字符串为双引号
fmt.Println("str1=", str1)
//自动推导类型
str2 := "mike"
fmt.Printf("str2 类型是 %T\n", str2)
//内建函数,len()可以测字符的长度,有多少个字符
fmt.Println("len(str2)=", len(str2))
注意:字符与字符串的区别
- 字符单引号控制,除转义字符(\n)外往往都只有一个字符。
- 字符串双引号控制字符串有一个或者多个字符组成,字符串都是隐藏了一个结束符(\0)的
ch := 'a'
fmt.Println("ch =", ch)
str := "hello go"
fmt.Println("str =", str)
fmt.Printf("str[0]=%c,str[1]=%c\n", str[0], str[1])
3.5 复数类型
var t complex128
t = 2.1 + 3.14i
fmt.Println("t =", t)
//自动推到类型
t2 := 3.3 + 4.4i
fmt.Println("t2 type is %T\n", t2)
//通过内建函数,取实部和虚部
fmt.Println("real(t2)=", real(t2), "imag(t2)=", imag(t2))
4.fmt包的格式化输出输入
4.1输出的使用
a := 10
b := "abc"
c := 'a'
d := 3.14
// %T操作变量所属类型
fmt.Printf("%T ,%T ,%T,%T\n", a, b, c, d)
fmt.Printf("a=%d ,b=%s ,c=%c,d=%f\n", a, b, c, d)
fmt.Printf("a=%v ,b=%v ,c=%v,d=%v\n", a, b, c, d) //%v自动匹配格式
4.2输入的使用
var a int //声明变量
fmt.Printf("请输入变量a:")
//阻塞等待用户的输入
// fmt.Scanf("%d", &a) //别忘记加&
fmt.Scan(&a)
fmt.Println("a=", a)
5.类型转换与别名
5.1类型转换
var a int //声明变量
fmt.Printf("请输入变量a:")
//阻塞等待用户的输入
// fmt.Scanf("%d", &a) //别忘记加&
fmt.Scan(&a)
fmt.Println("a=", a)
5.2类型别名
//给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)
6.运算符
6.1算术运算符
6.2关系运算符
fmt.Println("4 > 3结果:", 4 > 3)
fmt.Println("4 != 3 结果:", 4 != 3)
--result------------------
H:\golang>go run 08_字符串类型.go
4 > 3结果: true
4 != 3 结果: true
6.3 逻辑运算符
fmt.Println("!(4 > 3)结果:", !(4 > 3))
fmt.Println("!(4 != 3) 结果:", (4 != 3))
//&&与 ,并且,左边右边都为真,结果才是真
fmt.Println("true && true 结果", true && true)
fmt.Println("true && true 结果", true && false)
// ||或者,左边右边都是假,结果才是假,其他情况都是真
fmt.Println("true || true 结果", true || true)
fmt.Println("true || true 结果", true || false)
特别注意:当关系与逻辑运算相结合时。无区间定义
- 在go语言中bool类型和int类型不兼容
#判断一个数字,是否在0-10的范围内
a := 8
fmt.Println("0 <= a && a <= 10结果是", 0 <= a && a <= 10)
6.4位运算符
6.5 赋值运算符
6.6 其他运算符
6.7运算优先级
在go语言中,一元运算符拥有最高优先级,二元运算符的运算方向均是从左至右。