go语言学习笔记

 

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):显式关闭信道或根据信道存储元素个数来防止阻塞,死锁

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值