别太在意编程语言

背景 经常有人这样说: PHP是最好的语言 现在golang越来越吃香,好找工作 python学习的人越来越多,太难了 对于这些,我想说:别太在意编程语言。 ...

February 18, 2020

深入分析Golang sync.pool优化

前言 最近golang的1.13版本发布了,有很多新特性与改进合入。这里主要分析sync.pool的优化。 本文主要解答以下几个问题: sync.pool优化体现在哪里? 优化是如何实现? 优化的好处有哪些? 优化 具体优化项如下: ...

September 6, 2019

深入分析Golang sync.pool

定义 sync.Pool是一个可以存或取的临时对象池。对外提供New、Get、Put等API,利用mutex支持多线程并发。 目标 sync.Pool解决以下问题: ...

June 10, 2019

Golang最工程化的语言

Golang是什么语言 PHP是最好的语言。 Haskell最难学的语言。 Golang最工程化的语言。 下面分别从语言层面及软件工程两个方面进行说明。 语言 安全性 相比较于C/C++,golang不支持指针操作,不支持隐式类型转换,支持内存溢出与越界检查。 ...

July 3, 2018

Gorm小技巧: 如何优雅地创建多个相同的表

背景 因为需要bitfinex抓取各种历史交易信息。为了实现可扩展与便于数据管理,在数据架构设计方面满足下面的需求: 不同的交易对的交易数据放到不同的表上。 方案 方案1 编写sql,通过多条sql语句创建多个不同名字的表。 ...

December 21, 2017

slice复用的陷阱

前言 先下结论:slice复用得当心,引用不当深埋雷。如若复用请分叉,分叉之后再使用。 问题 先看一下代码吧 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package main import ( "fmt" ) func a() { x := []int{} x = append(x, 0) x = append(x, 1) // commonTags := labelsToTags(app.Labels) y := append(x, 2) // Tags: append(commonTags, labelsToTags(d.Labels)...) z := append(x, 3) // Tags: append(commonTags, labelsToTags(d.Labels)...) fmt.Println(y, z) } func b() { x := []int{} x = append(x, 0) x = append(x, 1) x = append(x, 2) // commonTags := labelsToTags(app.Labels) y := append(x, 3) // Tags: append(commonTags, labelsToTags(d.Labels)...) z := append(x, 4) // Tags: append(commonTags, labelsToTags(d.Labels)...) fmt.Println(y, z) } func main() { a() b() } 上面的如此简单的代码,分析代码希望得到预期结果如下: ...

July 28, 2017

使用golang present工具制作presentation

依赖 依赖golang的开发环境 安装 present工具在golang.org/x/tools中,依赖golang.org/x/net包,安装过程如下: ...

May 10, 2017

Go的50度灰补充--http response只能读一次

问题 还是从代码开始吧 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 func fetch(url string) { tlsConfig := &tls.Config{ InsecureSkipVerify: true, } transport := &http.Transport{ TLSClientConfig: tlsConfig, } client := http.Client{Transport: transport} resp, err := client.Get(url) if err != nil { fmt.Println(err) <-time.After(300 * time.Second) go fetch(url) return } buf, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("fetchyh:", err) return } save(buf) //保存html到文件 defer resp.Body.Close() // http to doc doc, err := goquery.NewDocumentFromResponse(resp) if err != nil { fmt.Println(err, "http resp to doc failed") return } /* <div class="datanowin" id="myCont2"> */ datanowin := doc.Find("div.datanowin") fmt.Println("datanowin:", datanowin.Length()) tables := datanowin.Find("table") tablelen := tables.Length() fmt.Println("tablelen:", tablelen) for i := 0; i < tablelen; i++ { item := tables.Eq(i) tableDo(item) } fmt.Println(doc.Find(".table").Length()) } 调用上面的代码后,html网页上没有找到自己所需要的内容,上面的代码问题在哪里? 假想一下,一般有以下原因选项: ...

February 20, 2017

从C语言epoll编程到go net实现分析

说明 go源码版本:1.7 go源码运行环境:Linux epoll在c语言编程示例 先看一下大家比较熟悉的epoll在c语言中应用,代码取自rtmpserver_demo中的文件rtmpepollsrv.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 int RtmpSessionHandle(int iFd, int iEvent, void *pContext) { int iRet; RTMP_SESSION *pSession = (RTMP_SESSION *)pContext; if(iEvent&EPOLLIN ) { if(0 == pSession->handshake) { iRet = RtmpSessionHandshake(pSession); if(0 != iRet) { RtmpSessionHandleFin(pSession); } } else { iRet = RtmpPktHandle(pSession); } } if(iEvent & (EPOLLERR |EPOLLHUP) ) { RtmpSessionHandleFin(pSession); } return iRet; } int ListenHandle(int iFd, int iEvent, void *pContext) { int iNewFd; int iRet = 0; struct sockaddr tmpAddr; memset(&tmpAddr, 0, sizeof(tmpAddr)); int iSocketSize = sizeof(tmpAddr); EPOLL_CTX *pCtx; RTMP_SESSION *pServer; if(iEvent|EPOLLIN) { iNewFd = accept(iFd, &tmpAddr, (socklen_t *)&iSocketSize); if(RTMP_EPOLLSRV_INVALIDFD < iNewFd) { pServer = (RTMP_SESSION *)malloc(sizeof(RTMP_SESSION)); if(NULL == pServer) { return -1; } pServer->handshake = 0; pCtx = (EPOLL_CTX *)malloc(sizeof(EPOLL_CTX)); if(NULL == pCtx) { free(pServer); return -1; } pServer->socket = iNewFd; pCtx->iFd = iNewFd; pCtx->pContext = pServer; pCtx->pfHandle = RtmpSessionHandle; /* 加入epoll */ iRet = epoll_op(g_iEpollFd, EPOLL_CTL_ADD, iNewFd, EPOLLIN|EPOLLERR|EPOLLHUP, pCtx); } else { printf("accept errno:%s",strerror(errno)); } } return iRet; } int epoll_op(int iEpollFd, int iOp, int iFd, int iEvent, EPOLL_CTX *pCtx) { int iRet; struct epoll_event ev; ev.events = iEvent; ev.data.ptr = pCtx; iRet = epoll_ctl(iEpollFd, iOp, iFd, &ev); return iRet; } int epoll_loop(int iEpollFd) { int iNum; struct epoll_event astEpEvent[RTMP_EPOLLSRV_MAXEPOLL]; int i; EpollCallBack_PF pfHandle; EPOLL_CTX *pCtx; for( ; ;) { iNum= epoll_wait(iEpollFd, &astEpEvent[0], RTMP_EPOLLSRV_MAXEPOLL, -1); if( 0 < iNum) { for(i = 0; i < iNum; i++) { pCtx = (EPOLL_CTX *)astEpEvent[i].data.ptr; pfHandle = pCtx->pfHandle; (void)pfHandle(pCtx->iFd, astEpEvent[i].events, pCtx->pContext); } } else { printf("epoll_wait failed\r\n"); } } return 0; } int main(void) { int iFd; struct sockaddr_in addr; printf("in the main\r\n"); /* 初始化epoll */ g_iEpollFd = epoll_create(200); if(RTMP_EPOLLSRV_INVALIDFD >= g_iEpollFd) { printf("create epoll failed\r\n"); return -1; } /* 创建侦听端口 */ iFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(RTMP_EPOLLSRV_INVALIDFD >= iFd) { printf("create listen socket failed\r\n"); return -1; } addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(g_cRtmpSrvAddr); addr.sin_port = htons(g_usRtmpSrvPort); if( 0 != bind(iFd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in))) { return -1; } if( 0 != listen(iFd, 200)) { return -1; } EPOLL_CTX *pEpollCtx = (EPOLL_CTX *)malloc(sizeof(EPOLL_CTX)); if(NULL == pEpollCtx) { return -1; } pEpollCtx->iFd = iFd; pEpollCtx->pfHandle = ListenHandle; pEpollCtx->pContext = NULL; /* 加入epoll */ if(0 != epoll_op(g_iEpollFd, EPOLL_CTL_ADD, iFd, EPOLLIN|EPOLLERR|EPOLLHUP, pEpollCtx)) { return -1; } g_iListenFd = iFd; epoll_loop(g_iEpollFd); return 0; } 功能 上述代码代码主要通过epoll实现一个最基本的网络服务器(侦听一个端口,处理这个端口上连接) ...

September 10, 2016

Go channel 编程篇

本篇以ChanBroker版本迭代过程,总结常见Channel编程问题 简介 ChanBroker设计主要参考Kafka模型,主要提供进程内goroutine之间通信,实现以下功能: 支持多个Publisher发布内容 支持Subscriber注册与去注册订阅 发布内容可以是任何形式 ChanBroker根据订阅情况完成内容推送 版本1 具体代码如下: ...

August 20, 2016