golang 全局变量_Golang语言小技巧(踩坑)

bec827278076f94088a92a5f232d48f0.png

golang小技巧

用来记录golang使用过程中的一些技巧

技巧

  • golang可以在函数定义的时候确定其返回值具体为 func foo(arg int)(res int){}
  • go env GOPATH 可以用来去查看当前的GOPATH
  • golang 查找问题, 可以根据Goglandack工具一起结合查找
  • golang中的init函数用来初始化一些变量, 它总是会被运行, 只要导入了这个包, 初始化就会在run main之前被运行
  • golang中的接口类型, 以接口类型传入参数, 如果该接口类型, 实现了方法则ok
  • proto.String() 是一个helper方法, 分配一个新的空间, 并返回一个指向它的指针
  • golang中首字母大写表示public, 首字母小写则表示protect 或者 private
  • golangdefer语句的执行顺序为逆序
  • golang中有时候为了诊断方便, 可以使用printStackruntime.Stack(buf[:], false)
  • io.Writer是golang中接口类型的一种典型的运用, Fprintf=>(Printf, SPrintf)
  • Stringer接口通常用于对于printf或者println等一些列的函数数输出
  • golang中的数组array为定长数组, 如两个数组相比较必须是comparable即长度和类型必须一致
  • golang语言定义变量或者结构体在编译期就已经复制, 在运行期赋值, 需要重新定义一个函数
  • golangflag库需要使用flag.parse()来传递参数
  • buffer channelchannel中的元素个数小于channel size时为非阻塞的, 达到channel size之后则阻塞当前线程直到元素被取出.
  • 0 buff channel即为sync channel. 生产者和消费者都会被阻塞.
  • golang中对比并行程序设计有: 设置返回channel, 以经典的生产者消费者模式进行处理.
  • timer主要是用来设置定时任务, tickers主要是用来设置周期任务.
  • 使用sync.Mutex通过对全局变量的LockUnLock实现atomic加锁和解锁
  • 对于Atomic inc也可以使用sync/atomic库实现.
  • CAS: Compare And Swap比较并交换, 在golang中是以共享内存方式实现的一种同步机制.
  • Share memory by communicating; don't communicate by sharing memory.
  • golang中更好的一种方式是通过sync包以及channel来实现同步机制.
  • time.Sleep vs time.After
    • time.After通常于select搭配使用, 可以设置超时机制
    • time.Sleep可读性更强, 暂停当前Goroutine, 直到达到时间.
  • timer 通过AfterFuncNewTimer来创建, 使用Reset来重置, timer. 使用Stop来停止timer, 停止timer之后, 相应的goroutine会被阻塞.
  • timer 使用时, 如果使用了timer.Stop(), 则timer, 会被GC所回收, 但是timer对应的channel不会关闭, 则channel将会被永远的阻塞.
  • timer.Stop对应的timer被GC所回收, timer.C被阻塞, 如果再使用timer.Reset,则重新给timer对应的时间赋值并放入timer.C
  • timer 使用的正确姿势是, 使用timer.Reset, 而不是使用timer.Stop. 如果使用指针并且使用对应的timer.Channel. 重置timer时, 应当使用Reset而不是重新Stop+NewTimer来重置, 这样会导致内存泄漏, 阻塞goroutine
  • deadlock死锁: 多个线程占有一部分资源, 去请求另一部分资源时阻塞. 这些线程等等其他的线程释放资源. (已请求到锁)
  • livelock:活锁, 不断请求锁, 但是无法请求到资源. (未加锁)
  • selectchannel搭配使用, 如果要实现类似listener的模式, 则需要在外层加for {select ...}.
  • 通常使用select实现函数超时机制.
  • HTTP keep-alive是保持TCP连接open, 即复用TCP连接的一种手段. 例如: 通过HTTP keep-alive就可以实现不用每次都去重新建立HTTP连接, 这样就不会重新去请求静态资源css,html等.
  • TCP keep-alive是TCP协议定时地发送空的ack包来确认彼此的状态.
  • TCP keep-aliveHTTP keep-alive是两个不同的技术, 不存在谁依赖谁的关系. TCP keep-alive用来检测对端是否存在, 而HTTP keep-alive用来协商以复用连接.
  • context上下文类型,带有deadline,取消信号,还有其他与请求相关的request-scoped的值
  • context遵循的几个原则:
    • 不要将Context放入结构体,使用Context应该作为第一个参数传入,并命名为ctx,func DoSomething(ctx context.Context, arg Arg) error {//use ctx}
    • 即使函数允许,不要传入nil的Context.如果不知道用哪种Context,使用context.TODO()
    • 使用context的Value相关的方法只应该用于在程序和接口中传递和请求相关元数据,不要用它传递可选参数
    • 相同的Context可以传递给不同的goroutine, Context并发安全
  • sync.Map go1.9支持的线程安全的map,通过cas实现
  • reflect: go语言反射机制。reflact反射是一种机制,这种机制可以实现自我类型的检查和描述
  • init函数在main函数之前执行,通常用作初始化
  • sync.Once保证程序仅仅执行一次action
  • panic类似于抛出异常,即停止当前正确的程序流程, panic之后会执行defer函数
  • recover类似于恢复异常,即panic会一直向上抛出阻碍正常流程,直到recover则恢复
  • 具体的某个golang对象初始化时候,通常的一种写法是通过OptionFunc来初始化一些可选参数
  • // +build:是golang的build tag 例如// +build linux,386 darwin,!cgo 等价于(linux AND 386) OR (darwin AND (NOT cgo))
  • go build -tags="linux 386"进行编译, 并根据Build Constraints的条件进行编译
  • golang make初始化并分配内存
  • golang %#v%+v 为打印变量并打印其变量名
  • value receiverpointer receiver
    • value receiver是并发安全的, 且不改变value本身的值, copy by value
    • pointer receiver 不是并发安全的,且可以改变pointer本身的值
  • golang elastic 使用Scorll可以滚动的获取所有请求的结果
  • dep 为官网golang包管理工具
  • dep init : 效率较低,初始化golang项目的独立环境,利用gps分析出当前代码包中的依赖关系,并将其约束写入项目中的,Gopkg.toml文件中。将所有依赖的包最新的version/branch/revision信息写入Gopkg.lock,创建vendor目录,并以Gopkg.lock为输入,将其中包下载到vendor目录下面。
  • dep status: 查看当前项目下的status的状态
  • dep ensure : 确保当前项目的vendor处于一个正确的状态
  • gorilla/mux : golang 非常受欢迎的URL router dispatchergoconvey : golang 带UI的单元测试框架,可以很好的显示单元覆盖度
  • ACL: access control list 访问控制列表,是路由器和交换机接口的指令,用于控制端口进出的数据包,ACL提供了网络安全访问的基本手段。
  • map[string]*person{}map[string]person{}的区别在于指针和实例,实例为重新copy构造,改变内容之后,不改变map本身的内容, 末尾的{}为初始化map
  • OLAP: Online Analytical Processing: 在线数据处理关注于数据分析,OLTP: Online Transaction Processing 在线事务处理,类似于增删查改,专注于查询的速度
  • 一致性hash,为了解决弹性集群动态扩容的问题,通常的做法是构造0~2^32-1个hash环状空间,对于具体的某个key找到对应服务器上节点时,只需要顺序在环上转动找到第一个命中的节点即可。当出现负载不均的情况时,可以考虑使用引入虚拟节点达到负载均衡的效果。
  • GC: Garbage collection 垃圾回收机制,常见的垃圾回收算法有: 引用计数,标记清除Mark-Sweep法,三色标记法,分代收集法。
  • 引用计数:最基础的垃圾回收算法,例如C++中的std:shared_ptr
  • 标记清除:分为两个步骤:1. Mark: 从程序的根节点开始,遍历所有的对象,对可达的节点进行标记。2. Sweep: 将所有未标记的节点对象作为垃圾进行回收清除操作。有一个问题是会有STW(Stop The World)的问题,算法进行标记时会暂停整个应用程序。当程序中的对象特别多时,遍历整个对象树会消耗很多的时间。go1.3
  • 三色标记:是Mark-Sweep的一个改进,支持并发,即可以实现on-the-fly即在程序执行的同时进行垃圾回收 go1.6. 步骤如下:
​
1. 首先创建三个集合:白、灰、黑。
2. 将所有对象放入白色集合中。
3. 然后从根节点开始遍历所有对象(注意这里**并不递归遍历**),把遍历到的对象从白色集合放入灰色集合。
4. 之后遍历灰色集合,将灰色对象引用的对象从白色集合放入灰色集合,之后将此灰色对象放入黑色集合
5. 重复 4 直到灰色中无任何对象
6. 通过write-barrier检测对象有变化,重复以上操作
7. 集所有白色对象(垃圾)
  • 分代收集:也是Mark-Sweep的一个改进。该算法基于一个经验:绝大多数的对象生命周期都很短,按照对象生命周期的长短来分代。
一般分代GC,分为3代,新生代(Young Generation),年老代(Tenured Generation),永久代(Permanent Generation)
原理如下:
​
1. 新对象放入第 0 代
2. 当内存用量超过一个较小的阈值时,触发 0 代收集
3. 第 0 代幸存的对象(未被收集)放入第 1 代
4. 只有当内存用量超过一个较高的阈值时,才会触发 1 代收集,2 代同理
因为 0 代中的对象十分少,所以每次收集时遍历都会非常快(比 1 代收集快几个数量级)。只有内存消耗过于大的时候才会触发较慢的 1 代和 2 代收集。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值