一、基础
1、声明变量与常量
(1)变量声明的三种方式
var i int=16
var i=16
i :=16
(2)声明常量
const pi=3.1415926
const(
e=2.156132
E=1.251515
)
(3)变量声明注意事项
var(
i int
b bool
)
_,result:=func()
(4)常量声明注意事项
const(
a=100
b
c
d
)
const(
a=iota
b
c
_
d
)
const (
aq,ao=iota+1,iota+4
af,as
ap,ah
)
2、基本数据类型
(1)整型
包括无符号整型:uint8=>byte,uint16,uint32,uint64
有符号整型:int8,int16,int32,int64
特殊类型:
int=>32位电脑32,64位电脑64
uint=>同上
uintptr=>用来存放指针
(2)浮点型:float32,float64
(3)bool型:false,true
(4)字符串类型:
var s string="哈哈哈哈哈哈\n"==>哈哈哈哈哈哈
var s string=`哈哈哈哈哈哈\r\n`==>哈哈哈哈哈哈哈\r\n
(5)byte和rune类型
byte表示字节型,rune表示字符型(可用来表示汉字)
(6)类型转换
1、T(type)=>转换为t类型
2、strconv.prase()字符串类型转别的类型
3、strconv.format()别的类型转字符串类型
3、流程控制
(1)for循环
for{}
for i>=10{}
for i:=10;i>=10{}
for i:=0;i<=10;i++{}
for _,v :=range 数组名称{}
(2)switch-case
switch {
case bool判断:
case bool判断:
}
switch c{
case 'a','b':
}
4、数组
(1)定义数组
var i=[...]int{}
var i=[4]int{}
(2)注意
数组赋值和传参直接传的是值,所以更改的只是一个副本
数组之间可以进行==和!=的比较
5、切片
(1)定义
arr :=[...]int{1,2,3,4,5}
slice := arr[a:b:c]
===========>len(slice)=b-a cap(slice)=c-a
slice :=[]int{11,15,13}
slice :=make(int,a,b)
(2)切片底层
type slice struct{
array *notInHeap
len int
cap int
}
(3)切片的容量与长度
长度:append添加数据时,添加的数据是往len长度之后添加的
容量:当容量满了之后需要扩容时,将会使用扩容
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
if old.cap < 1024 {
newcap = doublecap
} else {
for 0 < newcap && newcap < cap {
newcap += newcap / 4
}
if newcap <= 0 {
newcap = cap
}
}
}
(4)切片追加数据
slice :=make(int,4,4)
slice2 :=[]int{1,2,3}
slice=append(slice,1,2,3,5)
slice=append(slice,slice2...)
(5)切片拷贝
注意:一定要初始化容量大小,拷贝的容量大小是根据len来的
s :=[]int{8,11,55,15,16}
var fpx []int=make([]int,5,7)
ace :=fpx[2:7:7]
copy(ace,s[:])
fpx=append(fpx, 99)
fmt.Println(fpx,s,ace)
fmt.Println(&fpx[2],&s[0],&ace[0])
[0 0 8 11 55 99] [8 11 55 15 16] [8 11 55 99 16]
0xc000010250 0xc00000c330 0xc000010250
结论:
在不触发任意一个切片扩容的前提下,操作的还是同一个数组
(6)删除
切片删除只能根据特性,实际上生成了新的切片并将指针返回去
var slice=[]int{1,2,3,4,5,6}
append(slice[:2],slice[3:])
6、map
(1)定义
公式 map[key类型]value类型
var m map[string]int=make(map[string]int,b)
var m=map[string]int{
"sss":11,
"ppp":12,
}
(2)增删改查
var m :=make(map[string]interface{},6)
m["张三"]=16
delate(m,"张三")
m["张三"]=18
v,b :=m["张三"]
(3)注意事项
map中存切片,若切片发生扩容,地址将发生变化,
此时map中的切片原地址将发生变化,所以需要及时维护
var nice =make([]int,1)
var mc=make(map[string][]int,3)
nice[0]=12
mc["zhangzhang"]=nice
nice=append(mc["zhangzhang"],13)
mc["zhangzhang"]=append(mc["zhangzhang"],13)
7、函数
(1)定义
func (专属函数t type)add(入参a int) (返回值i int){}
type person struct{
name string
age int
}
func (p person)say(name string,age int){
fmt.println("i`am---->",p.name)
}
func add(a int,b int)int{
retuen 0;
}
type two func(int,int)int
var t two
t=add
(2)应用
函数可以作为参数,也可以作为一个返回值
func add(a int,op func(int,int)int)int{}
func acc(a int)(fun(int,int)int){}
(3)匿名函数
回调函数
func (a int,b int)int{
}(5,10)
闭包=环境+函数
func sum()func(int,int)int{
var i int
return func(f,v int)int{
i+=f^v
return i
}
}
v :=sum()
v(3,5)
(4)defer
注意:
只能执行在函数语句之前,且只作用在最外层函数
注册时若函数有参数,则要先确定函数的参数值
执行的时机在return赋值之后,ret之前
func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
}
func main() {
x := 1
y := 2
defer calc("AA", x, calc("A", x, y))
x = 10
defer calc("BB", x, calc("B", x, y))
y = 20
}
打印结果:
A 1 2 3
B 10 2 12
BB 10 12 22
AA 1 3 4
(5)异常处理
panic()用来抛出异常,类似于java中的throw(不会继续执行)
recover()可以用来处理异常,要配合defer使用,且在异常之前
func f2() (x int) {
defer func() {
error := recover()
if error!=nil {
fmt.Println("f2 error")
}
}()
panic("错了我的宝")
x=555
return x
}
即使捕获到了异常,这里的值也不会正常返回,但会执行下边
8、指针
(1)make和new
二者都是用来做内存分配的,make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。
9、结构体
(1)定义
type rune int32
type i=int
type person struct{
name string
age int8
}
(2)使用
var p = new(person)
var p = &person{}
var p = person{name:"牛德华",age:12}
var person struct{name string;age int}
(3)结构体字节对齐
1、偏移量必须为变量自身的长度的倍数,结构体中第一位无偏移量
2、若成员变量所占字节长度大于编译器默认对齐长度时取编译器默认对齐长度
3、结构体整体对齐长度为编译器默认对齐长度的倍数
4、编译器默认对其长度可更改,64位电脑默认为8字节,32位默认4字节
type person struct{
name string
age int8
sex int32
money int64
b bool
}
5、总结:多数情况下,尽量将所占内存小的往前边写
(4)结构体成员嵌套与匿名
type person struct{
name string
age int8
}
type student struct{
p person
schoolName string
}
type person struct{
string
int
}
(5)继承
type animal struct{
name string
age int8
}
type dog struct{
animal
color string
}
注意:
继承的方法名,参数,返回值必须要相同
(6)封装
在成员变量的首字母小写时实现封装,此成员变量只有本包可见
(7)json序列化与反序列化
序列化:data, err := json.Marshal(c)
反序列化:err = json.Unmarshal([]byte(str), c1)
注意:在使用json函数时,一定要确保属性字段可见才可以获取到
(8)为结构体定义tag
type person struct{
Id int `json:"Id" ps:"hhshsh"`
}
后边反引号组成的便是tag,可以多个可以一个,必须严格遵守此格式
10、导包
(1)常见错误
经常会遇到导入自己的包报错的情况,或者没有报错但是提示找不到包,这个时候需要配置

执行go mod init

(2)init函数
在go语言中,一个go文件的初始化从init()函数开始
1、首先会根据import形成一个树形结构,从最后导入的依赖的init开始执行
2、init函数不能主动调用,在程序执行时会自动调用
3、init函数没有参数也没有返回值
11、接口
12、反射