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整数。


  • 字符串:字符串是不可变的,是不定长字节,不能对字符串中某个字符单独赋值,不支持下标操作。
  • 指针:不支持指针运算。
  • 平行赋值:等号左边和右边含有多个表达式。
  • 高级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生效


  1. 先在DialURL中参数options中设置DialClientname。
  2. DialClientName返回了一个DialOption,这个DialOption设置了clientname。

    • DialOption这个struct包了一个func,在func里面对参数do进行设置。

  3. ​func DialClientName(name string) DialOption { return DialOption{func(do *dialOptions) { do.clientName = name }} } ​
  4. DialURL中设置passwd, address等,然后调用Dial
  5. Dial调用DialContext

    1. Dial只是调用了DialContext,传入context.Background作为Context。

  6. ​func Dial(network, address string, options ...DialOption) (Conn, error) { return DialContext(context.Background(), network, address, options...) } ​
  7. DialContext

    1. 设置dialOptions类型do中Timeout、Keepalive、tlsHandshakeTiemout等参数。
    2. 调用options中的f func,设置do的clientname字段。
    3. 通过do的dialContext获得netConn,获得&conn的c。
    4. 当​​do.clientname!=""​​才调用c.do进行设置CLIENTNAME。



  • 当clientname为空字符串时,其实是不会进行设置clientname的。

Go程序加载流程


  • 【Go】杂七杂八GoLang_go语言
  • 初始化流程,执行main.main()之前,Go引导程序会先对整个程序的包进行初始化。

    1. 包初始化从main()引用的包开始,逐级查找,最终生成一个包引用的有向无环图。
    2. 先初始化常量 const...
    3. 然后初始化全局变量 var...
    4. 执行包的init()


go内存管理机制

golang中不存在野指针


  • go语言的自动内存管理机制使得只要还有一个指针引用一个变量,那这个变量就会在内存中得以保留。
  • go语言中变量是分配在栈中还是在堆中也是不能确定的,栈中的变量可能会逃逸到堆,堆中的变量也可能因为编译优化而在栈中分配,这都是由go语言管理的。

内存泄漏


  • 在Go语言里,我们检测内存泄漏主要依靠的是go里面的pprof包。
  • 除此之外,我们还可以使用浏览器来查看系统的实时内存信息(包括CPU、goroutine等的信息)。