
go
pengpengzhou
主要学习语言Java,Nodejs,Go
展开
-
Go语言切片拷贝时容量对于效率的影响
由于append在编译期会转换成汇编代码,所以append本身几乎没有效率上的开销。真正影响效率的是切片的容量,如果能够预先知道拷贝所需要的容量大小,则在初始化切片时一定要指定容量大小,避免在拷贝过程中切片内部生成新的数组。......原创 2022-08-09 15:05:00 · 908 阅读 · 0 评论 -
Go后端开发的web框架对比
从Gin官网给出的性能对比来看,Gin在执行效率、响应时间、内存占用及内存分配方面都相当优秀,应该是后端开发比较理想的选择。原创 2022-07-26 11:28:52 · 1019 阅读 · 0 评论 -
Go语言采用go-redis模块对Redis进行批量执行smembers的示例
package mainimport ( "fmt" "github.com/go-redis/redis")func main() { client := redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6380", Password: "", DB: 0, }原创 2022-04-08 13:48:36 · 1698 阅读 · 1 评论 -
Go语言:HTTP响应头Transfer-Encoding: chunked和Content-Length的关系
如果没有显式的设定Content-Length请求头,则当响应Body的字节数小于2KB时,server会自动追加Content-Length;如果大于2KB,server不会再追加Content-Length,而是改为追加响应头Transfer-Encoding: chunked,Body会相应的采用chunk格式。Transfer-Encoding: chunked和Content-Length只会出现其中一个,不会同时出现,如果当Body大于2KB时,仍然想以非chunk方式返回,则需要在调用wri原创 2022-01-05 10:30:33 · 3842 阅读 · 0 评论 -
Go Nodejs Java Aes 128 CBC 加密解密结果保持一致
在多语言的生产环境下,常常是由一种语言进行加密而由另一种语言来进行解密,因此有必要保持各种语言之间加密解密算法的一致性。下面列出了Go,Nodejs,Java 的 Aes-128-Cbc的加密解密算法,它们的加解密结果是一致的。CBC比ECB加密强度更大,更难破解。Go 1.15package mainimport ( "bytes" "crypto/aes" "crypto/cipher" "encoding/hex"原创 2021-07-30 17:32:05 · 1154 阅读 · 0 评论 -
Go Nodejs Java Aes 128 ECB加密解密结果保持一致
在多语言的生产环境下,常常是由一种语言进行加密而由另一种语言来进行解密,因此有必要保持各种语言之间加密解密算法的一致性。下面列出了Go,Nodejs,Java 的 Aes-128-Ecb的加密解密算法:Gopackage mainimport ( "crypto/aes" "crypto/md5" "encoding/hex" "fmt")func generateMd5Key(str string) []byte {原创 2021-07-30 14:37:54 · 1215 阅读 · 0 评论 -
Go语言:go-zookeeper客户端支持在zk集群节点断开时重新连接新节点,但不支持Ephemeral Node (临时节点)过期重建
从线上系统的一次故障日志来看,"github.com/samuel/go-zookeeper/zk"这个客户端在面向zk集群时,如果请求原有zk节点i/o超时后,会自动去尝试连接其它zk节点直到重新建立连接。但是如果用来做服务的注册与发现的话,原来创建的Ephemeral Node (临时节点)过期后无法自动重建,需要由应用程序来自行重建。下面的日志表明客户端在与192.168.6.45:2181的连接i/o超时后,尝试了与192.168.6.106:2181建立连接但session已超时服务端认证失败,原创 2021-06-25 14:23:17 · 994 阅读 · 0 评论 -
Go语言:JSON序列化和带缩进的序列化如何设定HTML特殊字符是否转义
Go的Marshal和MarshalIndent都会进行HTML特殊字符转义如 &转成 \u0026,如果要取消转义的话,可以按如下方式写:func JSONMarshal(t interface{}, escapeHtml bool) ([]byte, error) { buffer := &bytes.Buffer{} encoder := json.NewEncoder(buffer) encoder.SetEscapeHTML(esc原创 2021-06-22 15:01:41 · 690 阅读 · 0 评论 -
Go语言:HTTP响应头字段字母大小写控制
如果使用Header().Set()方法,HTTP响应头字段会自动将首字母和“-”后的第一个字母转换为大写,其余转换为小写,如"accept-encoding" 转换为 "Accept-Encoding"。这个转换规则在绝大多数情况是没有问题的,但是有些字段如“P3P”,按约定应该是全大写的,如果转成“P3p”,可能会引起前端异常。如果想要控制字母的大小写,官方文档提供了一种解决办法就是直接操作Header哈希表(map[string][]string),“To use non-canonical key.原创 2021-04-30 09:45:48 · 3429 阅读 · 0 评论 -
Go语言:自动化测试时Jenkins报错build cache is required, but could not be located: GOCACHE is not defined and ne
Jenkins执行脚本来运行go的命令时,可能会因为读取不到相关的环境变量而报如下错误,build cache is required, but could not be located: GOCACHE is not defined and neither $XDG_CACHE_HOME nor $HOME are defined解决方案:把go env命令打印出来的环境变量写成export语句加到脚本里,如下所示:export GO111MODULE=""export GOARCH=.原创 2021-04-25 13:37:58 · 3978 阅读 · 2 评论 -
thrift协议0.14.1在Nodejs和Go语言之间的跨语言调用的兼容性测试
thrift协议本来按设计理念来说应该是能够跨语言调用的,但实际测试了一下,Nodejs和Go之间并不能通过thrift-0.14.1协议进行跨语言调用,具体用例见《Go语言:thrift协议0.14.1的使用示例》和《Nodejs thrift协议0.14.1的使用示例》。Go的thrift客户端把context.Context引入到RPC函数,而nodejs并没有相应的context,这可能是导致双方不能正常调用的原因。...原创 2021-03-16 16:17:28 · 518 阅读 · 0 评论 -
Go语言:thrift协议0.14.1的使用示例
echo.thrift:namespace go echostruct EchoReq { 1: string msg;}struct EchoRes { 1: string msg;}service Echo { EchoRes echo(1: EchoReq req);}如果是Win10的话直接下载执行exe,其它系统可能需要先安装thrift 0.14.1thrift-0.14.1.exe -r --gen go echo.thrift.原创 2021-03-15 17:37:16 · 1539 阅读 · 1 评论 -
Go语言:字节数转换为人类可读字符串(human readable)
Here’s how to convert1000to"1 kB",1000000to"1 MB"etc.func ByteCountDecimal(b int64) string { const unit = 1000 if b < unit { return fmt.Sprintf("%d B", b) } div, exp := int64(unit), 0 for...转载 2020-12-25 17:01:04 · 709 阅读 · 0 评论 -
Go语言:如何在HTTP Sever服务端端口监听成功时输出一条日志
像在Nodejs语言里端口监听建立成功时会触发一个事件来执行相应的代码,而在Go里面如果直接使用ListenAndServe函数的话是没办法知道端口监听是何时建立成功的。ListenAndServe包含两步操作:1)监听端口 2)accept以阻塞方式等待接受请求;如果1)执行成功,会立即进入阻塞状态,后面的代码在shutdown之前都无法执行,所以如果想在端口监听成功时输出一条日志,则需要单独建立net.Listener再传给Serve函数,具体代码如下:package mainimport原创 2020-11-19 15:01:51 · 2797 阅读 · 0 评论 -
Go语言:http: superfluous response.WriteHeader call from
在同一次请求响应过程中,只能调用一次WriteHeader(code int),否则会有一条日志输出“http: superfluous response.WriteHeader call from”。如下所示:func handler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=utf-8") w.WriteHeader(200) w..原创 2020-11-16 10:40:01 · 10622 阅读 · 0 评论 -
Go语言:编译错误“ is not an expression”
Go语言里,创建map映射表和slice切片的时候都必须用make,否则会报编译错误:“not an expression”,如下例所示:package mainfunc main(){ m := map[string]string s := []string}./expression.go:4:7: type map[string]string is not an expression./expression.go:5:7: type []string.原创 2020-11-09 17:12:16 · 11763 阅读 · 1 评论 -
Go语言:samuel的go-zookeeper客户端监测连接是否已建立
samuel的zk客户端在建立连接时,会返回3个参数,其中第二个参数可用于监测连接的建立状态,仅当state等于StateHasSession时,客户端才是可用的。func Connect(servers []string, sessionTimeout time.Duration, options ...connOption) (*Conn, <-chan Event, error)typeStatetype State int32const ( StateUnkn..原创 2020-11-03 15:26:16 · 736 阅读 · 0 评论 -
Go语言:go-redis客户端对sentinel模式下(非集群cluster)redis-server主从切换的支持
通过调用NewFailoverClient函数可以创建一个能支持redis-server主从切换(sentinel模式下)的client, 基本用法如下:redis主从节点主127.0.0.1:6388 从127.0.0.1:6398假如有3个sentinel实例依次为:127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381;sentinel的配置如下,sentinel monitor mymaster 127.0.0.1 6388 2senti.原创 2020-10-29 16:46:47 · 6325 阅读 · 0 评论 -
Go语言:go-redis客户端之消息的订阅subscribe与发布publish
订阅subscribepackage mainimport ( "fmt" "github.com/go-redis/redis")func main() { client := redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6379", Password: "", DB: .原创 2020-10-23 17:28:27 · 5458 阅读 · 2 评论 -
Go语言:命令行参数解析模块docopt-go的使用方法
docopt-go是docopt标准(Command-line interface description language)的Go语言实现。可打印帮助,版本以及获取各种类型的可选参数。基本用法如下:cmdtool.gopackage mainimport ( "errors" "fmt" "github.com/docopt/docopt-go" "strconv")func ArgvString(argvMap map[原创 2020-10-23 10:52:52 · 573 阅读 · 0 评论 -
Go语言:RESTful API接口在服务端读取POST的JSON数据
如果客户端POST表单数据则服务端可以直接调用Request的ParseForm()函数来获取对应参数和取值,而RESTful API接口POST的是JSON数据,服务端需要获取POST消息体的原始数据,方法如下:server.gopackage mainimport ( "fmt" "io" "io/ioutil" "log" "net/http")func main() { handler原创 2020-10-15 16:50:28 · 1983 阅读 · 0 评论 -
Go语言:生成指定长度随机字符串的包randstr的用法
randstr包用于生成指定长度的随机字符串,综合参考了java apache的org.apache.commons.lang3.RandomStringUtils类和nodejs random-string模块,三者的核心算法都是通过产生随机索引从指定字符集中逐位获取字符。用法示例:/*** @date 2020-09-04* @author pengpengzhou <philip_chow@163.com> */package mainimport (原创 2020-09-04 17:14:27 · 2450 阅读 · 0 评论 -
Go语言:带有缓冲区的字节流读写(bufio.Reader/bufio.Writer)的示例之redis读写
在上一篇《Go语言:字节流读写(io.Reader/io.Writer)的示例之redis读写》的基础上,本篇把缓冲区加上去。bufio包有两个New函数,分别是在任意io.Reader和io.Writer的基础上再包装一层缓冲区得到bufio.Reader和bufio.Writer。func NewReader(rd io.Reader) *Readerfunc NewWriter(w io.Writer) *Writer下面的代码利用bufio来执行两条redis客户端操作,需要注意的是原创 2020-09-03 17:15:41 · 2766 阅读 · 0 评论 -
Go语言:字节流读写(io.Reader/io.Writer)的示例之redis读写
读写字节流的两个基本接口定义如下:type Reader interface { Read(p []byte) (n int, err error)}type Writer interface { Write(p []byte) (n int, err error)}net.Conn这个接口也定义了上述两个函数,因此即是io.Reader接口也是io.Writer接口。下面的代码利用net.Conn来执行两条redis客户端操作:127.0.0.1:6380&g...原创 2020-09-03 16:52:41 · 1882 阅读 · 0 评论 -
Go语言:go-redis客户端遍历扫描scan所有键值key的用法示例
package mainimport ( "fmt" "github.com/go-redis/redis" "strconv")func main() { client := redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6380", Password: "", // no password set.原创 2020-09-02 16:10:12 · 15072 阅读 · 2 评论 -
Go语言:go-redis客户端设置过期时间相关命令Expire,ExpireAt,TTL的用法示例
ExpireAt和Expire类似,只是参数是过期的时间点。TTL查看key还有剩余多少秒才过期。incr,expire这两条命令不是原子操作,如果需要进行事务操作,可以使用Multi,Exec,详见《Go语言采用go-redis模块对Redis进行批量操作(MULTI和EXEC) 的示例及性能》package mainimport ( "fmt" "github.com/go-redis/redis" "time")func main() .原创 2020-09-02 15:20:41 · 17554 阅读 · 0 评论 -
Go语言:go-redis客户端计数相关命令Incr,IncrBy,Decr,DecrBy的用法示例
package mainimport ( "fmt" "github.com/go-redis/redis")func main() { client := redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6380", Password: "", DB: 0, .原创 2020-09-02 14:32:47 · 2660 阅读 · 0 评论 -
Go语言:go-redis客户端读写队列的相关命令LPush,RPush,LRange,LPop,RPop的用法示例
redis的值的数据结构可以是队列,并且可以操作头部或者尾部,用法如下:package mainimport ( "fmt" "github.com/go-redis/redis")func main() { client := redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6380", Password: "".原创 2020-09-02 14:12:39 · 3787 阅读 · 0 评论 -
Go语言:go-redis客户端读写哈希表(hash)的相关命令hset hget hgetall hdel的用法示例
package mainimport ( "fmt" "github.com/go-redis/redis")func main() { client := redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6380", Password: "", DB: 0, .原创 2020-09-02 10:40:37 · 4953 阅读 · 0 评论 -
Go语言:go-redis客户端set集合相关的命令sadd和smembers的用法示例
package mainimport ( "fmt" "github.com/go-redis/redis")func main() { client := redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6380", Password: "", DB: 0, .原创 2020-09-02 10:11:06 · 2349 阅读 · 0 评论 -
Go语言:运行报错cannot load ... malformed module path “...“: missing dot in first path element解决办法
报错机制:报这个错是因为,在$GOROOT和$GOPATH下都没有找到对应的包,于是就把这个path当成一个网络地址去下载,在下载前先CheckPath检查其合法性,其中一项检查就是域名,如“github.com/pochard/logrotator”,如果按“/”分隔后第一个元素里没有"."存在那就不是一个合法的域名,所以就报“missing dot in first path element”。报错场景:通常是在引用用户自己创建的本地包时,由于没有把文件放在包名所对应的文件夹下,导致找不到对原创 2020-09-01 14:32:06 · 37223 阅读 · 2 评论 -
Go语言: go-redis客户端通过MSet方法一次性批量写入多个key的值
redis客户端一次性批量写入multiple keys对应的值可以减少网络操作。代码如下:package mainimport ( "fmt" "github.com/go-redis/redis")func main() { client := redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6380", Pas原创 2020-08-31 11:26:33 · 4278 阅读 · 1 评论 -
Go语言: go-redis客户端通过MGet方法一次性批量读取多个key的值
package mainimport ( "fmt" "github.com/go-redis/redis")func main() { client := redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6380", Password: "", DB: 0, .原创 2020-08-31 11:14:37 · 6951 阅读 · 0 评论 -
Go语言:结构体匿名组合编译报错“ambiguous selector”
Go没有类似Java那样的继承,只能通过结构体的匿名组合来实现继承的特性。这个过程是在编译过程完成的,例如下例,假如没有T2的话,那么编译器会给MyStruct创建一个m1方法,然后在方法里调用T1.m1()。func (m *MyStruct) m1(){ m.T1.m1()}但是如果MyStruct又匿名组合了T2,而T2也有m1()方法,则编译器就不知道在给MyStruct创建m1方法时应该选择T1还是T2的m1(),于是就报错“ambiguous selector”。除了方法..原创 2020-08-27 16:41:28 · 1679 阅读 · 0 评论 -
Go面试:哪些类型的变量可以用“==”比较
两个变量如果要用“==”来比较,需要满足如下条件:必须是同类型,如果是两个接口则其中一个接口必须定义了另一个接口的全部方法 不能是func, map, slice 如果是两个struct的实例,则所有字段都必须可比较 如果是数组,则元素必须可比较。验证代码example.gopackage mainimport "fmt"type A interface {}type B interface {}type C interface { run()}type.原创 2020-08-26 16:56:09 · 757 阅读 · 0 评论 -
Go语言:编译报错mixture of field:value and value initializers
Go创建结构体实例的时候要么全有字段名,要么全省略字段名,不能一些有一些没有,否则编译报错。package mainimport "fmt"type Person struct{ age int name string}func main() { sn1 := Person{age: 11,name: "qq"} sn2 := Person{12, "qq2"} sn3 := Person{age:13, "qq3"} //错误.原创 2020-08-26 15:24:35 · 1890 阅读 · 0 评论 -
Go面试:new能不能做变量名
下面的代码能不能编译通过,如果能,输出什么?package mainfunc add(old, new int) int{ return old + new}func main() { println(add(1,2))}我们都知道new是Go的内置函数用于创建指针,但编译器并没有强行限制不能用new做变量名。运行上面的代码可以得到输出:3事实上在Go的源代码中大量使用new来做变量名,例如:./strings/strings.go:9原创 2020-08-19 17:18:11 · 503 阅读 · 0 评论 -
Go面试:命名返回值是defer延迟函数在surrounding函数返回前修改返回值的唯一途径
package mainfunc main() { println(func1()) println(func2()) println(func3())}func func1() (t int) { defer func() { t = 3 }() return t}func func2() int { t := 0 defer fu.原创 2020-08-19 15:52:05 · 290 阅读 · 0 评论 -
Go面试:Go通过匿名组合实现的继承和Java的继承之间的差别
Go没有直接的继承关键字,只能用结构体的匿名组合来实现继承,在实现机制和效果上和Java的继承是有差异的,虽然两者都是在编译期实现的。示例Go代码:type People struct {}func (p *People) ShowA() { fmt.Println("showA") p.ShowB()}func (p *People) ShowB() { fmt.Println("showB")}type Teacher struc.原创 2020-08-17 10:57:15 · 526 阅读 · 0 评论 -
Go面试:当runtime.GOMAXPROCS(1)时多个协程的执行顺序是固定的,没有随机性。参考答案有误
网上有一道关于多个协程的执行顺序的题目。下面的代码会输出什么,并说明原因func main() { runtime.GOMAXPROCS(1) wg := sync.WaitGroup{} wg.Add(20) for i := 0; i < 10; i++ { go func() { fmt.Println("A: ", i) .原创 2020-08-14 17:39:58 · 1869 阅读 · 0 评论