1.数据类型:
(1)布尔类型
(2)数字类型:整形,浮点型,复数
(3)字符串类型
(4)派生类型:指针,数组,结构体,Channel(通道类型,先进先出的队列,各个协程之间同步),函数,切片,接口,map
2.变量声明:
(1)
var a int 声明后若不赋值,使用默认值,相同代码块变量声明之后不能再被声明
a := 10 //ok
a = 10 //error
var b int = 10
var c = “abc” 自动判断类型
d := 10 去掉var,自动判断类型,:=前的变量不应该是已经声明过的
(2)
多变量声明:
Var vname1, vname2, vname3 type = 1, 2, 3
Vname1, vname2, vname3 := 1, 2, 3
Var (
a int
b string
)//一般用于全局变量生命
const (
a = 10
b = “str”
)//用于声明常量,不使用:=的方式
(3)
iota:特殊常量,可以被编译器修改,与const一起使用
每一个const出现时重置为0,下一个const出现之前,每出现一个iota,自动加一
const (
a = iota //0
b = "ha" //独立值:iota+1
f = "ha" //2
c = 10 //3
d = iota //4
)
const (
e = iota //下一个const出现,iota重置为0
)
值类型与引用类型(例:两数交换)
int,float,bool,string都属于值类型,使用=赋值或传参实际上把内存中的值进行拷贝
Var a int = 10
p1 := &a
p2 := &a
*p1 = 20 //指针前加*获取指针指向的内容,空指针值为nil
func trueSwap(str1 *string, str2 *string) {
var temp string
temp = *str1
*str1 = *str2
*str2 = temp
}
func falseSwap(str1 string, str2 string) {
var temp string
temp = str1
str1 = str2
str2 = temp
}
3.语言结构:
包声明
引入包
函数
变量
语句&表达式
注释 // /**/
(1)import中,或者定义的变量,没有使用,编译时都会报错
(2)包中名称已大写字母起始为可导出的函数,可以在包的外部调用
4.循环语句,条件语句:
for循环,无while循环:
for循环中使用range,迭代数组,切片,通道,map中的元素
hashMap := map[string]string{"a": "apple", "b": "banana"}
for k, v := range hashMap {
fmt.Println(k, ":", v)
}
判断map中元素是否存在,有key,则ok为true,否则false
_, ok := hashMap["key"]
nums := []int{1, 2, 3}
元素遍历(数组,map等都适用)
for index, value := range nums {
fmt.Println(index, value)
}
索引遍历(数组,map等都适用)
for i := range nums {
fmt.Println(nums[i])
}
支持嵌套循环,break,continue,goto
if...else语句:
if true {
} else { //if...else的正确格式
}
switch语句(除正常使用外,可判断类型)
参数i的类型为空接口,空接口可接收任何类型数据
func getType(i interface{}) {
switch i.(type) {
case string:
fmt.Println("string")
case int:
fmt.Println("int")
default:
fmt.Println("unknow")
}
}
还可通过反射直接获取变量类型信息,需要引入reflect包
reflect.TypeOf(i)
select语句:监听io操作,当io操作发生时,触发相应的动作
Select的每一个case必须是io操作,要么是发送要么是接收
Select随机执行一个可运行的case,如果没有case可运行,它将阻塞,直到有case可运行
select实现timeout机制:
timeout := make(chan bool, 1)
go func() {
time.Sleep(1e9)
timeout <- true
}()
ch := make(chan int)
select {
case <-ch:
case <-timeout:
fmt.Println("timeout!")
}
select中的default,实现服务繁忙,请稍后再试的功能:
ch := make(chan int, 5)
for {
select {
case ch <- 1:
//处理客户端连接
fmt.Println("put one...")
default:
//告知新连接客户服务繁忙,稍后再试
fmt.Println("channel is full!")
}
}
5.数组:向函数传递数组(len:获取元素个数)数组长度不可改变
func printArray(array [][]int) {
length := len(array)
for i := 0; i < length; i++ {
for j := 0; j < len(array[i]); j++ {
fmt.Println(array[i][j])
}
}
}
(1)参数为数组,返回当前维度元素个数
(2)参数为指向数组的指针p,返回*p的元素个数
(3)slice,map,channel等,代表其存储元素的个数
6.指针:
空指针:nil
指针数组:
var array = [5]int{1, 2, 3, 4, 5}
var pArray [len(array)]*int
for i := 0; i < len(array); i++ {
pArray[i] = &array[i]
fmt.Println(pArray[i], *pArray[i])
}
数组指针:
var array = [5]int{1, 2, 3, 4, 5}
pArray := &array
for i := 0; i < len(array); i++ {
fmt.Println(pArray[i])
}
指针的指针:
a := 10
b := &a
c := &b
fmt.Println(a, b, *b, c, *c, **c)
结构体指针:(使用结构体指针访问结构体成员,使用”.”操作符)
type Person struct {
name string
age int
}
mtt := Person{"mtt", 22}
p := &mtt
fmt.Println(mtt.name, mtt.age, p.name, p.age)
7.切片(Slice):动态数组,长度可变,使用make创建切片
(1)切片定义:
var array []int = make([]int, length, capacity)
//capacity为切片容量,可选,不指定容量和length一样大小,增长方式:2的n次方
numbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8} //[]没有数字则为切片,有数字则为数组
(2)切片截取
s := arr[startIndex:endIndex]
//s为数组array引用,也可使用这种方式对切片进行截取,对s修改则会对原数组进行修改
(3)append()和copy()函数
append用法一:
array = append(array, 1)
//从切片长度的下标开始追加元素,返回值必须有变量接收,否则编译出错
append用法二:
number3 := append(number1, number2...)
//将两个切片拼接在一起
copy:
copy(slice2, slice1)
//将切片1中len(slice1)大小的元素拷贝到切片2中
//slice2的len,cap还是自己的
//若slice2长度小于slice1,则只拷贝len(slice2)大小的元素
(4)切片由三部分组成:指向底层数组的指针,len,cap分别为8个字节
unsafe.Sizeof(slice) //大小为24
8.接口:
(1)结构体实现了接口的所有方法,才算实现了该接口,否则便宜出错
(2)接口的赋值:
将对象实例赋值给接口
将接口赋值给接口(接口类型转换,超集到子集可以)
(3)接口类型不包含任何成员
(4)重写Error()方法即实现了error接口
9.错误处理:
(1)defer延迟语句:不管程序是否出现异常,在函数退出时自动执行相关代码,多个defer语句按照FIFO的原则执行,常用来关闭或释放资源
文件拷贝使用defer示例:
func copyFile(dstName string, srcName string) (copylen int64, err error) {
src, e1 := os.Open(srcName)
if e1 != nil {
return
}
defer func() { //defer后+匿名函数,实现更多的操作
src.Close()
}()
dst, e2 := os.Create(dstName)
if e2 != nil {
return
}
defer func() { //函数退出时先执行此defer,再执行上一个defer
dst.Close()
}()
return io.Copy(dst, src)
}
(2)panic(),recover(),运行时异常处理机制:
使用panic()发起错误,在defer()语句中使用recover()捕获错误
10.并发与并行的区别:
两个队列,一个coffee机,并发
两个队列,两个coffee机,并行
(1)开启一个协程:go func()
(2)当前的协程不发生阻塞,是不会让出cpu给其它协程,使用runtime.GOMAXPROCS(2) //runtime调度器设置最大可同时使用cpu核数,来达到并行
11.信道:channel
(1)使用make创建:var channel chan int = make(chan int)或 channel := make(chan int)
(2)channel <- message //向信道中存消息
message <- channel //从信道中取消息
当不设置信道大小时,默认为1(无缓冲信道)
信道满存不进数据,信道空取不出数据,都会挂起当前协程,直到可以存取
(3)缓冲信道:设置合理的信道大小,可明显提高数据在信道之间传输效率
close(channel),len(channel):显式关闭信道或根据信道存储元素个数来防止阻塞,死锁