Lab1
lab1[toc]
1 Producer-Consumer problem参考博客1
参考博客2
参考博客3
参考博客4
也称 有限缓冲问题 Bounded-buffer problem
多线程同步的问题
1.1 信号量配合互斥锁
信号量特性:
非负整数,对共享资源和线程的控制
通过信号量的线程会使得信号量减一,当为零时,所有试图通过的线程等待
操作:
Wait:线程调用该函数时
要么得到资源并将信号量减一
要么线程进入等待队列,直到信号量大于零
Release:在信号量上执行加一
释放由信号量守护的资源
Wait,Release再Linux中:
int sem_wait(sem_t* sem)
int sem_post(sem_t* sem)
针对该问题:
设定两个信号量:
empty: 空槽的个数
full: 占有的个数
生产者 向任务队列 放资源时,调用 sem_wait(&empty) 检查队列是否已满,
若满,就阻塞,直到有消费者从队列里取资源
若不满,就放入资源,并通知消费者取
消费者 从任务队列 取资源时,调用 sem_wai ...
17 网络编程
17 网络编程
使得程序相互通信
演示使用net 包进行TCP 和UDP 通信
互联网协议介绍
互联网的核心是一系列协议,总称为互联网协议 (Internet Protocol Suite)
这一系列协议规定了电脑如何连接和组网
互联网分层模型
互联网的逻辑实现:
![osi七层模型](E:\LearningNotes\Go\17 网络编程.assets\osi.png)
互联网按照不同的模型划分为不同的分层
无论按照什么模型划分:越往上的层越 靠近用户,越往下的层越 靠近硬件
物理层
电脑与外界互联网通信
先把电脑连接网络:使用 双绞线、光纤、无线电波 等方式
实物理层:把电脑连接起来的物理手段
主要是规定了网络的一些电气特性,作用是负责传送 0 和 1 的电信号
数据链路层
功能:规定解读电信号的方式,确定了物理层传输的 0 和 1 的分组方式及代表意义
例如:多少电信号算一组?每个信号位有何意义
以太网 (Ethernet) 的协议占据了主导地位
以太网 规定,一组电信号构成一个数据包,叫做 帧Frame
一个帧:标头Head 和 数据D ...
16 并发
16 并发[toc]
Go 语言 在语言层面天生支持并发
并发 与 并行
并发:在同一时间段内执行多个任务
用微信和两个人聊天
并行:同一时刻执行多个任务
我和朋友都在用微信别人聊天
Go 的并发通过goroutine 实现
goroutin 类似于线程,属于用户态的线程,可以创建许多个goroutine 并发工作
goroutine 是 由Go 语言运行时,调度完成,而线程是由操作系统调度完成
Go 还提供channel 在多个goroutine 间进行通信
goroutine 和 channel 是Go 语言秉承的 CSP(Communicating Sequential Process) 并发模式的重要实现基础
goroutine
java/c++ 中实现并发编程:耗费大量心智
需要自己维护一个线程池,
需要自己去包装一个又一个任务
需要自己去调度线程执行任务并维护上下文切换
Go 中goroutine 机制:程序员自己定义多个任务,让系统帮助我们将任务分配到 CPU 上实现并发
goroutine :类似于线程,由Go 在 runtime 时调度和管理
...
15 反射
15 反射变量的内在机制
Go 的变量分为两部分
类型信息:预先定义好的元信息
值信息:程序运行过程中可动态变化的
反射介绍
程序运行时 对程序本身进行访问和修改的能力
一般,程序在编译时,变量被转换成内存地址,变量名不会被编译器写道可执行部分
在运行程序时,程序无法获取自身的信息
但对于支持反射的语言,在程序编译时会将变量的反射信息(字段名、类型信息、结构体信息等)整合到可执行文件中,并给程序提供 接口 访问反射信息
Go 在运行期间 使用 reflect包 访问程序的反射信息
reflect 包
在 Go 的反射机制中,任何接口值 都是由一个具体类型 和 具体类型的值 两部分组成
反射相关功能由 内置 reflect 包提供,
任意接口值在反射中都可以理解为reflect.Type 和 reflect.Value 两部分,
reflect 包提供了reflect.TypeOf reflect.ValueOf 获取任意对象的 Value 和 Type
TypeOf
使用reflect.TypeOf() 可以获得任意值的类型对象(reflect.Type), 程序通过 ...
14 接口
14 接口
Interface 定义了一个对象的行为规范,
只定义规范而不实现,由具体的对象来实现规范的细节
接口类型
`Interface ·是一种抽象的类型
Interface 是一组 method的集合,是 duck-type programming的一种体现
接口的作用:定义一个协定(规则),
不用关心其数据,和方法具体是什么
`Interface· 是一种类型
为什么使用接口
```gotype Cat struct{}
func (c Cat) Say() string { return “喵喵喵” }
type Dog struct{}
func (d Dog) Say() string { return “汪汪汪” }
func main() {
c := Cat{}
fmt.Println("猫:", c.Say())
d := Dog{}
fmt.Println("狗:", d.Say())
}
123456789101112131415161718* 共同特点:都会叫 * ...
13 包
13 包
在工程化Go 开发项目中,Go 的源码复用建立在 包 基础之上
定义包、导出包内容、导入其他包
包介绍
package 是多个Go 源码的集合,高级的代码复用方案
内置包:fmt, os,io
定义包
一个包 简单理解为存放.go文件的文件夹
该文件夹下的所有go文件,都要在代码第一行添加package 包名,声明该文件归属的包
==注意:==
一个文件夹下,直接包含的文件只能归属于一个package, 同样一个package文件不能在多个文件夹下
包名不可以和文件夹名一样
包名为main的包,是程序的入口包,这种包编译后会得到一个可执行文件,而编译不包含main包的源代码则不会得到可执行文件
可见性
如果想在一个包中,引用另一个包里的 标识符,该标识符必须对外可见(public),
Go 中只需要将标识符的首字母大写,即为public
```gopackage pkg2
import “fmt”
// 包变量可见性
var a = 100 // 首字母小写,外部包不可见,只能在当前包内使用
// 首字母大写外部包可见,可在其他包中使用const Mode ...
12 结构体
12 结构体
Go 中无 ·类· 的概念,不支持类的继承等面向对象的概念
通过 结构体的内嵌再配合接口 比面向对象具有更高的扩展性和灵活性
类型别名和自定义类型自定义类型
Go 中的基本数据类型:string, int… ,浮点数等
Go 可以使用type 关键字定义自定义类型
自定义类型:定义了一个全新的类型
可以基于内置基本数据类型
可以通过struct定义
type name T
name 就是一种新类型,具有 T类型的特性
类型别名
类型别名规定:type TypeAlias = Type
TypeAlias 只是Type 的别名,
本质上是同一个类型
rune 和 byte 就是类型别名:
type rune = int32
type byte = uint8
类型定义 和 类型别名的区别
type NewInt int : %T : main.NewInt
type MyInt = int: %T : int
结果显示a的类型是main.NewInt,表示main包下定义的NewInt类型。
b的类型是int。MyInt类型只会在代码中存在,编译完成时并 ...
11 指针
11 指针
与C/C++ 中的指针不同,Go 中的指针不能进行偏移和运算,是安全指针
取地址符:&
根据指针取值:*
需要知道:指针地址、指针类型、指针取值
指针地址和指针类型
每个变量运行时都有一个地址,代表变量在内存中的位置
指针类型:*int…
取变量指针的语法:ptr := &v
v : 被取地址的变量
ptr :接收地址的变量,ptr 的类型就为*T,称为T的指针类型
指针取值
对普通变量使用 & 取地址后,会获得这个变量的指针
可以对指针使用*操作,对指针取值
根据指针去内存取值
总结: 取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。
变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:
对变量进行取地址(&)操作,可以获得这个变量的指针变量。
指针变量的值是指针地址。
对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值。
定义函数时,可以传入地址,使用指针传值
new 和 make
Go 中对于引用类型的变量,我们在使用时,不仅要声明它,还 ...
10 内置函数介绍
10 内置函数介绍
内置函数
介绍
close
关闭 channel
len
求长度(string, array, slice, map, channel)
new
分配内存,主要用来分配值类型,int,struct。返回的是指针
make
分配内存,主要用来分配引用类型,chan,map, slice
append
用来追加元素到数组、slice
panic, recover
做错误处理
panic/recover
Go 无异常机制,但是使用 panic/recover 模式来处理错误
panic 可在任何地方引发,但recover 只有在**defer 调用的函数中**有效
例子:
12345678910111213141516func funcA() { fmt.Println("func A")}func funcB() { panic("panic in B") //panic}func funcC() { fmt.Println("fu ...
9 函数进阶
9 函数进阶变量作用域全局变量
定义于函数外部,在程序整个运行周期内有效
局部变量
函数内定义的变量无法在该函数外使用
若局部变量和全局变量重名,优先访问局部变量
if 条件判断、for循环、switch语句块中定义的变量,只能在该语句块中使用
函数类型与变量定义函数类型
使用关键字type 定义一个函数类型,格式:
type calculation func(int,int) int
定义了一个calculation 类型,一种函数类型,接收两个int类型参数并且返回一个int类型
满足 参数列表一致并且返回值列表一致的 都是某一函数类型
var c calculation
函数类型变量
可以 声明函数类型的变量并且为该变量赋值
```gofunc main() {
var c calculation // 声明一个calculation类型的变量c
c = add // 把add赋值给c
fmt.Printf("type of c:%T\n", c) // ty ...