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}