每日新闻

每日新闻

GoCN每日新闻资讯
有问必答

有问必答

Go相关的问题,技术相关的问题
文章分享

文章分享

技术文章分享,让知识传播给更多的人
招聘应聘

招聘应聘

为Gopher服务的招聘应聘平台

C++ STL的go语言版本,欢迎各位大佬完善

stirlingx 发表了文章 • 0 个评论 • 330 次浏览 • 2019-11-20 11:21 • 来自相关话题

项目地址: https://github.com/liyue201/gostl目前已实现的功能data structure ...查看全部

gout: 流式http client v0.0.3版本发布

guonaihong 发表了文章 • 0 个评论 • 239 次浏览 • 2019-11-18 09:31 • 来自相关话题

简介    gout是golang写的流式http client,易用的接口和丰富的数据绑定,比标准库更爽的使用感受。目前可用于RESTful 接口开发。流式构架设计方便水平扩张功能,下个版本支持benckmark模式 ...查看全部

简介

    gout是golang写的流式http client,易用的接口和丰富的数据绑定,比标准库更爽的使用感受。目前可用于RESTful 接口开发。流式构架设计方便水平扩张功能,下个版本支持benckmark模式


Changlog

<main>
  • #78 debug模式下-支持json语法高亮
  • #84 支持x-www-form-urlencoded
  • #82 新增example目录,存放使用示例
  • #83 SetForm支持更多数据类型
  • #81 代码测试覆盖度达到90%
</main>

    Excelize 发布 2.0.2 版本, Go 语言 Excel 文档基础库

    xuri 发表了文章 • 0 个评论 • 402 次浏览 • 2019-10-10 14:32 • 来自相关话题


    Excelize 是 Go 语言编写的用于操作 Office Excel 文档类库,基于 ECMA-376 Office Open XML 标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的 XLSX 文档。相比较其他的开源类库,Excelize 支持写入原本带有图片(表)、透视表和切片器等复杂样式的文档,还支持向 Excel 文档中插入图片与图表,并且在保存后不会丢失文档原有样式,可以应用于各类报表系统中。入选 2018 开源中国码云 Gitee 最有价值开源项目 GVP,目前已成为 Go 语言最受欢迎的 Excel 文档基础库。

    开源代码

    GitHub: github.com/xuri/excelize
    Gitee: gitee.com/xurime/excelize
    中文文档: xuri.me/excelize/zh-hans

    Excelize 知名用户


    2019年10月9日,社区正式发布了 2.0.2 版本,该版本包含了多项新增功能、错误修复和兼容性提升优化。下面是有关该版本更新内容的摘要,完整的更改列表可查看 change log

    有关更改的摘要,请参阅 Release Notes。完整的更改列表可查看 change log

    Release Notes

    此版本中最显著的变化包括:

    兼容性提示

    升级至该版本需要您的 Go 语言版本高于 1.10。

    新增功能

    问题修复

    • 修复部分情况下读取批注内容文本不完整的问题,解决 issue #434
    • 修复由于内部合并单元格偏移量计算错误导致的部分情况下使用 RemoveRow() 删除行出现下标越界问题,解决 issue #437
    • 修复部分情况下数据验证下拉菜单中的公式失效问题
    • 修复在循环迭代中调用 Save() 方法保存导致的文档损坏问题,解决 issue #443
    • 提升文档内部 workbook.xml.rels 中相对路径格式解析的兼容性,解决 issue #442
    • 修复部分情况下,删除带有合并单元格的文档所导致的文件损坏问题
    • 修复部分情况下设置保护工作表属性失效的情况,解决 issue #454
    • 修复部分情况下 GetSheetName 获取工作表名称为空的问题, 解决 issue #457
    • 增加单元格内多行文本解析的支持, 相关 issue #464
    • 修复 32 位操作系统环境下数字溢出问题,相关 issue #386
    • 修复 go module 依赖版本不匹配问题, 相关 issue #466 和 issue #480
    • 修复部分情况下调用 SetSheetPrOptions() 所致的文档损坏问题,解决 issue #483

    性能表现

    • 性能优化,减少读取文档时的内存开销和耗时,相关 issue #439

    其他

    • 完善 SetSheetRow() 函数中的异常处理
    • 代码精简优化, 合并了下列内部函数:

    将函数 workBookRelsWriterdrawingRelsWriter 合并为 relsWriter;
    将函数 drawingRelsReaderworkbookRelsReaderworkSheetRelsReader 合并为 relsReader;
    将函数 addDrawingRelationshipsaddSheetRelationships 合并为 addRels

    [gev] 一个轻量、快速的基于 Reactor 模式的非阻塞 TCP 网络库

    惜朝 发表了文章 • 0 个评论 • 387 次浏览 • 2019-09-25 16:45 • 来自相关话题

    `gev` 是一个 ...查看全部

    `gev` 是一个轻量、快速的基于 Reactor 模式的非阻塞 TCP 网络库。

    ➡️➡️ https://github.com/Allenxuxu/gev

    特点

    - 基于 epoll 和 kqueue 实现的高性能事件循环
    - 支持多核多线程
    - 动态扩容 Ring Buffer 实现的读写缓冲区
    - 异步读写
    - SO_REUSEPORT 端口重用支持

    网络模型

    `gev` 只使用极少的 goroutine, 一个 goroutine 负责监听客户端连接,其他 goroutine (work 协程)负责处理已连接客户端的读写事件,work 协程数量可以配置,默认与运行主机 CPU 数量相同。

    性能测试

    > 测试环境 Ubuntu18.04 | 4 Virtual CPUs | 4.0 GiB

    吞吐量测试

    限制 GOMAXPROCS=1(单线程),1 个 work 协程


    限制 GOMAXPROCS=4,4 个 work 协程


    其他测试

    速度测试


    和同类库的简单性能比较, 压测方式与 evio 项目相同。
    - gnet
    - eviop
    - evio
    - net (标准库)

    限制 GOMAXPROCS=1,1 个 work 协程


    限制 GOMAXPROCS=1,4 个 work 协程


    限制 GOMAXPROCS=4,4 个 work 协程


    安装 gev


    ```bash
    go get -u github.com/Allenxuxu/gev
    ```

    快速入门


    ```go
    package main

    import (
    "log"

    "github.com/Allenxuxu/gev"
    "github.com/Allenxuxu/gev/connection"
    "github.com/Allenxuxu/ringbuffer"
    )

    type example struct{}

    func (s *example) OnConnect(c *connection.Connection) {
    log.Println(" OnConnect : ", c.PeerAddr())
    }

    func (s *example) OnMessage(c *connection.Connection, buffer *ringbuffer.RingBuffer) (out []byte) {
    log.Println("OnMessage")
    first, end := buffer.PeekAll()
    out = first
    if len(end) > 0 {
    out = append(out, end...)
    }
    buffer.RetrieveAll()
    return
    }

    func (s *example) OnClose(c *connection.Connection) {
    log.Println("OnClose")
    }

    func main() {
    handler := new(example)

    s, err := gev.NewServer(handler,
    gev.Address(":1833"),
    gev.NumLoops(2),
    gev.ReusePort(true))
    if err != nil {
    panic(err)
    }

    s.Start()
    }
    ```

    Handler 是一个接口,我们的程序必须实现它。

    ```go
    type Handler interface {
    OnConnect(c *connection.Connection)
    OnMessage(c *connection.Connection, buffer *ringbuffer.RingBuffer) []byte
    OnClose(c *connection.Connection)
    }

    func NewServer(handler Handler, opts ...Option) (server *Server, err error) {
    ```

    在消息到来时,gev 会回调 OnMessage ,在这个函数中可以通过返回一个切片来发送数据给客户端。

    ```go
    func (s *example) OnMessage(c *connection.Connection, buffer *ringbuffer.RingBuffer) (out []byte)
    ```

    Connection 还提供 Send 方法来发送数据。Send 并不会立刻发送数据,而是先添加到 event loop 的任务队列中,然后唤醒 event loop 去发送。

    更详细的使用方式可以参考示例:[服务端定时推送]

    ```go
    func (c *Connection) Send(buffer []byte) error
    ```

    Connection ShutdownWrite 会关闭写端,从而断开连接。

    更详细的使用方式可以参考示例:[限制最大连接数]

    ```go
    func (c *Connection) ShutdownWrite() error
    ```


    ➡️➡️ https://github.com/Allenxuxu/gev



    花了半天用go写一个带ui的redis客户端

    ownGolang 回复了问题 • 6 人关注 • 5 个回复 • 1468 次浏览 • 2019-09-18 10:17 • 来自相关话题

    go + koa = ? 一个新的web框架 goa 诞生

    nicholascao 发表了文章 • 1 个评论 • 517 次浏览 • 2019-08-08 15:52 • 来自相关话题

    ## koajs 相信绝大部分使用nodejs的开发者都知道[koa](https://koa.bootcss.com/),甚至每天都在跟koa打交道。 ## goa 最近因工作需要 ...查看全部
    ## koajs

    相信绝大部分使用nodejs的开发者都知道[koa](https://koa.bootcss.com/),甚至每天都在跟koa打交道。

    ## goa

    最近因工作需要从nodejs转到go,因此开发了一个koa for golang的web框架--goa。
    几乎一样的语法,一样基于中间件。

    github地址:[goa](https://github.com/goa-go/goa)

    demo:

    ``` golang
    package main

    import (
    "fmt"
    "time"

    "github.com/goa-go/goa"
    "github.com/goa-go/goa/router"
    )

    func logger(c *goa.Context, next func()) {
    start := time.Now()

    fmt.Printf("[%s] <-- %s %s\n", start.Format("2006-6-2 15:04:05"), c.Method, c.URL)
    next()
    fmt.Printf("[%s] --> %s %s %d%s\n", time.Now().Format("2006-6-2 15:04:05"), c.Method, c.URL, time.Since(start).Nanoseconds()/1e6, "ms")
    }

    func json(c *goa.Context) {
    c.JSON(goa.M{
    "string": "string",
    "int": 1,
    "json": goa.M{
    "key": "value",
    },
    })
    }

    func main() {
    app := goa.New()
    router := router.New()

    router.GET("/", func(c *goa.Context) {
    c.String("hello world")
    })
    router.GET("/json", json)

    app.Use(logger)
    app.Use(router.Routes())
    app.Listen(":3000")
    }
    ```
    如果觉得这个项目不错的话,请给个star给予作者鼓励,
    另外欢迎fork和加入开发团队共建。

    再次贴上地址https://github.com/goa-go/goa

    golang + qt5 开发的百度网盘不限速客户端

    peterq 发表了文章 • 1 个评论 • 585 次浏览 • 2019-07-01 15:55 • 来自相关话题

    > 百度云不限速客户端,使用golang + qt5 开发,跨平台。代码注释详细,并有附有开发文档,gopher们快来支持下吧 官网: https://github.com/peterq/pan-light ...查看全部
    > 百度云不限速客户端,使用golang + qt5 开发,跨平台。代码注释详细,并有附有开发文档,gopher们快来支持下吧

    官网: https://github.com/peterq/pan-light

    github: https://github.com/peterq/pan-light

    go游戏服务器框架

    xiaodi 发表了文章 • 1 个评论 • 514 次浏览 • 2019-06-28 21:24 • 来自相关话题

    项目地址:https://github.com/okpub/rhino 欢迎服务器爱好者入群交流,腾讯,阿里大牛在线装逼
    项目地址:https://github.com/okpub/rhino

    欢迎服务器爱好者入群交流,腾讯,阿里大牛在线装逼

    基于Golang的轻量级并发服务器框架---Zinx

    Aceld 发表了文章 • 0 个评论 • 659 次浏览 • 2019-04-18 11:48 • 来自相关话题

    # Zinx [![License](https://img.shields.io/badge/License-GPL%203.0-blue.svg)](LICENSE) [![Gitter](https://img.shields.io/badg ...查看全部
    # Zinx
    [![License](https://img.shields.io/badge/License-GPL%203.0-blue.svg)](LICENSE) [![Gitter](https://img.shields.io/badge/在线交流-Gitter-green.svg)](https://gitter.im/zinx_go/community) [![zinx详细教程](https://img.shields.io/badge/zinx详细教程-简书-red.svg)](https://www.jianshu.com/p/23d07c0a28e5) [![zinx原创书籍下载](https://img.shields.io/badge/原创书籍下载-Gitbook-black.svg)](https://legacy.gitbook.com/book/aceld/zinx/details)

    Zinx 是一个基于Golang的轻量级并发服务器框架

    ###源码地址:
    [https://github.com/aceld/zinx](https://github.com/aceld/zinx)

    ### 开发人员

    - 刘丹冰([@aceld](https://github.com/aceld))
    - 张超([@zhngcho](https://github.com/zhngcho))


    ## 一、写在前面

    我们为什么要做Zinx,Golang目前在服务器的应用框架很多,但是应用在游戏领域或者其他长链接的领域的轻量级企业框架甚少。

    设计Zinx的目的是我们可以通过Zinx框架来了解基于Golang编写一个TCP服务器的整体轮廓,让更多的Golang爱好者能深入浅出的去学习和认识这个领域。

    Zinx框架的项目制作采用编码和学习教程同步进行,将开发的全部递进和迭代思维带入教程中,而不是一下子给大家一个非常完整的框架去学习,让很多人一头雾水,不知道该如何学起。

    教程会一个版本一个版本迭代,每个版本的添加功能都是微小的,让一个服务框架小白,循序渐进的曲线方式了解服务器框架的领域。

    当然,最后希望Zinx会有更多的人加入,给我们提出宝贵的意见,让Zinx成为真正的解决企业的服务器框架!在此感谢您的关注!

    ## 二、初探Zinx架构
    ![1-Zinx框架.png](https://upload-images.jianshu.io/upload_images/11093205-21a249a83fec62e9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    ## 三、Zinx详细教程(代码教程同步更新)
    [《Zinx框架教程-基于Golang的轻量级并发服务器》](https://www.jianshu.com/p/23d07c0a28e5)

    ## 四、Zinx开发API文档

    ### 快速开始

    #### server
    基于Zinx框架开发的服务器应用,主函数步骤比较精简,最多主需要3步即可。
    1. 创建server句柄
    2. 配置自定义路由及业务
    3. 启动服务

    ```go
    func main() {
    //1 创建一个server句柄
    s := znet.NewServer()

    //2 配置路由
    s.AddRouter(0, &PingRouter{})

    //3 开启服务
    s.Serve()
    }
    ```

    其中自定义路由及业务配置方式如下:
    ```go
    import (
    "fmt"
    "zinx/ziface"
    "zinx/znet"
    )

    //ping test 自定义路由
    type PingRouter struct {
    znet.BaseRouter
    }

    //Ping Handle
    func (this *PingRouter) Handle(request ziface.IRequest) {
    //先读取客户端的数据
    fmt.Println("recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData()))

    //再回写ping...ping...ping
    err := request.GetConnection().SendBuffMsg(0, []byte("ping...ping...ping"))
    if err != nil {
    fmt.Println(err)
    }
    }
    ```

    #### client
    Zinx的消息处理采用,`[MsgLength]|[MsgID]|[Data]`的封包格式
    ```go
    package main

    import (
    "fmt"
    "io"
    "net"
    "time"
    "zinx/znet"
    )

    /*
    模拟客户端
    */
    func main() {

    fmt.Println("Client Test ... start")
    //3秒之后发起测试请求,给服务端开启服务的机会
    time.Sleep(3 * time.Second)

    conn,err := net.Dial("tcp", "127.0.0.1:7777")
    if err != nil {
    fmt.Println("client start err, exit!")
    return
    }

    for n := 3; n >= 0; n-- {
    //发封包message消息
    dp := znet.NewDataPack()
    msg, _ := dp.Pack(znet.NewMsgPackage(0,[]byte("Zinx Client Test Message")))
    _, err := conn.Write(msg)
    if err !=nil {
    fmt.Println("write error err ", err)
    return
    }

    //先读出流中的head部分
    headData := make([]byte, dp.GetHeadLen())
    _, err = io.ReadFull(conn, headData) //ReadFull 会把msg填充满为止
    if err != nil {
    fmt.Println("read head error")
    break
    }
    //将headData字节流 拆包到msg中
    msgHead, err := dp.Unpack(headData)
    if err != nil {
    fmt.Println("server unpack err:", err)
    return
    }

    if msgHead.GetDataLen() > 0 {
    //msg 是有data数据的,需要再次读取data数据
    msg := msgHead.(*znet.Message)
    msg.Data = make([]byte, msg.GetDataLen())

    //根据dataLen从io中读取字节流
    _, err := io.ReadFull(conn, msg.Data)
    if err != nil {
    fmt.Println("server unpack data err:", err)
    return
    }

    fmt.Println("==> Recv Msg: ID=", msg.Id, ", len=", msg.DataLen, ", data=", string(msg.Data))
    }

    time.Sleep(1*time.Second)
    }
    }
    ```

    ### Zinx配置文件
    ```json
    {
    "Name":"Zinx Game",
    "Host":"0.0.0.0",
    "TcpPort":8999,
    "MaxConn":3000,
    "WorkerPoolSize":10
    }
    ```

    `Name`:服务器应用名称

    `Host`:服务器IP

    `TcpPort`:服务器监听端口

    `MaxConn`:允许的客户端链接最大数量

    `WorkerPoolSize`:工作任务池最大工作Goroutine数量


    ### I.服务器模块Server
    ```go
    func NewServer () ziface.IServer
    ```
    创建一个Zinx服务器句柄,该句柄作为当前服务器应用程序的主枢纽,包括如下功能:

    #### 1)开启服务
    ```go
    func (s *Server) Start()
    ```
    #### 2)停止服务
    ```go
    func (s *Server) Stop()
    ```
    #### 3)运行服务
    ```go
    func (s *Server) Serve()
    ```
    #### 4)注册路由
    ```go
    func (s *Server) AddRouter (msgId uint32, router ziface.IRouter)
    ```
    #### 5)注册链接创建Hook函数
    ```go
    func (s *Server) SetOnConnStart(hookFunc func (ziface.IConnection))
    ```
    #### 6)注册链接销毁Hook函数
    ```go
    func (s *Server) SetOnConnStop(hookFunc func (ziface.IConnection))
    ```
    ### II.路由模块

    ```go
    //实现router时,先嵌入这个基类,然后根据需要对这个基类的方法进行重写
    type BaseRouter struct {}

    //这里之所以BaseRouter的方法都为空,
    // 是因为有的Router不希望有PreHandle或PostHandle
    // 所以Router全部继承BaseRouter的好处是,不需要实现PreHandle和PostHandle也可以实例化
    func (br *BaseRouter)PreHandle(req ziface.IRequest){}
    func (br *BaseRouter)Handle(req ziface.IRequest){}
    func (br *BaseRouter)PostHandle(req ziface.IRequest){}
    ```


    ### III.链接模块
    #### 1)获取原始的socket TCPConn
    ```go
    func (c *Connection) GetTCPConnection() *net.TCPConn
    ```
    #### 2)获取链接ID
    ```go
    func (c *Connection) GetConnID() uint32
    ```
    #### 3)获取远程客户端地址信息
    ```go
    func (c *Connection) RemoteAddr() net.Addr
    ```
    #### 4)发送消息
    ```go
    func (c *Connection) SendMsg(msgId uint32, data []byte) error
    func (c *Connection) SendBuffMsg(msgId uint32, data []byte) error
    ```
    #### 5)链接属性
    ```go
    //设置链接属性
    func (c *Connection) SetProperty(key string, value interface{})

    //获取链接属性
    func (c *Connection) GetProperty(key string) (interface{}, error)

    //移除链接属性
    func (c *Connection) RemoveProperty(key string)
    ```


    ---
    ### 关于作者:

    作者:`Aceld(刘丹冰)`
    简书号:`IT无崖子`

    `mail`:
    [danbing.at@gmail.com](mailto:danbing.at@gmail.com)
    `github`:
    [https://github.com/aceld](https://github.com/aceld)
    `原创书籍gitbook`:
    [http://legacy.gitbook.com/@aceld](http://legacy.gitbook.com/@aceld)

    beego:在go1.10中在没设置GOPATH的情况下将不会工作

    回复

    hanchao 发起了问题 • 1 人关注 • 0 个回复 • 629 次浏览 • 2019-03-13 11:28 • 来自相关话题

    go-telnet包如何非阻塞得读

    回复

    zhougb3 发起了问题 • 1 人关注 • 0 个回复 • 438 次浏览 • 2019-03-08 18:30 • 来自相关话题

    有没有能接go的,请联系我

    回复

    Mandy 发起了问题 • 1 人关注 • 0 个回复 • 619 次浏览 • 2019-02-19 20:00 • 来自相关话题

    go mod包管理+docker容器化必看练手项目,真香~

    erik 发表了文章 • 1 个评论 • 785 次浏览 • 2019-01-11 21:10 • 来自相关话题

    ### hi guys! ![](https://github.com/ErikJiang/market_monitor/blob/master/app/src/public/gopher.png) ...查看全部
    ### hi guys!

    ![](https://github.com/ErikJiang/market_monitor/blob/master/app/src/public/gopher.png)


    > 本项目见:[market_monitor](https://github.com/ErikJiang/market_monitor) , 喜欢的话,请加 star 或 fork ~

    这是一个初级 Gopher 练手的小项目,该项目功能简单,主要实现监测币市行情变化、达到预警效果的功能,大致的使用场景如下:
    > 1. 用户登录服务;
    > 2. 用户设置关注的币种及预警的走势价格;
    > 3. 当行情变化触发到用户的预警设置时,服务将自动发送提醒邮件通知用户;

    ok, 就是酱紫,简明的功能,通过这个小项目你能学到:

    * [基于 Go Mod 的项目包管理](https://github.com/JiangInk/market_monitor/wiki/GoModTutorials)
    * [Gin 框架的基本开发](https://github.com/JiangInk/market_monitor/wiki/GoGinTutorials)
    * [Gin 服务跨域问题的处理](https://github.com/JiangInk/market_monitor/wiki/GinCORSTutorials)
    * [基于 JWT 注册、登录等验证流程](https://github.com/JiangInk/market_monitor/wiki/JwtTutorials)
    * [数据库 MySQL ORM 的基本使用](https://github.com/JiangInk/market_monitor/wiki/GORMTutorials)
    * [缓存数据库 Redis 的基本使用](https://github.com/JiangInk/market_monitor/wiki/RedisTutorials)
    * [为项目工程添加配置文件](https://github.com/JiangInk/market_monitor/wiki/ConfigTutorials)
    * [在项目中添加日志](https://github.com/JiangInk/market_monitor/wiki/LoggerTutorials)
    * [基于 Cron 的 Scheduler 定时任务](https://github.com/JiangInk/market_monitor/wiki/CronTutorials)
    * [如何为编写的 API 添加 Swagger 接口文档](https://github.com/JiangInk/market_monitor/wiki/GinSwagTutorials)
    * [如何使应用服务平滑重启](https://github.com/JiangInk/market_monitor/wiki/LiveReloadTutorials)
    * [构建应用服务 docker 镜像](https://github.com/JiangInk/market_monitor/wiki/DockerBuildTutorials)
    * [Docker Compose 容器编排部署](https://github.com/JiangInk/market_monitor/wiki/ComposeDeployTutorials)

    功能点:

    1. 常规的用户注册、登录、登出、身份验证等功能
    2. 监测市场源选择(用于选择支持监测的交易所,开始仅支持监测 gate.io )
    3. 监测策略设置管理(用于设置监测的具体要求,开始仅支持走势大小值预警)
    4. 监测信息通知(在监测策略被触发后,用于通知用户,开始仅支持邮件通知)

    本项目用到的依赖:

    * web framework: [gin](https://github.com/gin-gonic/gin)
    * redis: [redigo](https://github.com/gomodule/redigo)
    * mysql: [gorm](https://github.com/jinzhu/gorm)
    * logger: [zerolog](https://github.com/rs/zerolog)
    * scheduler: [cron](https://github.com/robfig/cron)
    * config: [viper](https://github.com/spf13/viper)
    * json web token: [jwt-go](https://github.com/dgrijalva/jwt-go)
    * swagger docs: [swaggo](https://github.com/swaggo/gin-swagger)


    tendermint区块链五分钟入门

    ezpod 发表了文章 • 0 个评论 • 355 次浏览 • 2019-01-09 14:45 • 来自相关话题

    区块链应用已经从单纯电子现金发展到去中心化投票等更多的领域,但是区块链这样的分布式系统的开发还存在一些困难的问题:安全、可靠性、敏捷度、以及一致性保证等等。Tendermint的目的就是致力于解决分布式系统开发中像公示算法这样的技术难点,而让Tendermin ...查看全部
    区块链应用已经从单纯电子现金发展到去中心化投票等更多的领域,但是区块链这样的分布式系统的开发还存在一些困难的问题:安全、可靠性、敏捷度、以及一致性保证等等。Tendermint的目的就是致力于解决分布式系统开发中像公示算法这样的技术难点,而让Tendermint区块链应用开发者可以将关注点集中在业务逻辑上。


    > 如果希望快速掌握基于Tendermint的区块链开发,推荐汇智网的在线互动课程:[Tendermint区块链开发详解](http://xc.hubwiz.com/course/5bdec63ac02e6b6a59171df3?affid=govip7878),技术问题可咨询课程助教。

    ## Tendermint简介

    Tendermint萌芽于比特币、以太坊这样的加密货币,它的目标是提供一个比比特币的工作量证明(PoW)更加高效和安全的共识算法。简单地说,Tendermint是一个可供二次开发的软件包,可以在多台机器上安全、一致地实现应用状态的复制。

    - Tendermint可以在不超过1/3的机器失效时依然正常工作,无论失效的原因
    是什么。Tendermint实现了拜占庭容错。
    - 任何正常工作的机器都会收到相同的交易日志,并分别推导出相同的状态

    Tendermint的特性如下图所示:

    ![](http://blog.hubwiz.com/2019/01/08/tendermint-101/feature-cn.png)


    Tendermint包含两个主要的组件:

    - 区块链共识引擎,即:Tendermint内核
    - 应用与区块链接口,即:**A**pplication **B**lock**C**hain **I**nterface

    Tendermint内核可以托管任意的应用状态,因此可以使用任何语言开发区块链软件:Haskell、GoLang、或者Rust都可以用来开发ABCI应用。

    其他区块链的一个问题是,它们都是单体设计思维的软件。以比特币为例,比特币的设计就是单体的,其区块链技术栈都包含在单一程序里,需要处理从P2P链接到交易广播、达成共识乃至检查账户余额的一切事情。

    单体应用通常不容易扩展、升级或再利用,而Tendermint则致力于将区块链技术栈的两个核心组件与其他部分解耦:共识引擎和P2P连接 —— 事实上这也是开发区块链的最困难的两个技术环节 —— 从而可以使用任何开发语言来开发ABCI应用。

    废话不多说了,让我们撸起袖子开干!

    ## Tendermint开发环境搭建与测试

    ### STEP 1:下载Tendermint内核

    tendermint内核采用Go开发,有官方预编译程序,下载地址:[Tendermint Core](https://github.com/tendermint/tendermint/releases)。

    下载后直接解压,并将tendermint程序目录添加到环境变量PATH的设置里。

    ### STEP 2:初始化Tendermint

    执行如下命令初始化Tendermint:

    ```
    ~$ tendermint init
    ```

    应当可以在终端看到tendermint的输出信息:

    ```
    I[10–18|20:14:08.996] Generated private validator module=main path=/Users/niharikasingh/.tendermint/config/priv_validator.json
    I[10–18|20:14:08.996] Generated node key module=main path=/Users/niharikasingh/.tendermint/config/node_key.json
    I[10–18|20:14:08.996] Generated genesis file module=main path=/Users/niharikasingh/.tendermint/config/genesis.json
    ```

    ### STEP 3:启动Tendermint节点

    使用node子命令启动Tendermint节点:

    ```
    ~$ tendermint node -proxy_app=kvstore
    ```

    `-proxy_app`运行标志用来指定一个内置的ABCI应用,例如kvstore是tendermint程序内置的键值对状态机。你应该可以看到如下的tendermint程序输出:

    ```
    I[10–18|20:16:40.037] Starting multiAppConn module=proxy impl=multiAppConn
    ...
    I[10–18|20:16:42.051] enterPropose: Our turn to propose module=consensus height=2 round=0 proposer=601302EBD1F8B4BCE9F99B219965F2796AB6BB10 privValidator=”PrivValidator{601302EBD1F8B4BCE9F99B219965F2796AB6BB10 LH:1, LR:0, LS:3}”
    I[10–18|20:16:42.055] Signed proposal module=consensus height=2 round=0 proposal=”Proposal{2/0 1:48B45F4423A5 (-1,:0:000000000000) F52DF1F111D8 @ 2018–10–18T14:46:42.051967933Z}”
    I[10–18|20:16:42.056] Received proposal module=consensus proposal=”Proposal{2/0 1:48B45F4423A5 (-1,
    ```

    ### STEP 4:提交交易

    要提交一个交易,可以使用curl向Tendermint节点的RPC服务发出请求,例如:

    ```
    ~$ curl http://localhost:26657/broadcast_tx_commit?tx=\"niharika\"
    ```

    响应结果如下:

    ```
    {
    "jsonrpc":"2.0",
    "id": "",
    "result": {
    "check_tx": {
    "gasWanted": "1"
    },
    "deliver_tx": {
    "tags": [
    {
    "key": "YXBwLmNyZWF0b3I=",
    "value": "amFl"
    },
    {
    "key": "YXBwLmtleQ==",
    "value": "bmloYXJpa2E="
    }
    ]
    },
    "hash": "EAAD936D3EDCCCF5DD214E02BB4065E5511CA5AC",
    "height": "3533"
    }
    }
    ```

    注意结果中的value字段,例如`bmloYXJpa2E`,这其实是字符串`niharika`的base64编码。

    现在让我们查询一下:

    ```
    ~$ curl -s 'localhost:26657/abci_query?data="niharika"'
    ```

    响应结果如下:

    ```
    {
    "jsonrpc":"2.0",
    "id": "",
    "result": {
    "response": {
    "log": "exists",
    "index": "-1",
    "key": "bmloYXJpa2E=",
    "value": "bmloYXJpa2E="
    }
    }
    }
    ```

    很好,看起来我们的Tendermint内核与ABCI接口的工作一切正常!

    在本文中,我们成功安装并启动了tendermint内核,然后通过节点旳ABCI接口提交了一个交易来更新内置键值库应用的状态,最后通过ABCI接口查询了ABCI应用的状态。这就是基于Tendermint进行应用开发的核心模型:可以使用任何开发语言来代替curl完成这些操作,实现自己的ABCI应用!

    ---

    原文链接:[自主可控区块链神器Tendermint五分钟入门 - 汇智网](http://blog.hubwiz.com/2019/01/08/tendermint-101/)

    Mastering Go翻译项目召集

    回复

    Cloud001 发起了问题 • 4 人关注 • 0 个回复 • 656 次浏览 • 2019-01-04 21:58 • 来自相关话题