PalletOne技术讲堂之golang编程经验总结

PalletOne · · 1096 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

王继有 Pallet  7月5日

点击上方蓝字及时获取PalletOne最新消息

讲师简介:

王继有,PalletOne高级核心开发工程师,8年研发经验,精通C,C++,Go语言。具有丰富的DHCPv6、ND、RUI协议以及高性能服务器和对象存储的设计开发经验;熟悉区块链P2P网络的设计与开发。

一、unsafe.Pointer类型转换

[ ]byte转string


        var x = []byte("Hello World!")

        var y = *(*string)(unsafe.Pointer(&x))


string转[ ]byte


        var a string = "hello world"

        var b = *(*[]byte)(unsafe.Pointer(&a))

结构体和[]byte之间的互转


参考:

https://studygolang.com/articles/5348


 二、golang 几种常见的字符串连接性能比较

如果对字符串的拼接有效率要求,那么最好转换成字节用append来操作。


有如下方式:

strings.Join  fmt.Sprintf string +  bytes.Buffer

    v := "ni shuo wo shi bu shi tai wu liao le a?"

   var s string

var buf bytes.Buffer    //buffer := bytes.NewBuffer(make([]byte, 0, 65536))

    s = fmt.Sprintf("%s[%s]", s, v)

    s = s + "[" + v + "]"

    s = strings.Join([]string{s, "[", v, "]"}, "")

buf.WriteString("[")

   buf.WriteString(v)

   buf.WriteString("]")


对比结果:


string len: 410000  time of [fmt.Sprintf]=   318.093256ms

string len: 410000  time of [+]=     197.03476ms

string len: 410000  time of [strings.Join]=  439.952002ms

string len: 410000  time of [bytes.Buffer]=  435.764µs

len较小


strings.Join:

10000000           139 ns/op

bytes.Buffer:

10000000           166 ns/op

+:

3000000           429 ns/op


单次调用性能:操作符+>strings.Join>=bytes.Buffer>fmt.Sprintf


灵活性:bytes.Buffer>fmt.Sprintf>=strings.Join>操作符+


多次连接字符串操作:bytes.Buffer应该是最快的。


参考:


https://www.golangnote.com/topic/148.html


https://gocn.vip/question/265

三、同步机制

Atomic:数字的使用


RWMutex:读写锁


Channel:速度最慢。处理不好使协程阻塞,导致内存泄漏


//unsafe.Pointer


参考:

https://www.golangnote.com/topic/225.html


3.1、atomic使用

用原子操作可以替换mutex锁。其主要原因是,原子操作由底层硬件支持,而锁则由操作系统提供的API实现。若实现相同的功能,前者通常会更有效率。


32位系统下atomic.AddUint64导致程序崩溃,64位原子操作的调用者必须确保指针的地址是对齐到8字节的边界。


使用sync.RWMutex来实现互斥,如下:


mutex.Lock()

uint64 += 1

mutex.Unlock()

四、Golang 减小gc 压力、内存泄漏的分析和避免

4.1make([]int, len, cap) 预分配内存  make([]int,0,256)

4.2 ioutil.ReadAll()——>bytes.Buffer.ReadFrom——>makeSlice :

buffer := bytes.NewBuffer(make([]byte, 0, resp.ContentLength)

buffer.ReadFrom(res.Body)

body := buffer.Bytes()

4.3channel的释放

func produce(ch chan<- T, cancel chan struct{}) {

   defer close(ch)

select {

     case ch <- T{}:

     case <- cancel: // 用select同时监听cancel动作

       return

    } 

}

func consume(ch <-chan T, cancel chan struct{}) {

    v := <-ch

   err := doSomeThing(v)

   if err != nil {

       close(cancel) // 能够通知所有produce退出

       return

    }

}

for i:=0; i<10; i++ {

   go produce( )

}

consume( )

4.4 pprof工具的使用

log.Fatal(http.ListenAndServe(":9876", nil))

go tool pprof  http://localhost:9876/debug/pprof/profile

查看top10函数,分析导致内存泄漏的是哪个函数


参考:


https://www.golangnote.com/topic/222.html


http://www.cnblogs.com/yjf512/archive/2012/12/27/2835331.html (pprof或者https://www.cnblogs.com/snowInPluto/p/7403097.html)


五、尽可能少的使用reflect,代码理解容易

reflect,中文一般叫做反射。反射机制是指在运行时态能够调用对象的方法和属性。很多人比较熟悉的是Java的反射机制,其实go语言中也提供了反射机制,import  reflect就可以使用。在go语言中,主要用在函数的参数是interface{}类型,运行时根据传入的参数的特定类型执行不同的动作。


六、相对于math/rand 随机数,crypto/rand 随机数更加复杂并且不可预测


6.1、数字加减乘除要SafeMath


https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol


七、go test单元测试

hello.go    hello_test.go

测试单个文件:go test -v hello_test.go hello.go

测试单个函数:go test -v -run TestHello     hello_test.go     hello.go

压测单个函数:go test -v -bench BenchmarkHello     hello_test.go      hello.go

八、PalletOne工程简单讲解

8.1目录简单讲解

8.2Core下接口示例和事件订阅、p2p通信示例

go-palletone /core/coredata.go 

go-palletone/ consensus/consensus.go

在ProtocolManager.Start( )开始订阅共识事件,并发送给对端peer。


对端ProtocolManager.handleMsg( )中处理ConsensusMsg状态码



推荐:

GoLang 编程经验分享

https://www.golangnote.com/


代码规范


https://www.golangnote.com/topic/24.html                                                  


注释:包、函数、行代码修改添加删除注释。

区块链世界的IP协议高性能分布式账本

更多有价值的悄悄话,欢迎加入PalletOne社群

添加PalletOne波波微信

加入社区,咨询更多消息

官网:https://pallet.one/

官方邮箱:contact@pallet.one

Telegram:https://t.me/palletchinese

Github:https://github.com/PalletOne

Facebook:https://www.facebook.com/profile.

php?id=100026164972741

更多官方咨询,关注公众号获得


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:PalletOne

查看原文:PalletOne技术讲堂之golang编程经验总结

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1096 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传