golang
golang学习、工作
w妙音
这个作者很懒,什么都没留下…
展开
-
全局gin对象如何在子模块中修改Logger
gin是通过中间件写日志, 日志对象是中间件的闭包变量。在use加载中间件完成之后,无法修改日志对象。app := gin.Default()被放在了顶层模块,并且加载了默认中间件。借助zapio.Writer对象,通过修改它的Log属性实现。程序真正的log在子模块中初始化。在子模块中如何修改gin的日志?以下是设置gin日志的方法。原创 2022-12-11 17:22:08 · 438 阅读 · 0 评论 -
viper监控文件变化出现两次事件
监控配置文件变化,如果内容发生了修改,需要及时加载. 使用viper监控文件变化发现了, 对文件修改一次,会出发两次事件.原创 2022-09-17 19:57:31 · 896 阅读 · 1 评论 -
gin支持prometheus
gin使用了微服务架构, 如何将自己的服务都监控起来?原创 2022-08-03 15:21:45 · 1221 阅读 · 0 评论 -
golang实现枚举类型
枚举类型是一种类型, 它的值只有有限个. 换而言之, 枚举类型=一个类型+N个离散值go的实现, 可以自定义一个类型, 把它作为枚举类型, 然后使用该类型定义N个常量.原创 2022-07-25 10:47:54 · 2265 阅读 · 0 评论 -
goja能够做什么
goja是什么goja实现了ECMAScript 5.1(+)特性1. 完整支持ECMAScript 5.12. 测试通过了ECMAScript官方所有测试用例3. 支持任何能在babel, typescript编译器中运行任何ES54. 支持sourcemapgoja能够做什么执行js表达式func testExpression(){ //创建运行实例 vm := goja.New() //运行表达式 v, _ := vm.RunString("2 + 2") //获原创 2022-05-11 10:17:01 · 2196 阅读 · 0 评论 -
golang实现单例模式
golang实现单例模式go已经提供了实现单例模式的工具sync.Once示例借用sync.Once的一次性特点import ( "sync")type singleton struct {}var _instance *singletonvar _once sync.Oncefunc GetInstance() *singleton { _once.Do(func() { instance = &singleton{} }) return instanc原创 2022-05-06 10:17:15 · 413 阅读 · 0 评论 -
基于ectd实现go的服务注册
描述基于etcd实现go程序的服务注册,所看的学习资料均比较简单, 实际中要经过反复测试,自己写了一个先用着,有坑再填.需求1. 注册一个服务: 程序启动时2. 注销服务: a. 程序异常退出时, 自动注销, 有5秒TTL延迟; b. 调用Stop()接口主动注销3. 健壮性: a.ectd单节点重启, ectd本身支持; b. etcd全部重启后, 能够恢复正常4. key的格式: 前缀/ip/pid5. value: 字符串.(可以先转为json, 再转string)创建etcd客户原创 2021-11-27 18:40:46 · 567 阅读 · 0 评论 -
go和python解码msgpack不一致
描述有一个消息字典类型, 使用go进行编码, 传入消息中间件。同时有一个python程序监听, 监听到消息之后进行解码, 遇到了编码问题环境go使用: github.com/vmihailenco/msgpack/v5 v5.3.4python使用: msgpack==1.0.2python解码# go编码的对象是个字典,value可能包含了数组,并且数组类型复杂msgpack.unpackb(xxx)错误提示UnicodeDecodeError: 'utf-8' codec原创 2021-11-27 18:31:02 · 720 阅读 · 0 评论 -
golang位移操作的一个小坑
问题描述现有int16类型的整数,将它转为两个字节存放。在还原时,一不小心会就被坑。错误用法length := int(keyBytes[cursor] + keyBytes[cursor+1] <<8)正确用法keyBytes := []byte{ 16, 1}length := int(uint16(keyBytes[cursor]) + uint16(keyBytes[cursor+1]) <<8)错误原因字节byte位移时类型不会自动变化, 先要转换类型原创 2021-11-25 16:02:07 · 513 阅读 · 0 评论 -
nats批量publish最后一条疑似丢失
问题描述写了一个测试脚本,从数据读取一组数据,然后逐条publish到nats-server中, 确定每条都publish了有另外一个程序中subscribe订阅,在该程序发现最后一条一直没收到环境go: 1.16nats-server程序摘要发布for _, record := range records{ ... gNatsConn.Publish(Topic, record) time.Sleep(time.Second*0.1) //原创 2021-11-14 13:20:34 · 353 阅读 · 0 评论 -
go版本的supervisord
#%%描述python版本的supervisrod, 在linux、windows系统中离线安装都不怎么方便. 是否有go版本的呢?github地址https://github.com/ochinchina/supervisord/踩坑记录编译32版本, 有些报错, 需要修改源码在ui界面快速点击start/stop, 进程可能会启动多个。需要加锁处理处理.用法配置文件查找顺序$CWD/supervisord.conf$CWD/etc/supervisord.conf原创 2021-11-14 13:14:32 · 983 阅读 · 0 评论 -
influxdb遇到时间点存储不了
问题描述有一份mysql存储的历史数据,准备把它转为influxdb存储, 时间点用的是mysql表中记录的创建时间,创建时间是时许的。环境描述influxdb: 2.0.8开发语言: goinflux客户端: influxdb-client-go 2.5.0关键代码摘要使用如下代码, 创建point,发现存储不了。point := influxdb2.NewPoint("table_name", map[string]string{ ...原创 2021-09-23 10:47:55 · 319 阅读 · 0 评论 -
influxdb如何把point中的多个field一起查出来
问题描述influx查询包含了水平拆分、垂直拆分. 查询结果的每一条记录record,只对应一个field写入一个point时包含多个field, 查询时如何将这几个field一起查出来呢?写入示例point := influxdb2.NewPoint("history", map[string]string{ "Version": DedefaultVersion, "Name": sh.Name, "Active": fmt.Sprin原创 2021-08-29 14:33:47 · 2550 阅读 · 0 评论 -
golang编译-ldflags -H windowsgui被认为是病毒
介绍使用walk为程序做了一个windows界面, cmd窗口需要隐藏。使用了 go build -ldflags="-H windowsgui"结果exe程序被杀毒软件认为是病毒为什么会认为是病毒?隐藏cmd窗口, 双击exe,可以直接启动,并且看不到任何窗口。这不就是病毒的喜欢干的事吗.所以有些杀毒软件, 干脆通杀, 使用了 "-H windowsgui" 直接被认为是病毒我们这些正常的需求该咋办呢?解决办法在程序中,使用代码隐藏cmd窗口import "github.co原创 2021-08-26 17:18:49 · 2961 阅读 · 5 评论 -
golang离线环境依赖包问题
问题描述在一个win10虚拟机中安装了go(go1.16.4)的开发环境, 其中有自己的项目,此时正常编译。然后将这个虚拟机放到内网,内网网络受限,不允许访问外网如果新一个依赖包,该怎么办呢?方法一: 拷贝vendor目录(推荐)在外网环境项目目录,生成vendorgo mod vendor将vendor拷贝进内网,放在内网项目目录缺点:只能当前项目使用优点:体积小类似python的pip download -r requipment.txt,将包下载后放到一个目录方法二:原创 2021-08-21 17:02:26 · 3825 阅读 · 4 评论 -
nats-server系统服务只能使用sc命令注册
起因描述windows环境下nats-server注册成系统, 官方推荐是sc命令而我觉得sc命令台太麻烦, 为什么不用github.com/kardianos/service,或者更方便的工具呢?方法一:使用nssm通过界面进行配置下载地址http://nssm.cc/download过程省略结果死活不行,由于是第三方工具,出错找不到原因,放弃方法二:通过服务外壳作为系统服务介绍使用go生成一个demo.exe,再将demo.exe注册成系统,demo.exe读取配原创 2021-08-19 02:38:39 · 423 阅读 · 0 评论 -
zap日志写入通道被覆盖
描述实现了一个io.Writer接口,允许zap日志写入,传递给界面,出现了日志被覆盖、重复的情况。原因io.Writer的接口Write传入的[]byte真实类型是slice。通道传递slice时,用的是引用传递,所以真实数据有被覆盖的情况示例zap初始化...out = COut()zapcore.NewCore(encoder, zapcore.AddSync(out), clevel),...自定义日志写入Channelpackage logsvar _Globa原创 2021-08-17 19:54:02 · 305 阅读 · 0 评论 -
msgpack代替json防止丢失类型
描述开发了一个通信协议, 协议对数据类型比较敏感, 根据不同数据数据类型使用不同格式。golang的数据类型能够满足需求。然后,讲协议转为http方式时,如果传入json,会发现数据类型不符合预期例如,本来是应该int结果是float64; 本来应该是[]byte,结果是string环境http服务器: gin开发语言: golang解决方法探寻什么传输协议会带上数据类型?json类型丢失默认情况下gin的BindJSON,可将传入的参数绑定到具体的结构体,产生类型转换。然后,我的结原创 2021-06-30 15:06:26 · 343 阅读 · 0 评论 -
nats的安装docker方式
描述docker-compose方式启动nats-server。nats的镜像非常小, docker-cpomse进行管理。下面是配置方式docker-compose.yaml配置version: "2"services: nats-server: #image: provide/nats-server:latest image: nats:latest volumes: - ./nats-server.conf:/nats-s原创 2021-06-12 11:58:42 · 2067 阅读 · 0 评论 -
go实现Event事件模型修正
描述之前文章中实现了event事件模型,实际使用中发现了几个问题并发会出现情况send先执行, 此时还没有waiter。将wait拆分成addWaiter和wait()不能使用缓冲通道。会出现send完成,wait还未收到的情况。用法修正e.Reset()waiter := e.AddWaiter()waiter := e.Wait(waiter, xxx)e.Send(xxx)事件实现package commonimport ( "context" "errors原创 2021-06-03 22:35:51 · 268 阅读 · 0 评论 -
rabbitmq辣眼睛的忙等
背景用golang做了一个分布式结构的系统, 消息服务器用了rabbitmq。整体是基于machinery+rabbitmq形式的分布式任务系统在做压力测试时,发现rabbitmq的cpu使用率飙升分析官方给出的解释scheduler采用了忙等,来提高消息传递性能https://www.rabbitmq.com/runtime.html#cpu其中也讲了一些方法来降低cpu使用率官方建议rabbtimq最好是装在单独的服务器,不与其它应用共用。也介绍了修改cpu使用个数原创 2021-05-28 07:10:49 · 221 阅读 · 0 评论 -
go实现Event事件context版
描述上一篇文章,写了go如何实现Event事件,有几个可以优化的地方.sync.Map保存结果可以不用这么复杂.改用context关闭通道更加方便Event实现package commonimport ( "context" "errors" "go.uber.org/zap" "time")func NewEvent() *Event { e := &Event{ log: zap.S(), } e.Reset() return e}type Even原创 2021-05-22 08:24:44 · 335 阅读 · 1 评论 -
go如何实现并发安全的优先级队列
描述go的如何实现优先级队列?优先级别队列是否并发安全?我的需求场景实现了一个通信协议,收发消息。发送通道会阻塞。如果拥堵时,要控制拥堵消息的优先顺序。优先级用Priority加上时间, Priority小优先, 早到优先。原理通过实现官方接口heap, 得到优先级队列使用用chan进行控制并发控制,达到并发安全的效果优先队列实现package queueimport ( "xxxx/packets" "container/heap" "time")//---原创 2021-05-20 19:10:34 · 865 阅读 · 0 评论 -
go实现Event事件
描述go协程之间用通道通信,如何将它改造成事件形式。需求描述以下是我的需求e := NewEvent()//协程1等待结果, 10是等待时间e.Wait(10)//协程2发送结果e.Send(xxxx)原理原理比较简单,不描述了示例package commonimport ( "go.uber.org/zap" "sync" "time")var NOT_USED interface{} = struct{}{}func NewEvent() *Event {原创 2021-05-16 21:08:33 · 2078 阅读 · 1 评论 -
golang如何正确关闭计时器
描述go的官方库计时器, 有一个陷阱,ticker.Stop()如果不注意会导致协程无法关闭。如果我们想强制中断计时,该如何做?示例:ticker.Stop()会导致协程无法结束下面示例便于理解func main(){ ticker := time.NewTicker(time.Second*10) go func(){ log.Println("go start") select{ case <-ticker.C:原创 2021-05-16 20:10:59 · 1088 阅读 · 1 评论 -
golang用通道实现串口信号量
描述串口通信,使用权该谁?需要采用信号量,进行控制。go如何实现?原理缓冲通道的缓冲大小等于资源数time计时器控制超时示例func NewPortAvailableSem()*PortAvailableSem{ ps := &PortAvailableSem{ PortChan: make(chan int, 1), } ps.PortChan <- 1 return ps}type PortAvailableSem struct{ PortCh原创 2021-05-15 16:07:02 · 259 阅读 · 1 评论 -
golang超时等待
描述go中如何实现超时等待python实现:队列超时等待queue.get(block=True, timeout=45)go实现:通道+time计时select会阻塞两个case,直到其中一个返回。如果是response,则停止计时器; 否则,就返回错误func _waitResponse(queueChan *chan int, timeout time.Duration) (int, error){ ticker := time.NewTicker(timeout) var resp原创 2021-05-08 11:09:51 · 562 阅读 · 0 评论 -
任务队列machinery用法
描述go实现的基于消息中间件的异步任务队列, 下面是学习笔记使用概述步骤1: 创建server,配置参数、注册task。(此处server只是个配置作用, 并不是单独的server进程)步骤2: 启动worker步骤3: 发送task与celery的用法是完全一致的创建serverfunc startServer() (*machinery.Server, error) { cnf := &config.Config{ Broker: "amqp://gue原创 2021-05-01 09:24:51 · 621 阅读 · 1 评论 -
golang如何实现静态变量的效果
说明go的结构和方法接收者, 可以模拟类的概念, 然而go不支持静态变量不能总是每次先创建一个结构体, 然后获取变量吧该如何办?如何创建"类"先展示一下,平时我是如何创建"类"的私有的结构体作为真实对象对外暴露方法,这个方法类似class可以作为参数传递,使用这个class就可以创建对象BaseVar定义对外暴露的接口定义方法的interface,方便作为参数传递type BaseVar interface { //对外暴露的接口}//方便传递typ原创 2021-04-24 20:40:45 · 6657 阅读 · 1 评论 -
golang网络字节与基本类型转换
说明网络通信要将go基本数据类型转为字节, golang如何做?基本类型c类型go类型字节长度signed charint81unsigned charuint81_Boolbool1shortint162unsigned shortuint162intint324unsigned intuint324floatfloat324long longint648unsigned l longu原创 2021-04-15 21:29:21 · 1358 阅读 · 0 评论 -
golang的继承不是继承
问题struct嵌套,内层struct方法访问同名的属性,这个属性是谁的?示例package mainimport ( "fmt")type ProductA struct{ Name string}func (p *ProductA) PrintName(){ fmt.Println("a:", p.Name)}type ProductB struct{ ProductA Name string Level string}func main() { b原创 2021-04-12 19:43:08 · 167 阅读 · 0 评论 -
go的反射有什么不同
说明go的反射有什么不同, 与动态语言python有什么不同go反射的不同首先, go是静态强类型。再怎么反射它也是静态语言,不支持动态获取类型,例如,通过字符串"struct_name",创建struct_name对象go的反射,在于通过对象获取类型信息。例如,通过object,得到Type,然后获取Type的属性reflect的入口是TypeOf和ValueOf。一切的前提是先有对象佛說大乘無量壽莊嚴清淨平等覺經pdf净土大经科注2014-doc此生必看的科学实验-水知道原创 2021-04-10 11:05:53 · 81 阅读 · 0 评论 -
gorm模型定义原理借鉴分析
说明python有元类概念,在定义db模型时,相当方便,极大简化代码go中没有元类概念, gorm有模型定义,看看它怎么实现,能否借鉴gorm原理gorm运用了结构体标签,通过reflect获取标签内容,这是基本原理,这里不做介绍。关注它如何运用这些特性,是否可以借鉴使用直接分析源码太复杂,绕的路径太多。基于gorm模型定义最核心的代码,写一个小例子,展示gorm的用法,这也是我需要借鉴的地方gorm所有的接口db.Create, db.Model,…最终都是调用schema.原创 2021-04-10 10:21:45 · 795 阅读 · 0 评论 -
nsq双机集群部署
问题双机nsq如果部署集群,如何保证高可用性单节点nsqlookup故障?单节点nsq故障?消息丢失?环境说明两台机器机器A 192.168.120.1机器B 192.168.120.101部署过程部署方法机器A部署一套nsqlookup+nsqd机器B部署一套nsqlookup+nsqd生产者将消息同时写入两个nsqd消费者监听两个nsqlookup结构图机器Ansqlookupd -broadcast-address 1原创 2021-04-02 13:23:43 · 798 阅读 · 1 评论 -
nsq.reader错误connection closed
描述学习官网例子时,会碰到的一个小错误. 过程描述:按照nsq官网,搭建一个nsq小集群2.使用python客户端pynsq编写测试客户端如果上面过程在一台机子上完成,不会有问题如果客户端与nsq不在一台机子上,会出现下面错误错误内容WARNING:nsq.reader:[localhost.localdomain:4150:test:abc] connection closedpython消费客户端import nsqdef handler(message):原创 2021-04-02 11:14:59 · 267 阅读 · 1 评论 -
golang的import原理
描述import是个很重要的东西,golang是怎么import的import查找包的顺序?import的是什么,包还是路径?自己项目中怎么importgolang的包管理历史第一阶段 早期golang,import是直接查找GOPATH/scr,GOPATH/scr,GOPATH/scr,GOROOT/scr目录第二阶段 v1.5开始采用vendor模式,每个项目有一个vendor目录,存放依赖包第三阶段 v1.12开始增加了go mod用于管理依赖包部分学习资料比较早,原创 2021-03-28 12:23:12 · 2474 阅读 · 0 评论