go study notes
- 开发环境 GOPATH
- go 1.8 以后Unix默认$HOME/go
- Windows默认%USERPROFILE%/go
- Mac上修改~/.bash_profile设置
- go command
- go version (查看go版本)
- go run hello_world.go (运行go)
- go build hello_world.go (编译go)
- 应用程序入口
- 必须是main包: package main
- 必须是main方法: func main()
- 文件名不一定是main.go
- 退出返回值(与其他语言区别)
- Go中main函数不支持任何返回值
- 通过os.Exit返回状态
- 获取命令行参数(与其他语言区别)
- main函数不支持传入参数func main(arg []string)
- 在程序中直接通过os.Args获取命令行参数
- 编写测试程序
- 源码文件以_test结尾:xxx_test.go
- 测试方法名以Test开头:func TestXXX(t *testing.T){}
- 变量赋值(与其他主要语言差异)
- 赋值可以进行自动类型推断
- 在一个赋值语句中可以对多个变量进行同时赋值
- 常量定义(与其他主要语言差异)
- 快速设置连续值(iota)
- 基本数据类型
- bool
- string
- int int8 int16 int32 int64
- uint uint8 uint16 uint32 uint64 uintptr
- byte // alias for uint8
- rune // alias for int32, represents a Unicode code point
- float32 float64
- complex64 complex128
- 类型转换(与其他主要语言差异)
- Go语言不允许隐式类型转换
- 别名和原有类型也不能进行隐式类型转换
- 类型预定义值
- math.MaxInt64
- math.MaxFloat64
- math.MaxUint32
- 指针类型(与其他主要语言差异)
- 不支持指针运算
- string是值类型,其默认初始值为空字符串,而不是nil
- 算数运算符
- + - * / % ++ --
- Go语言没有前置++, --
- 比较运算符
- == != > < >= <=
- 用==比较数组
- 相同维数且含有相同个数元素的数组才可以比较
- 每个元素都相同的才相等
- 逻辑运算符
- && || !
- 位运算符(与其他主要语言差异)
- & | ^ << >>
- &^ 按位置0
-
循环(与其他主要语言差异)
- Go语言仅支持循环关键字
- for j := 7; j <= 9; j++
-
if条件(与其他主要语言差异)
- condition表达式结果必须为布尔值
- 支持变量赋值:
- if var declaration; condition {
}
-
switch(与其他主要语言差异)
- 条件表达式不限制为常量或者整数
- 单个case中,可以出现多个结果选项,使用逗号分隔;
- 与C语言规则相反,Go不需要break来明确退出一个case;
- 可以不设定switch之后的条件表达式,在此种情况下,整个switch结构与多个if...else...的逻辑等同
- 数组声明
- var a [3]int //声明并初始化为0
- b := [3]int{1, 2, 3} // 声明同时初始化
- c := [2][2]int{{1, 2}, {3, 4}} // 多维数组初始化
- 相同维数相同长度可以比较
- 数组截取(与其他主要语言差异)
- a[开始索引(包含), 结束索引(不包含)]
- 不支持负数索引
- 切片(可变长数组)
- 指针,len,cap
- 切片不可比较,只能和nil比较
- map(与其他主要语言差异)
- s := map[string]int{"a": 1, "b": 2}
- 在访问key不存在时,仍会返回零值,不能通过返回nil来判断元素是否存在
- map(extend)
- map的value可以是一个方法
- 与Go的Dock type接口方式一起,可以方便实现单一方法对象的工厂模式
- 实现Set(与其他主要语言差异)
- Go的内置集合中没有Set实现,可以map[type]bool
- 元素唯一性
- 基本操作
- 添加元素
- 判断元素是否存在
- 删除元素
- 元素个数
- Go的内置集合中没有Set实现,可以map[type]bool
- 字符串(与其他主要语言差异)
- string是数据类型,不是引用和指针类型
- string是只读的byte slice, len函数是它所包含的byte数
- string的byte数组可以存放任何数据
- string是不可变的byte slice
- Unicode UTF8
- Unicode是一种字符集(code point)
- UTF8是unicode的存储实现(转换为字节序列的规则)
- 常用的字符串函数
- strings http://golang.org/pkg/strings/
- strconv http://golang.org/pkg/strconv/
- 函数是一等公民(与其他主要语言差异)
- 可以有多个返回值
- 所有参数都是值传递:slice,map,channel会有传引用的错觉
- 函数可以作为变量的值
- 函数可以作为参数和返回值
- 函数可变参数相当于数组
- defer函数
- 行为的定义和实现
- 定义
- 行为
- 接口(与其他主要语言差异)
- 接口为非入侵性的,实现不依赖于接口定义
- 接口的定义可以包含在接口使用者包内
- 自定义类型
- 扩展和复用
- 多态
- 空接口和断言
- 空接口可以表示任何类型
- 通过断言将空接口转换为制定类型
- v, ok := p.(int) // ok=true 转换成功
- Go接口最佳实践
- 倾向于使用小的接口定义,很多接口只包含一个方法
- 较大的接口定义,可以有多个小接口组合而成
- 只依赖于必要功能的最小接口
- Go的错误机制(与其他主要语言差异)
- 没有异常处理
- error类型实现了error接口
- 可以通过errors.New来快速创建错误实例
- Go错误最佳实践
- 定义不同错误变量,以便于判断错误类型
- 及早失败,避免嵌套
- panic
- panic用于不可恢复的错误
- panic退出前会执行defer指定的内容
- panic vs os.Exit
- os.Exit退出时不会调用defer指定的函数
- os.Exit退出时不输出当前调用栈信息
- recover
- 形成僵尸服务进程,导致health check失效
- "Let's it Crash!"往往是我们恢复不确定性错误的最好办法
- 构建可复用模块
- 基本复用模块单元(以首字母大写来表明可被包外代码访问)
- 代码的package可以和所在的目录不一致
- 同一目录里的Go代码的package要保持一致
- init方法
- 在main被执行前,所有依赖的package的init方法都会被执行
- 不同包的init函数按照包导入的依赖关系决定执行顺序
- 每个包可以有多个init函数
- 包的每个源文件也可以有多个init函数,这点比较特殊
- package
- 通过go get来获取远程依赖
- go get -u 强制从远程更新依赖(go get -u github.com/easierway/concurrent_map)
- 注意代码在github上的组织形式,以适应go get
- 直接以代码路径开始,不要有src
- Go未解决问题
- 同一环境,不同项目使用同一包的不同版本
- 无法管理对包的特定版本的依赖
- vendor(查找包路径解决方案)
- 当前包下的vendor目录
- 向上级目录查找,直到找到src下的vendor目录
- 在GOPATH下面查找依赖包
- 在GOROOT目录下查找
- 常用的依赖管理工具
- Thead vs Groutine
- 创建时默认的stack的大小
- JDK5以后Java Thread stack 默认为1M
- Groutine 的Stack初始化大小2k
- 和KSE(Kernel Space Entity)的对应关系
- Java Thread 1:1
- Groutine M : N
- 创建时默认的stack的大小
- 共享内存并发机制
- CSP vs Actor
- 和Actor的直接通讯不同,CSP模式则是通过Channel进行通讯的,更松耦合一些.
- Go中是有容量限制并且独立与处理Groutine,而如Erlang,Actor模式中的mailbox容量是无限的,接受进程也是被动的处理消息.
- 多路选择和超时(select)
- 向关闭的channel发送数据, 会导致panic
- v, ok <- ch; ok 为bool值,true表示正常接受,false表示通道关闭
- 所有的channel接收者都会在channel关闭时,立刻从阻塞等待中返回且上述ok值为false,这个广播机制常常被利用,进行向多个订阅者同时发送信号.
- 任务取消(close channel是广播机制,取消所有协程)
- Context与任务取消
- 根Context: 通过context.Background()创建
- 子Context: context.WithCancel(parentContext)创建
- ctx, cancel := context.WithCancel(context.Background)
- 当前Context被取消时, 基于他的子context都会被取消
- 接受取消通知<-ctx.Done()
- 仅执行一次(单例模式)
- 仅需任意任务完成(buffer channel 防止协程泄漏,内存泄漏)
- 所有任务完成
- 对象池
- sync.Pool对象获取
- 尝试从私有对象获取
- 私有对象不存在,尝试从当前Processor的共享池获取
- 如果当前Processor共享池是空的,那么就尝试去其他Processor的共享池获取
- 如果所有子池都是空的,最后就用用户指定的New函数产生一个新的对象返回
- sync.Pool对象的放回
- 如果私有对象不存在则保存为私有对象
- 如果私有对象存在,放入当前Processor子池的共享池中
- sync.Pool对象的生命周期
- GC会清楚sync.pool缓存的对象
- 对象的缓存有效期为下一次GC之前
- sync.Pool总结
- 适用于通过复用,降低复杂对象的创建和GC代价
- 协程安全,会有锁的开销
- 生命周期受GC影响,不适合于做连接池等,需自己管理生命周期的资源的池化
- 内置单元测试框架
- Fail,Error: 该测试失败,该测试继续,其他测试继续执行
- FailNow,Fatal: 该测试失败,该测试中止,其他测试继续执行
- 代码覆盖率
- go test -v -cover
- 断言
- 内置单元测试框架
- go test -bench=.(性能测试)
- go test -bench=. benchmem(内存测试)
- BDD
- 安装 go get -u github.com/smartystreets/goconvey/convey
- WEB UI $GOPATH/bin/goconvey
- reflect.TypeOf vs reflect.ValueOf
- reflect.TypeOf 返回类型(reflect.Type)
- reflect.ValueOf 返回类型(reflect.Value)
- 可以从reflect.Value获得类型
- 通过kind的来判断类型
- DeepEqual(比较切片和map)
- 关于反射你应该知道的
- 提高了程序的灵活性
- 降低了程序的可读性
- 降低了程序的性能
- 不安全编程(unsafe 和C联合使用)
- Pipe-Filter模式
- 非常适合于数据处理和数据分析系统
- Filter封装数据处理功能
- 松耦合:Filter只跟数据(格式)耦合
- Pipe用于连接Filter传递数据或者异步处理过程中缓冲数据流 进程内同步调用时,pipe演变为数据在方法调用间传递
- Micro Kernel
- 特点
- 易于扩展
- 错误隔离
- 保持架构一致性
- 要点
- 内核包含公共流程或通用逻辑
- 将可变和可扩展部分规划为扩展点
- 抽象扩展点行为,定义接口
- 利用插件进行扩展
- 特点
- 内置的JSON解析(利用反射实现,通过FieldTag来标识对应的json值)
- hello,world
- 命令行参数
- 找出重复行
- GIF动画
- 获取一个URL
- 一个Web服务器
- 其他内容
- 名称
- 声明
- 变量
- 赋值
- 类型声明
- 包和文件
- 作用域
- 整数
- 浮点数
- 复数
- 布尔值
- 字符串
- 常量
- 数组
- slice
- map
- 结构体
- JSON
- 文本和HTML模块
- 函数声明
- 递归
- 多返回值
- 错误
- 函数变量
- 匿名函数
- 变长函数
- 延迟函数调用
- 宕机
- 恢复
- 方法声明
- 指针接受者的方法
- 通过结构体内嵌组成类型
- 方法变量和表达式
- 示例:位向量
- 封装
- 接口即约定
- 接口类型
- 实现接口
- 使用flag.Value来解析参数
- 接口值
- 使用sort.Interface来排序
- http.Handler接口
- error接口
- 示例:表达式求值器
- 类型断言
- 使用类型断言来识别错误
- 通过接口类型断言来查询特性
- 类型分支
- 示例:基于标记的XML解析
- 一些建议
- goroutine
- 示例:并发时钟服务器
- 示例:并发回声服务器
- 通道
- 并行循环
- 示例:并发的Web爬虫
- 使用select多路复用
- 示例:并发目录遍历
- 取消
- 示例:聊天服务器
- 竞态
- 互斥锁:sync.Mutex
- 读写互斥锁:sync.RWMutex
- 内存同步
- 延迟初始化:sync.Once
- 竞态检测器
- 示例:并发非阻塞缓存
- goroutine与线程
- 引言
- 导入路径
- 包的声明
- 导入声明
- 空导入
- 包及其命名
- go工具
- go test工具
- Test函数
- 覆盖率
- Benchmark函数
- 性能剖析
- Example函数
- 为什么使用反射
- reflect.Type和reflect.Value
- Display: 一个递归的值显示器
- 示例:编码S表达式
- 使用reflect.Value来设置值
- 访问结构体字段标签
- 显示类型的方法
- 注意事项
- unsafe.Sizeof,Alignof和Offsetof
- unsafe.Pointer
- 示例: 深度相等
- 使用cgo调用C代码
- 关于安全注意事项286
- 原理介绍
- 执行任务
- 捕获任务输出
- 强制结束任务
- cron表达式原理
- 开源cron解析库
- 调度多个cron
- 变量
- 常量
- 基本类型
- 引用类型
- 类型转换
- 字符串
- 指针
- 自定义类型
- 保留字
- 运算符
- 初始化
- 控制流
- 函数定义
- 变参
- 返回值
- 匿名函数
- 延迟调用
- 错误处理
- Array
- Slice
- Map
- Struct
- 方法定义
- 匿名字段
- 方法集
- 表达式
- 接口定义
- 执行机制
- 接口转换
- 接口技巧
- Goroutine
- Channel
- 工作空间
- 源文件
- 包结构
- 文档
- 内存布局
- 指针陷阱
- cgo
- Reflect
- 初始化
- 分配流程
- 释放流程
- 其他
- 初始化
- 垃圾回收
- 内存释放
- 状态输出
- 初始化
- 创建任务
- 任务线程
- 任务执行
- 连续栈
- 系统调用
- 系统监控
- 状态输出
- 初始化
- 收发数据
- 选择模式
- 工作区和GOPATH
- 你知道设置 GOPATH 有什么意义吗?
- 你可以把 GOPATH 简单理解成 Go 语言的工作目录,它的值是一个目录的路径,也可以是多个目录路径,每个目录都代表 Go 语言的一个工作区(workspace)
- GOROOT:Go 语言安装根目录的路径,也就是 GO 语言的安装路径。
- GOPATH:若干工作区目录的路径。是我们自己定义的工作空间。
- GOBIN:GO 程序生成的可执行文件(executable file)的路径
- 你知道设置 GOPATH 有什么意义吗?
- 命令源码文件
- 命令源码文件的用途是什么,怎样编写它?
- 命令源码文件是程序的运行入口,是每个可独立运行的程序必须拥有的。我们可以通过构建或安装,生成与其对应的可执行文件,后者一般会与该命令源码文件的直接父目录同名。
- 命令源码文件的用途是什么,怎样编写它?
- 库源码文件
- 怎样把命令源码文件中的代码拆分到其他库源码文件?
- 填入代码包声明语句package main(相同包名),main包一般不加载其它包并且一起运行
- 包函数权限
- 相同包:函数可以小写(私有函数)
- 不同包:函数必须大写才能调用(公用函数)
- internal:包级权限
- 怎样把命令源码文件中的代码拆分到其他库源码文件?
- 程序实体的那些事儿(上)
- 声明变量有几种方式?
- 短变量声明
- 直接声明 (var name string)
- 赋值声明 (var name = hello())
- 类型推断声明:=
- 短变量声明
- Go 语言的类型推断可以带来哪些好处?
- 通过这种类型推断,你可以体验到动态类型编程语言所带来的一部分优势,即程序灵活性的明显提升。
- 但在那些编程语言中(Python),这种提升可以说是用程序的可维护性和运行效率换来的。
- Go 语言是静态类型的,所以一旦在初始化变量时确定了它的类型,之后就不可能再改变。这就避免了在后面维护程序时的一些问题。
- 另外,请记住,这种类型的确定是在编译期完成的,因此不会对程序的运行效率产生任何影响。
- 声明变量有几种方式?
- 程序实体的那些事儿(中)
- 如果一个变量与其外层代码块中的变量重名会出现什么状况?
- 变量屏蔽
- 如果一个变量与其外层代码块中的变量重名会出现什么状况?
- 程序实体的那些事儿(下)
- 怎样判断一个变量的类型?
- 使用“类型断言”表达式
- 怎样判断一个变量的类型?
- 数组和切片
- 数组类型的值(以下简称数组)的长度是固定的,而切片类型的值(以下简称切片)是可变长的
- 怎样正确估算切片的长度和容量?
- var i; i++, cap = 2 * len
- i := 1024; i++, cap = 1.25 * len
- var i; 2 * i, cap > 2 * len
- container包中的那些容器
- 可以把自己生成的Element类型值传给链表吗?
- 不会接受,这些方法将不会对链表做出任何改动。
- 因为我们自己生成的Element值并不在链表中,所以也就谈不上“在链表中移动元素”。
- 更何况链表不允许我们把自己生成的Element值插入其中。
- 可以把自己生成的Element类型值传给链表吗?
- 字典的操作和约束
- 字典的键类型不能是哪些类型?
- Go语言字典的键类型不可以是函数类型、字典类型和切片类型
- 用var声明的值为nil的map,读,删除都不报错,新增报错,需要初始化
- 字典的键类型不能是哪些类型?
- 通道的基本操作
- 对通道的发送和接收操作都有哪些基本的特性?
- 对于同一个通道,发送操作之间是互斥的,接收操作之间也是互斥的。
- 发送操作和接收操作中对元素值的处理都是不可分割的。
- 发送操作在完全完成之前会被阻塞。接收操作也是如此。
- 对通道的发送和接收操作都有哪些基本的特性?
- 通道的高级玩法
- 单向通道有什么应用价值?
- 单向通道最主要的用途就是约束其他代码的行为
- 单向通道有什么应用价值?
- 使用函数的正确姿势
- 怎样编写高阶函数?
- 接受其他的函数作为参数传入
- 把其他的函数作为结果返回
- 对于引用类型,比如:切片、字典、通道,像上面那样复制它们的值,只会拷贝它们本身而已,并不会拷贝它们引用的底层数据。
- 也就是说,这时只是浅表复制,而不是深层复制go中参数都是值复制
- 怎样编写高阶函数?
- 结构体及其方法的使用法门
- Animal类型中的字段声明AnimalCategory代表了什么?
- 字段声明AnimalCategory代表了Animal类型的一个嵌入字段。
- Go 语言规范规定,如果一个字段的声明中只有字段的类型名而没有字段的名称,那么它就是一个嵌入字段,也可以被称为匿名字段。
- 我们可以通过此类型变量的名称后跟“.”,再后跟嵌入字段类型的方式引用到该字段。
- 也就是说,嵌入字段的类型既是类型也是名称。
- Animal类型中的字段声明AnimalCategory代表了什么?
- 接口类型的合理运用
- 当我们为一个接口变量赋值时会发生什么?
- pet变量的字段name的值依然是"little pig
- 除非我们只声明而不初始化,或者显式地赋给它nil,否则接口变量的值就不会为nil
- 当我们为一个接口变量赋值时会发生什么?
- 关于指针的有限操作
- 你能列举出 Go 语言中的哪些值是不可寻址的吗?
- 不可变的
- 临时结果(例外: 切片字面量的索引结果值是可寻址的)
- 不安全的
- 你能列举出 Go 语言中的哪些值是不可寻址的吗?
- go语句及其执行规则(上)
- 什么是主 goroutine,它与我们启用的其他 goroutine 有什么不同?
- 不会有任何内容被打印出来
- 什么是主 goroutine,它与我们启用的其他 goroutine 有什么不同?
- go语句及其执行规则(下)
- if语句、for语句和switch语句
- 使用携带range子句的for语句时需要注意哪些细节?
- 非引用类型复制,引用原地修改
- 使用携带range子句的for语句时需要注意哪些细节?
- 错误处理(上)
- 对于具体错误的判断,Go 语言中都有哪些惯用法?
- 对于类型在已知范围内的一系列错误值,一般使用类型断言表达式或类型switch语句来判断
- 对于已有相应变量且类型相同的一系列错误值,一般直接使用判等操作来判断
- 对于没有相应变量且类型未知的一系列错误值,只能使用其错误信息的字符串表示形式来做判断
- 对于具体错误的判断,Go 语言中都有哪些惯用法?
- 错误处理(上)
- panic函数、recover函数以及defer语句(上)
- 从 panic 被引发到程序终止运行的大致过程是什么?
- panic函数报错调用,栈结构,先进后出
- 从 panic 被引发到程序终止运行的大致过程是什么?
- panic函数、recover函数以及defer语句(下)
- defer函数调用,栈结构,先进后出
- 测试的基本规则和流程(上)
- Go 语言对测试函数的名称和签名都有哪些规定?
- 对于功能测试函数来说,其名称必须以Test为前缀,并且参数列表中只应有一个*testing.T类型的参数声明
- 对于性能测试函数来说,其名称必须以Benchmark为前缀,并且唯一参数的类型必须是*testing.B类型的
- 对于示例测试函数来说,其名称必须以Example为前缀,但对函数的参数列表没有强制规定
- Go 语言对测试函数的名称和签名都有哪些规定?
- 测试的基本规则和流程(下)
- cd golang/puzzlers/article20/q2 & go test .
- cd golang/puzzlers/article20/q2 & go test -bench=. -run=^$ .
- 更多的测试手法
- sync.Mutex与sync.RWMutex
- 我们使用互斥锁时有哪些注意事项?
- 不要重复锁定互斥锁
- 不要忘记解锁互斥锁,必要时使用defer语句
- 不要对尚未锁定或者已解锁的互斥锁解锁
- 不要在多个函数之间直接传递互斥锁
- 我们使用互斥锁时有哪些注意事项?
- 条件变量sync.Cond (上)
- 条件变量怎样与互斥锁配合使用?
- 条件变量的初始化离不开互斥锁,并且它的方法有的也是基于互斥锁的
- 条件变量怎样与互斥锁配合使用?
- 条件变量sync.Cond (下)
- 原子操作(上)
- sync/atomic包中提供了几种原子操作?可操作的数据类型又有哪些?
- 加法(add)、比较并交换(compareand swap,简称 CAS)、加载(load)、存储(store)和交换(swap)
- int32、int64、uint32、uint64、uintptr,以及unsafe包中的Pointer。
- 不过,针对unsafe.Pointer类型,该包并未提供进行原子加法操作的函数。
- sync/atomic包中提供了几种原子操作?可操作的数据类型又有哪些?
- 原子操作(下)
- sync.WaitGroup和sync.Once
- sync.WaitGroup类型值中计数器的值可以小于0吗?
- 不可以,这样会引发一个 panic
- 先统一Add,再并发Done,最后Wait
- sync.WaitGroup类型值中计数器的值可以小于0吗?
- context.Context类型
- 怎样使用context包中的程序实体,实现一对多的 goroutine 协作流程?
- 在这个函数体中,我先后调用了context.Background函数和context.WithCancel函数。
- 并得到了一个可撤销的context.Context类型的值(由变量cxt代表)。
- 以及一个context.CancelFunc类型的撤销函数(由变量cancelFunc代表)。
- 怎样使用context包中的程序实体,实现一对多的 goroutine 协作流程?
- 临时对象池sync.Pool
- 为什么说临时对象池中的值会被及时地清理掉?
- Go 语言运行时系统中的垃圾回收器,所以在每次开始执行之前,都会对所有已创建的临时对象池中的值进行全面地清除
- 为什么说临时对象池中的值会被及时地清理掉?
- 并发安全字典sync.Map (上)
- 并发安全字典对键的类型有要求吗?
- 键的实际类型不能是函数类型、字典类型和切片类型
- 并发安全字典对键的类型有要求吗?
- 并发安全字典sync.Map (下)
- unicode与字符编码
- strings包与字符串操作
- 与string值相比,strings.Builder类型的值有哪些优势?
- 已存在的内容不可变,但可以拼接更多的内容
- 减少了内存分配和内容拷贝的次数
- 可将内容重置,可重用值
- 与string值相比,strings.Builder类型的值有哪些优势?
- bytes包与字节串操作(上)
- bytes.Buffer类型的值记录的已读计数,在其中起到了怎样的作用?
- 读取内容时,相应方法会依据已读计数找到未读部分,并在读取后更新计数
- 写入内容时,如需扩容,相应方法会根据已读计数实现扩容策略
- 截断内容时,相应方法截掉的是已读计数代表索引之后的未读部分
- 读回退时,相应方法需要用已读计数记录回退点
- 重置内容时,相应方法会把已读计数置为0
- 导出内容时,相应方法只会导出已读计数代表的索引之后的未读部分
- 获取长度时,相应方法会依据已读计数和内容容器的长度,计算未读部分的长度并返回
- bytes.Buffer类型的值记录的已读计数,在其中起到了怎样的作用?
- bytes包与字节串操作(下)
- io包中的接口和工具(上)
- 在io包中,io.Reader的扩展接口和实现类型都有哪些?它们分别都有什么功用?
- 扩展接口
- io.ReadWriter
- io.ReadCloser
- io.ReadWriteCloser
- io.ReadSeeker
- io.ReadWriteSeeker
- 实现类型
- *io.LimitedReader
- *io.SectionReader
- *io.teeReader
- io.multiReader
- io.pipe
- io.PipeReader
- 扩展接口
- 在io包中,io.Reader的扩展接口和实现类型都有哪些?它们分别都有什么功用?
- io包中的接口和工具(下)
- bufio包中的数据类型(上)
- bufio.Reader类型值中的缓冲区起着怎样的作用?
- bufio.Reader类型的值(以下简称Reader值)内的缓冲区,其实就是一个数据存储中介,它介于底层读取器与读取方法及其调用方之间。
- 所谓的底层读取器,就是在初始化此类值的时候传入的io.Reader类型的参数值
- Reader值的读取方法一般都会先从其所属值的缓冲区中读取数据
- 同时,在必要的时候,它们还会预先从底层读取器那里读出一部分数据,并暂存于缓冲区之中以备后用
- bufio.Reader类型值中的缓冲区起着怎样的作用?
- bufio包中的数据类型(下)
- 使用os包中的API (上)
- os.File类型都实现了哪些io包中的接口?
- os.File类型拥有的都是指针方法,所以除了空接口之外,它本身没有实现任何接口。
- 而它的指针类型则实现了很多io代码包中的接口
- 对于io包中最核心的 3 个简单接口io.Reader、io.Writer和io.Closer,*os.File类型都实现了它们
- 该类型还实现了另外的 3 个简单接口,即:io.ReaderAt、io.Seeker和io.WriterAt
- os.File类型都实现了哪些io包中的接口?
- 使用os包中的API (下)
- 访问网络服务
- net.Dial函数的第一个参数network有哪些可选值?
- net.Dial函数会接受两个参数,分别名为network和address,都是string类型的。
- 参数network常用的可选值一共有 9 个。这些值分别代表了程序底层创建的 socket 实例可使用的不同通信协议
- tcp, tcp4, tcp6, udp, udp4, udp6, unix, unixgram, unixpacket
- net.Dial函数的第一个参数network有哪些可选值?
- 基于HTTP协议的网络服务
- http.Client类型中的Transport字段代表着什么?
- 向网络服务发送 HTTP 请求,并从网络服务接收 HTTP 响应的操作过程
- 也就是说,该字段的方法RoundTrip应该实现单次HTTP 事务(或者说基于 HTTP 协议的单次交互)需要的所有步骤
- http.Client类型中的Transport字段代表着什么?
- 程序性能分析基础(上)
- 怎样让程序对 CPU 概要信息进行采样?
- 需要用到runtime/pprof包中的 API
- 在我们想让程序开始对 CPU 概要信息进行采样的时候,需要调用这个代码包中的StartCPUProfile函数
- 而在停止采样的时候则需要调用该包中的StopCPUProfile函数。
- 怎样让程序对 CPU 概要信息进行采样?
- 程序性能分析基础(下)