Go语言的出现是为了解决当下编程语言以下的问题:
- 对并发支持不友好
- 编译速度慢
- 编程复杂
Go语言能干什么事?
- 服务器编程,以前你如果使用C或者C++做的那些事情,用Go来做很合适,例如处理日志、数据打包、虚拟机处理、文件系统等。
- 分布式系统、数据库代理器、中间件等,例如Etcd。
- 网络编程,这一块目前应用最广,包括Web应用、API应用、下载应用,而且Go内置的net/http包基本上把我们平常用到的网络功能都实现了。
- 数据库操作
- 开发云平台,目前国外很多云平台在采用Go开发
token
token是构成源程序的基本不可再分割的单元。
编译器编译源程序的第一步就是将源程序分割一个个独立的token,这个过程就是词法分析。
token可以分为关键字、标识符、操作符、分割符合字面常量等。
将源程序分割成token是借助分割符来实现,分割符主要有两类:
- 操作符:+、-、*、/ 等等,操作符是分割符,也是一种token
- 纯分割符:包括空格、制表符、换行符合回车符,其本身不具备任何语法含义,只作为其他token的分割功能。
Go语言一共支持25个关键字,主要分为三类。
引导程序整体结构的8个关键字
-
package //定义包名
-
import //导入包名
-
const //常量声明
-
var //变量声明
-
func //函数定义
-
defer //延迟执行
-
go //并发语法糖
-
return //函数返回
声明复合数据结构的4个关键字
- struct //定义结构类型
- interface //定义接口类型
- map //声明或创建map类型
- chan //声明或创建通道类型
控制程序结构的13个关键字
- if else //if else 语句关键字
- for range break continue //for 循环使用
- switch select type case default fallthrough //switch和select语句使用的关键字
- goto //goto跳转语句
Go语言提供了20种数据类型
整数(12个):byte int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr
浮点数(2个):float32 float64
复数型(2个):complex64 complex128
以上几种的数据类型转换可通过强制类型装换来实现
var count int = 5
var mean float32 = float32(count)
字符和字符串型(2个):string rune
字符串与数字的转化是借助strconv来实现的
补充: = 是赋值, := 是声明变量并赋值 并且系统自动推断类型,不需要var关键字
1 2 3 4 5 6 7 8 9 10 | package main import ( "fmt" "strconv" ) func main() { c,err := strconv.ParseFloat(b,64) //这里是短类型声明的方式,可以同时对多个变量进行赋值 _ = err //(_是空白标识符) err是操作失败赋予的默认值,这句是解决err没有被使用的报错 fmt.Println("Hello, World!",c) } |
接口型(1个):error
布尔型(1个):bool
其他
内置函数(15个): make new len cap append copy delete panic recover close complex real image print println
常量值标识符(4个)
- true false
- inta //用在连续的枚举类型的声明中
- nil //指针、引用型的变量的默认值就是nil (可以理解为null)
- 空白标识符(1个):_ //用来声明一个匿名的变量,通常用来占位,避免变量未使用,编译不通过。
Go语言支持的复合数据类型
复合数据类型指的是其他类型组合而成的类型。Go语言支持一下的复合数据类型:
- 指针
- 数组
- 切片
- 字典
- 通道
- 结构
- 接口
指针
Go语言支持指针,指针的声明类型为*T,Go同样支持多级指针**T。
指针是一种保存变量地址的变量.
对于普通变量,只允许修改它的内容;对于指针,可以修改指针变量的指向地址和该地址的内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //普通数据 a := 123 b := &a //b++ Go禁止指针运算 //结构体 type User stuct{ name string age int } andes := User{ name : "luo" age : 18 } p := &andes |
数组
数组创建完长度就固定了,不可以再追加元素
数组初试化的方式有以下方式:
1.指定长度和初始化字面量
1 | array :=[3] int{1,2,3} |
2.不指定长度,但是由后面的初始化列表数量来确定其长度
1 | array :=[...]int{1,2,3} |
3.指定总长度,并通过索引值进行初始化,没有初始化元素时使用类型默认值
1 | array :=[3]int{1:1,2:3} |
4.不指定总长度,并通过索引值进行初始化,没有初始化元素时使用类型默认值
1 | array :=[...]int{1:1,2:3} |
数组操作
方式一
1 2 3 4 5 | array :=[...]int{1,2,4} for i,v := range array{ fmt.Println("Hello, World!", v) _ = i } |
// i是索引值,v是真实值
//输出结果
Hello, World! 1
Hello, World! 2
Hello, World! 4
方式二
1 2 3 4 5 | array :=[...]int{1,2,4} alengh := len(array) for i:=0;i<alengh;i++ { fmt.Println("Hello, World!", array[i]) } |
切片
切片(slice)是一种变长数组,其数据结构中有指向数组的指针,所以是一种引用类型。
其结构如下:
1 2 3 4 5 | type slice struct { array unsafe.Pointer //指向底层数组的指针 len int //切片的元素数量 cap int //底层数组的容量 } |
1.由数组创建切片
1 2 3 4 5 6 7 | array :=[...]int{1,2,3,4,5,6,7} s1 := array[0:5] //获取 array[0] -array[4] s2 := array[:5] //获取 array[4]之前所有的 s3 := array[2:5] //获取 array[2] 到 array[4] fmt.Println(s1) fmt.Println(s2) fmt.Println(s3) |
结果是:
[1 2 3 4 5]
[1 2 3 4 5]
[3 4 5]
2.通过内置函数make创建切片
由内置函数make创建的切片个元素被默认初始化为切片元素类型的零值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //len=10,cap=10 aslice := make([]int, 10) //len=10,cap=15 bslice := make([]int,10,15) fmt.Println(aslice) fmt.Println(bslice) //获取切片长度 fmt.Println(len(aslice)) //获取切片底层数组容量 fmt.Println(cap(aslice)) //对切片追加元素 bslice = append(bslice,1) fmt.Println(bslice) fmt.Println("拷贝前的aslice",aslice) fmt.Println("拷贝前的bslice",bslice) //用于复制一个切片,只会复制aslice、bslice中最小的 copy(aslice,bslice) fmt.Println("拷贝后的aslice",aslice) fmt.Println("拷贝后的bslice",bslice) |
结果为:
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
10
10
[0 0 0 0 0 0 0 0 0 0 1]
拷贝前的aslice [0 0 0 0 0 0 0 0 0 0]
拷贝前的bslice [0 0 0 0 0 0 0 0 0 0 1]
拷贝后的aslice [0 0 0 0 0 0 0 0 0 0]
拷贝后的bslice [0 0 0 0 0 0 0 0 0 0 1]
3.字符串和切片的相关转换
1 2 3 4 5 | str :="hello,世界!" a := []byte(str) //将字符串转换为[]byte类型的切片 b := []rune(str) //将字符串转换为[]rune类型的切片 fmt.Println(a) fmt.Println(b) |
结果:
[104 101 108 108 111 44 228 184 150 231 149 140 33]
[104 101 108 108 111 44 19990 30028 33]
map
map是一种引用类型,又称为字典类型。map[K]T K是key的类型 T是value的类型
1.map的创建
方式一:使用字面量创建
1 2 3 | ma :=map[string]int{"a":1,"b":2} fmt.Println(ma["a"]) fmt.Println(ma["b"]) |
结果:
1
2
方式二:使用内置的make函数创建
make(map[K]T) //map的容量使用默认值
make(map[K]T,len) //map的容量使用给定的len值
1 2 3 4 5 6 | mp1 :=make(map[int]string) mp2 :=make(map[int]string,10) mp1[1] = "luo" mp2[1] = "king" fmt.Println(mp1[1]) fmt.Println(mp2[1]) |
结果:
luo
king
map的操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //遍历操作 mp1 :=make(map[int]string) mp1[1] = "luo" mp1[2] = "nice" //删除 delete(mp1,1) for k,v := range mp1{ fmt.Println("key=",k,"value=",v) } //修改 mp1[2] = "bad" for k,v := range mp1{ fmt.Println("key=",k,"value=",v) } |
结果:
key= 2 value= nice
key= 1 value= luo
key= 2 value= nice
key= 2 value= bad
备注:
1.如果map的Value的类型是引用类型的话,不能够直接使用 ma[1].age =12 方式进行修改
要修改对象后,替换整个元素
2.map不是并发安全地,并发安全的map可以使用标准包sync中的map.
struct
Go中的struct类型和C类似,即为结构
struct的声明以及赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | package main import ( "fmt" ) type Person struct{ name string age int } type Class struct{ Person number int } func main() { p := Person{ name: "luo", age: 18, } c :=Class{ Person :p, number:12, } fmt.Println(p) fmt.Println(c) } |
结果:
{luo 18}
{{luo 18} 12}