入职学习——go-tour

从编码规范会议学习到的

  • import后引用的是目录名,导入该目录下的所有.go文件(不包括子文件夹)
  • 调用某个方法时,格式为:a.b;a为引用的go文件的package,b为文件中的方法名
  • slice算是一个结构体,其中有一个变量是指针,指向存储地址,但是由于扩容的问题,指针会改变,如果直接赋值的话指针无法改变(无法做到深拷贝),要做到深拷贝(可能)要用copy

    从Go tour学到的

  • 返回值有一定的作用域,可以避免命名返回值
  • 定义参数/变量都是名字在前,类型在后
  • := 代替var声明【但是不能在函数外使用,函数外必须以关键字开始】
  • 常量不能用:= 用const xx=xxx
  • while改成for(即:省略前置和后置语句)
  • If也有前置语句,但是在前置语句中声明的变量仅在判断语句块内可以使用
  • Switch..case从上到下执行,但是默认加break,因此只挑选一种情况
  • defer栈:外层函数返回时按栈顺序调用
  • [ ]T是一个slice
  • T[low:high]表示分割,默认为0,Len(T)
  • slice构造函数:
  • b := make([]int, 0, 5) // len(b)=0, cap(b)=5
  • len表示当前长度,cap表示最大容量
  • for i, v := range pow 对pow slice进行遍历
  • 用_取代i,以隐藏/省略
  • map[string]Vertex key的类型为string,value的类型为vertex
  • 函数可以作为值传递
  • 为结构体定义方法:func (v Vertex) Abs() 必须在同一个包内
  • 如果需要修改原始数据,那么要用指针接收者,如果不改,就用值
  • 参数是指针的函数必须接受指针,接收者是指针的方法可以接收指针和值(值同理)
  • 接口interface——我理解的类似于抽象类,声明一些方法,结构体可以作为接收体来继承这个方法,但是无需特意声明继承于该抽象类
  • 如果没有继承的实现类,会报错
  • var i interface{} 声明一个空接口,i就可以变成各种类型的值
  • 对一些需要判断的语句,可以通过v,ok:=…中ok的值来判断是否异常
  • String()是一个接口方法,类似toString(),可重写,关于输出格式
  • 要改变输出格式:fmt.Sprintf
  • Error()和String()一样是一个接口方,如果继承了这个接口,说明这是结构体是一个error,返回string
  • Read()也是一个接口方法,返回(int, error)。int是长度

    并发

  • 信道:
    • ch := make(chan int)
    • ch <- v // 将 v 发送至信道 ch。
    • v := <-ch // 从 ch 接收值并赋予 v。
    • 信道存储的顺序是FIFO
    • Make后面可以加缓存容量数
  • range c产生的迭代值为Chan中发送的值,它会一直迭代直到channel被关闭。上面的例子中如果把close(c)注释掉,程序会一直阻塞在for …… range那一行。哦哦这里的range就是range到close(chan),所以如果没有close,会无限循环
  • Go表示同步(都要加)
  • 互斥锁:
    • 一个线程安全的struct可以有一个mux sync.Mutex。通过mux.Lock()/Unlock()来进行操作
    • lock之后同时只能有一个go线程可以访问
    • defer c.mux.Unlock()——defer关键字保证在返回前调用
      • Ps.defer调用顺序:先给返回值赋值,然后调用defer表达式,最后才是返回到调用函数中。【所以如果defer里修改的不是返回值,那么返回值是不变的】然后defer函数中的变量不需要传入,直接修改即可,如果传入变量,反而作用域会变 defer
Table of Contents