# go-test **Repository Path**: wangheng669/go-test ## Basic Information - **Project Name**: go-test - **Description**: golang - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-02-22 - **Last Updated**: 2022-03-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 1.变量定义 go语言中的变量声明后必须要使用 变量名称在前,变量类型在后 可以不对变量进行类型声明 第一次使用时使用:= 重新赋值使用= var尽量不使用 函数外部也可以进行变量定义,函数外部定义变量不能使用:= 必须使用var go语言变量都是在包内部,包外部不生效 使用var ()集中定义变量 编译器可以推测变量类型 没有char,只有rune 原生支持复数类型 2.内建变量类型 bool,string int,int8,int16,int32,int64,uintptr(指针) byte,rune float32,float64,complex64,complex128 验证欧拉公式 任何语言遵循float标准都是不准确的 go语言类型转换是强制的int(math.Sqrt(float64(a*a + b*b))) 3.常量与枚举 常量不定义类型运算时不需要进行类型转换 常量可以使用const ()集中定义常量 go语言中常量尽量不要大写 常量的数值可作为各种类型使用 iota在常量中使用,下方的常量将会自增,可使用_跳过自增 4.条件语句 if的条件里不需要括号 if的条件里可以赋值 if的条件里赋值的变量作用域就在这个if语句里 switch会自动break,除非使用fallthrough switch后可以没有表达式 5.循环 for的条件里不需要括号 for的条件里可以省略初始条件,结束条件,递增表达式 go语言中没有while 整数转二进制,不断读取文件 6.函数 函数必须声明参数类型,返回值类型 go语言可以返回多个返回值 只使用一个函数返回值是使用_替代 使用fmt.errorf返回错误信息 函数返回多个值时可以起名字 仅用于非常简单的函数 函数起不起名字对于调用者而言没有区别 go语言中函数是一等公民,函数内部也可以有函数 没有默认参数,可变参数 7.指针 值传递是拷贝,引用传递是传递地址 go语言只有值传递一种方式 8.数组 数组可以不赋值或者使用{}赋初值 数组的长度在前,类型在后 数组指定长度后初值的长度不能过长 数组可以使用...声明不确定的长度 也可以直接声明二维数组[4][5] 使用range关键字进行数组遍历可以获取下标和值 数组是值类型,不同长度的数组参数不同在函数中传递 通过数组指针进行数组的重新赋值 在go语言中一般不直接使用数组 9.切片的概念 切片不需要传递地址,可以直接通过函数修改变量的值 切片叫slice slice本身没有数据,是对底层array的一个view 赋值时只能赋值切片 slice可以向后扩展,不可以向前扩展 s[i]不可以超越len(s),向后扩展不可以超越底层数组cap(s) 10.切片的操作 append增加切片的值 添加元素时如果超越cap,系统会重新分配更大的底层数组 由于值传递的关系,必须接受append的返回值 使用make进行切片的创建 使用copy函数进行变量的拷贝 通过元素下标实现删除操作 11.Map Map[K]V,Map[K1]map[K2]V Key的值在Map当中是无序的 Map有三种定义方式:= var make delelte(map,key) 删除Map中的元素 map赋值返回第二个参数可用来判断是否存在某个元素 map不保证遍历顺序,需手动对key进行排序 struct也可作为key 12.Map例题 寻找最长不含有重复的字串 13.字符和字符串处理 使用range 遍历pos,rune对 使用utf8.RuneCountInString获得字符数量 使用len获得字节长度 使用[]byte获得字节 Fields,Split,Join Contains,Index ToLower,ToUpper Trim,TrimRight,TrimLeft 14.结构体和方法 go语言仅支持封装,不支持继承和多态 go语言没有class,只有struct 使用自定义工厂函数,返回局部变量的地址 使用指针组作为方法接受者才可以改变结构内容 nil指针也可以调用方法 要改变内容必须使用指针接收者 结构过大也考虑使用指针接收者 一致性:如有指针接收者,最好都是指针接收者 值接收者是go语言特有 值/指针接收者均可接收值/指针 15.包和封装 名字一般使用CamelCase 首字母大写:public 首字母小写:private 每个目录一个包 main包包含可执行入口 为结构定义的方法必须放在同一个包内 可以是不同文件 16.扩展已有类型 定义别名,使用组合方式扩展已有类型的方法 17.依赖管理 依赖管理的三个截断GOPATH,GOVENDOR,go mod 18.GOPATH和GOVENDOR 默认在~/go(unix,linux) %USERPROFILE%\go(windows) 包会在GOROOT和GOPATH目录寻找 每个项目有自己的vendor目录,存放第三方库 大量第三方依赖管理工具:glide,dep,go dep 19.go mod的使用 增加go.mod文件 执行go get 包后会生成go.sum类似于composer 执行代码会自动导入未导入的包 go build ./... 会导入所有未导入的包 由go命令统一的管理,用户不必关心目录结构 初始化:go mod init 增加依赖:go get 更新依赖:go get [@v...] 去除多余依赖数据:go mod tidy 将旧项目迁移到go mod:go mod init,go bulid ./... 20.目录的整理 同一目录下只有一个main文件 21.接口的概念 强类型语言:熟悉接口的概念 弱类型语言:没有接口的概念 接口可以方便代码解耦,使用方法不用关心实现方 22.duck typing的概念 描述事务的外部行为而非内部结构 23.接口的定义和实现 接口由使用者定义 实现者只需实现接口中的方法 接口的实现是隐式的 24.接口的值类型 接口变量里存在实现者的类型,实现者的值 接口变量自带指针 接口变量同样采用值传递,几乎不需要使用接口的指针 指针接收者实现只能以指针方式使用,值接收者都可 表示任何类型:interface{} v.(int)对接口类型参数进行强制转换 25.接口的组合 实现者实现不同的方法,使用方可进行接口的组合 26.常用系统接口 stringer 实现string方法后会自动打印类似于构造方法 reader writer 27.函数式编程 函数是一等公民:参数,变量,返回值都可以是函数 高阶函数 26.函数式编程例 可以实现斐波那契数列 函数也可以实现接口 使用函数来遍历二叉树 更为自然,不需要修饰如何访问自由变量 没有lambda表达式,但是有匿名函数 27.defer调用 保证资源打开后出错时被关闭 defer的顺序是先进后出的 panic不会阻止defer的输出 参数在defer语句时计算 28.错误处理概念 包内方法中包含特定的错误信息 29.服务器统一出错处理 声明一个函数接收值为函数,返回值也为函数 接受函数值返回err类型 对返回的err进行处理后输出 30.panic和recover 停止当前函数执行 一直向上返回,执行每一层的defer 如果没有遇见recover,程序退出 defer中增加recover函数对panic进行捕获 意料之中的使用error,意料之外使用panic string类型也可以调用方法 31.测试 go语言语法可以更易实践表格驱动测试 可以在命令行执行测试文件 go test . 创建测试文件需要用_test为后缀 32.代码覆盖率和性能测试 使用go test -coverprofile=c.out生成代码覆盖率文件 go tool cover -html=c.out转换为html文件查看 使用go test -bench .得到执行指定次数时的时间 33.使用pprof进行性能调优 b.logF用于调试时打印数据 b.RestTimer()不对之前的操作进行时间计算 go test -bench . -cpuprofile cpu.out 获取性能数据 go tool pprof查看性能数据 使用web命令 34.测试http服务器 1.声明结构体及方法生成出不同的错误 2.使用表格测试的方式调用不同的方法查看返回值 使用假的request/response 通过起服务器 35.生成文档和示例代码 用注释写文档 在测试中加入example godoc -http :6060 查看方法文档 使用output编译时可以查看结果是否正确 36.测试总结 表格驱动测试 代码覆盖率 性能优化根据 http测试 37.goroutine 轻量级”线程“ 非抢占式多任务处理,由协程主动交出控制权 编译器/解释器/虚拟机层面的多任务 多个协程可能在一个或多个线程上运行 runtime.Gosched 手动交出控制权 go func 增加一个协程方法 time.Sleep 延迟输出 使用匿名函数是要将外部的变量传入否则会导致外部循环结束后协程找不到数据的问题 38.go语言的调度器 python使用yield关键字实现协程,3.5加入了async def对协程原生支持 任何函数只需加上go就能送给调度器运行 不需要在定义时区是否是异步函数 调度器在合适的点进行切换 使用-race来检测数据访问的冲突 goroutine可能的切换点:I/O,select,channel,等待锁,函数调用,runtime.Gosched() 39.channel channel传入数据之后需要使用协程去接收否则会报错 channel能加缓冲区后在不超过缓冲区大小时不会报错 channel可以被close掉,根据返回的ok值判断channel是否已输出完毕 可以把channel传来传去 channel可以使用range输出 不要通过共享内存来通信,通过通信来共享内存