`
on__the__way
  • 浏览: 23976 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

项目中的go实践

 
阅读更多

 

1,协程、select、channel

协程间的通信

  • 同一级的多个节点是可以并发执行的。 
  • 当有节点交汇时,后续节点需要等待前面节点的信号,出现等待阻塞的情况。使用select和有缓冲的channel等待信号发生。select 的功能和 select, poll, epoll 相似, 就是监听 IO 操作,当 IO 操作发生时,触发相应的动作。同时为了避免协程永久阻塞,加入超时机制。
  • 当关联节点是同步处理时,需要等待该节点处理完成并返回执行结果,用法与第二步相似
  • 在worker消费时,消息到达开新协程去消费,加入协程池

无缓冲channel和有缓冲channel

  • 对于无缓冲的channel,放入操作和取出操作不能再同一个routine中
  • 如果管道满了,对channel放入数据的操作就会阻塞,直到有某个routine从channel中取出数据;如果管道是空的,从channel取出数据的操作就会阻塞,直到某个routine向这个channel中放入数据
  • 关闭后的channel可以取数据,但是不能放数据

协程泄露

  1. 场景:被临时创建的协程,这些协程数量大且生命周期短。
  • 一种是协程想从一个通道读数据,但通道没有写入数据,或许这个通道已经被遗忘了。
  • 另外一种情况是协程想往一个通道写数据,可是由于无人监听这个通道即没有读出,该协程将永远无法向下执行

      2.  解决办法:

  • 第一种情况,无人往这个通道写入数据,加入定时器超时终止协程或对外暴露终止通道。
  • 第二种情况通道阻塞无法写入,就是给通道加缓冲,等协程执行完毕后,这部分通道内存将会失去引用,会被自动垃圾回收掉

WaitGroup,另一种同步机制

  • 场景:需要创建多个goroutine,并且一定要等它们都执行完毕后再继续执行接下来的操作,最大的优点就是.Wait()可以阻塞到队列中的任务都完毕后才解除阻塞。
  • 使用:Add(delta int)添加, Done()完成, Wait()阻塞等待

举例

2,反射(结构体和函数)

在php中根据传入的函数名参数可直接调用对应的函数或结构体,而golang是静态语言需要编译,使用switch case或者反射来进行调用。

反射就是一种检查接口变量的类型和值的机制。最基本的是reflect.Type和reflect.Value。可以通过reflect.TypeOf和reflect.ValueOf来得到接口变量的Type和Value

  • 通过Handle节点op调用对应的方法:

  • 通过结构体名实例化对应的结构体并调用方法

首先声明一个map结构,保存结构体名和reflect.Type的映射,如map[string]reflect.Type

根据传入的参数实例化对象

3,map排序

map是无序的,每次读出的顺序是随机的。

按key排序:可用slice对map进行间接排序,将读取map的key放在slice中,用sort对slice排序,再用排序后的key读取map

按value排序:实现sort包的Len Less 和Swap函数,自定义结构的排序函数

4,golang中的类型转换

  • interface到其他类型(int int64 string map slice...),接口类型向普通类型转换需要类型断言
    一个interface的值存储了一个赋给变量的具体值和这个值类型的描述type,使用断言取出值,断言只能是type类型,否则会panic
    接口类型向普通类型转换有两种方式:Comma-ok断言和switch测试。
        1,Comma-ok断言的语法是:value, ok := element.(T)。element必须是接口类型的变量,T是普通类型。如果断言失败,ok为false,否则ok为true并且value为变量的值。
        2,而switch是通过switch value := element.(type) 匹配type转换。
  • 其他类型到interface
    普通类型向接口类型的转换是隐式的。
  • str到int或float使用strconv包,如Atoi、Itoa、ParseInt、ParseFloat等...
  • 各种int和float之间的转换,直接强制转换如int(i)
  • 别名类型的转换,即便是别名对应的内置类型相同,也必须使用强制转换
  • 自定义类型之间的转换,特殊的,在count中使用了json.Unmarshal([]byte(ret), &this.G),ret是将G jsonencode后json格式,这里通过decode实例化G格式对象,需注意可导出元素要一一对应。

注意:nil只能赋值给指针、channel、func、interface、map或slice类型的变量,特别的,接口类型底层包含type和data,只有当都为nil时接口才为nil。

5,第三方库的选择

  • ssdb:基于hera封装的redis,提供了连接池

6,hera框架使用

  • 资源配置与pylon使用习惯相同,都是基于rigger
  • 单测,在资源配置中添加使用哪个系统的配置,单侧使用和go原生相同

7,图的存储和生成

8,其他

  • 二维数组的初始化

    this.G.Vr = make([][]int, len(res)+2) 
    for i := 1; i <= len(res)+1; i++ {
        this.G.Vr[i] = make([]int, len(res)+2) 
    }

 

参考

https://golang.org/pkg/reflect/

http://blog.golang.org/laws-of-reflection

http://blog.csdn.net/kjfcpua/article/details/18667255

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics