杂
assert
-
Every assertion function also takes an optional string message as the final argument, allowing custom error messages to be appended to the message the assertion method outputs.
-
func TestSomething(t *testing.T) { var a string = "Hello" var b string = "Hello" assert.Equal(t, a, b, "The two words should be the same.") } // assert many times func TestSomething(t *testing.T) { assert := assert.New(t) var a string = "Hello" var b string = "Hello" assert.Equal(a, b, "The two words should be the same.") }
validator
- required :必填
- email:验证字符串是email格式;例:“email”
- url:这将验证字符串值包含有效的网址;例:“url”
- max:字符串最大长度;例:“max=20”
- min:字符串最小长度;例:“min=6”
- excludesall:不能包含特殊字符;例:“excludesall=0x2C”//注意这里用十六进制表示。
- len:字符长度必须等于n,或者数组、切片、map的len值为n,即包含的项目数;例:“len=6”
- eq:数字等于n,或者或者数组、切片、map的len值为n,即包含的项目数;例:“eq=6”
- ne:数字不等于n,或者或者数组、切片、map的len值不等于为n,即包含的项目数不为n,其和eq相反;例:“ne=6”
- gt:数字大于n,或者或者数组、切片、map的len值大于n,即包含的项目数大于n;例:“gt=6”
- gte:数字大于或等于n,或者或者数组、切片、map的len值大于或等于n,即包含的项目数大于或等于n;例:“gte=6”
- lt:数字小于n,或者或者数组、切片、map的len值小于n,即包含的项目数小于n;例:“lt=6”
- lte:数字小于或等于n,或者或者数组、切片、map的len值小于或等于n,即包含的项目数小于或等于n;例:“lte=6”
函数
- variadic:有时候参数过多,或者想要让函数处理任意多个的参数,可以在函数定义语句的参数部分使用
ARGS...TYPE
的方式。这时会将...
代表的参数全部保存到一个名为ARGS的slice中,注意这些参数的数据类型都是TYPE。 - 接收器和方法:func和方法名之间有一个参数,这个参数为方法的receiver,于是定义的这个方法和接收者绑定在了一起。类似于Java中的类内的成员函数。
- 返回值变量,要不都有变量名,要不就一个变量名对应一个类型。
goroutine
- goroutine是Go中轻量级线程实现,由Go运行时(runtime)管理。
- 关键字 go 创建一个goroutine。
- 所有的goroutine在main()函数结束时会一同结束。
闭包
- Go中闭包是引用了自由变量的函数,被引用的自由变量和函数一同存在,即使已经离开了自由变量的环境也不会被释放或者删除,在闭包中可以继续使用这个自由变量。
- 闭包会使得函数中的变量都被保存在内存中,内存消耗很大。
Context
-
用于设置截止日期、同步信号,传递请求相关值的结构体。
-
// 需要实现这4个方法 type Context interface { Deadline() (deadline time.Time, ok bool) Done() <-chan struct{} Err() error Value(key interface{}) interface{} }
reflect
- reflect.TypeOf():返回一个表示着唯一接口参数值的动态类型的reflect.Type值。
- reflect.Type类型对象有成员函数
- Name(): 类型名
- Kind():种类
interface{ }类型
- interface{}类型,空接口,是没有方法的接口,所有类型都实现了空接口。
废弃方法api
- 在方法上加上注释Deprecated
cap
- arry:返回数组的元素个数
- slice:返回slice的最大容量
- channel:返回channel的buffer容量
语法
- 取反:用
^
或者!
,go不支持~
符号。 - import:import后面跟的是包路径,而不是包名。
- 同个目录下可以有多个.go文件,但是只能有一个包。
- 使用第三方库时,先将源码编译成.a文件放到临时目录下,然后去链接这个.a文件,而不是go install安装的那个.a文件;
- 使用标准库时,直接链接.a文件,即使修改了源码,也不会从新编译源码;
- 不管使用的是标准库还是第三方库,源码都是必须存在的,即使使用的是.a文件。
- 常量:go语言常量要是编译时就能确定的数据
- errors.New("xxx") 要等到运行时才能确定,所以它不能是const。
- 存储在常量中的数据类型只可以是布尔型、数字型(int, float, complex)和string。
- 循环语句
- switch:
- 声明语句和表达式语句都是可选的。(可以不设定swicth后的条件表达式,和if...else同个效果)
- 不需要break手动退出case。
- 条件表达式不限制为常量or整数。
- switch:
- 字符串:字符串是不可变的,是不定长字节,不能对字符串中某个字符单独赋值,不支持下标操作。
- 指针:不支持指针运算。
- 平行赋值:等号左边和右边含有多个表达式。
- 高级break:可以选择中断哪个循环。
- main
- main函数不能带参数
- main函数不能定义返回值
- main函数所在的包必须是main包
- main函数中可以使用flag包来获取和解析命令行参数。
struct、interface
- go里没有类这个概念
- interface中只能定义函数,不能定义变量。
- struct里只能定义变量。
- struct对interface的实现是隐式的,只要实现了interface里的函数,则相当于实现了interface,效果有点像成员方法。
go框架
GoMock
- interface可以通过GoMock框架打桩。
redigo
redis.Conn链接对象相关方法
- conn.Do() :Do发送一条命令到redis服务器端执行并返回结果
- conn.Send(): Send发送命令到缓存
- conn.Flush(): Flush发送命令到服务端执行
- conn.Receive(): Receive方法获取命令执行结果
- conn.Close(): 关闭链接
Pool连接池获取conn对象
-
pool封装dial实现连接池。
-
conn := pool.Get() //get方法获取conn链接对象
-
redis.Dial():获取conn
DialOption生效
-
先在DialURL中参数options中设置DialClientname。
-
DialClientName返回了一个DialOption,这个DialOption设置了clientname。
-
DialOption这个struct包了一个func,在func里面对参数do进行设置。
func DialClientName(name string) DialOption { return DialOption{func(do *dialOptions) { do.clientName = name }} }
-
-
DialURL中设置passwd, address等,然后调用Dial
-
Dial调用DialContext
-
Dial只是调用了DialContext,传入context.Background作为Context。
func Dial(network, address string, options ...DialOption) (Conn, error) { return DialContext(context.Background(), network, address, options...) }
-
-
DialContext
- 设置dialOptions类型do中Timeout、Keepalive、tlsHandshakeTiemout等参数。
- 调用options中的f func,设置do的clientname字段。
- 通过do的dialContext获得netConn,获得&conn的c。
- 当
do.clientname!=""
才调用c.do进行设置CLIENTNAME。
- 当clientname为空字符串时,其实是不会进行设置clientname的。
Go程序加载流程
- 初始化流程,执行main.main()之前,Go引导程序会先对整个程序的包进行初始化。
- 包初始化从main()引用的包开始,逐级查找,最终生成一个包引用的有向无环图。
- 先初始化常量 const...
- 然后初始化全局变量 var...
- 执行包的init()
go内存管理机制
golang中不存在野指针
- go语言的自动内存管理机制使得只要还有一个指针引用一个变量,那这个变量就会在内存中得以保留。
- go语言中变量是分配在栈中还是在堆中也是不能确定的,栈中的变量可能会逃逸到堆,堆中的变量也可能因为编译优化而在栈中分配,这都是由go语言管理的。
内存泄漏
- 在Go语言里,我们检测内存泄漏主要依靠的是go里面的pprof包。
- 除此之外,我们还可以使用浏览器来查看系统的实时内存信息(包括CPU、goroutine等的信息)。
序列化和反序列化
- 序列化就是把对象转换成字节流,便于保存在内存、文件、数据库中;
- 反序列化即逆过程,由字节流还原成对象。
- 序列化通常讲类型结构传入标准库or第三方包。
- 结构体在序列化时非导出变量(以小写字母开头的变量名)不会被encode,因此在decode时这些非导出变量的值为其类型的零值。