• 主页
  • Go
  • ChatOps
  • 归档
  • 关于
所有文章

  • 主页
  • Go
  • ChatOps
  • 归档
  • 关于

【Go】go get 自动代理

2019-03-21

最近发现技术交流群里很多人在询问 go get 墙外包失败的问题,大家给了很多解决方案:

  • 从 Github 的代码库 clone
  • 设置 GOPROXY 环境变量配置代理, 例如:GOPROXY=https://goproxy.io
  • 配置命令行代理,https_proxy 环境变量
  • 使用 go mod replace
  • 使用 Gopm 类似的工具
  • ……

Go 的社区很活跃,国内 gopher 对 Go 的热情不会因为墙的存在而减少,从社区想到这么多翻墙方案就能看出来了。

上面的方法都是可行的,但是总有一些不尽人意,社区也一直在找更好的方法,我一直使用自动代理的方式获取墙外的包,可以支持所有 Go 原生拉取包操作,比如 go get、go mod、dep、godep、glide 等各种方法,只需要配置一次,只要在任何原生命令前加前缀运行命令即可,效率很高。

more >>
  • go
  • proxy
  • git
  • shell
  • go

展开全文 >>

【Go】那么多数值类型,应该选哪个?

2019-03-19

Go 内置很多种数值类型,往往初学者不知道编写程序如何选择,使用哪种数值类型更有优势。

内置的数值类型有:uint8、 uint16、 uint32、 uint64、 uint、 int8、 int16、 int32、 int64、 int。

从类型名称上可以很好了解到类型的大小,这个非常直观,uint 和 int 这两种类型是不带大小的,那么它们的大小会根据编译参数 GOARCH=amd64 平台决定的。

我最早设计的一个go的项目,当时设计系统使用采用最小类型原则,几乎使用了大多数数值类型,很少使用 uint 和 int 类型,后来遇到很多问题,标准库和三方库函数都接收 int、 uint、 int64、uint64, 一些代码生成工具, 比如 protobuf 生成类型是 int32,一些三方系统大多数也是 int 类型,这时候与其它组件件的交互就需要 类型转换, 类型转换成本是很高的,导致程序性能并没有预期的好。

more >>
  • go
  • int
  • numerical
  • uintptr
  • go

展开全文 >>

【Go】string 优化误区及建议

2019-02-23

本文原标题为 《string 也是引用类型》,经过 郝林 大佬指点原标题存在诱导性,这里解释一下 “引用类型” 有两个特征:1、多个变量引用一块内存数据,不创建变量的副本,2、修改任意变量的数据,其它变量可见。显然字符串只满足了 “引用类型” 的第一个特点,不能满足第二个特点,顾不能说字符串是引用类型,感谢大佬指正。

初学 Go 语言的朋友总会在传 []byte 和 string 之间有着很多纠结,实际上是没有了解 string 与 slice 的本质,而且读了一些程序源码,也发现很多与之相关的问题,下面类似的代码估计很多初学者都写过,也充分说明了作者当时内心的纠结:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main

import "bytes"

func xx(s []byte) []byte{
....

return s
}

func main(){
s := "xxx"

s = string(xx([]byte(s)))

s = string(bytes.Replace([]byte(s), []byte("x"), []byte(""), -1))
}

虽然这样的代码并不是来自真实的项目,但是确实有人这样设计,单从设计上看就很糟糕了,这样设计的原因很多人说:“slice 是引用类型,传递引用类型效率高呀”,主要原因不了解两者的本质。

上面这个例子如果觉得有点基础和可爱,下面这个例子貌似并不那么容易说明其存在的问题了吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

func xx(s *string) *string{
....
return s
}

func main(){
s := "xx"

s = *xx(&s)

ss :=[]*string{}

ss = append(ss, &s)
}

指针效率高,我就用指针多好,可以减少内存分配呀,设计函数都接收指针变量,程序性能会有很大提升,在实际的项目中这种例子也不少见,我想通过这篇文档来帮助初学者走出误区,减少适得其反的优化技巧。

more >>
  • bytes
  • go
  • unsafe
  • string
  • go

展开全文 >>

【Go】strings.Replace 与 bytes.Replace 调优

2019-02-02

标准库中函数大多数情况下更通用,性能并非最好的,还是不能过于迷信标准库,最近又有了新发现,strings.Replace 这个函数自身的效率已经很好了,但是在特定情况下效率并不是最好的,分享一下我如何优化的吧。

我的服务中有部分代码使用 strings.Replace 把一个固定的字符串删除或者替换成另一个字符串,它们有几个特点:

  • 旧的字符串大于或等于新字符串 (len(old) >= len(new)
  • 源字符串的生命周期很短,替换后就不再使用替换前的字符串
  • 它们都比较大,往往超过 2k~4k

本博文中使用函数均在 go-extend 中,优化后的函数在 exbytes.Replace 中。

more >>
  • bytes
  • go
  • strings
  • replace
  • unsafe
  • go

展开全文 >>

【Go】优雅的读取http请求或响应的数据-续

2019-02-01

之前发布 【Go】优雅的读取http请求或响应的数据 文章,网友 “wxe” 咨询:“优化前后的请求耗时变化有多大”,之前只分析了内存分配,这篇文章用单元测试的方式分析优化前后的耗时情况,本文源码。

非常感谢 “wxe” 网友的提问,让我在测试过程中发现一个 json 序列化的问题。

more >>
  • net.http
  • http
  • pool
  • bytes
  • buffer
  • makeSlice
  • ioutil
  • go

展开全文 >>

【Go】优雅的读取http请求或响应的数据

2019-01-26

从 http.Request.Body 或 http.Response.Body 中读取数据方法或许很多,标准库中大多数使用 ioutil.ReadAll 方法一次读取所有数据,如果是 json 格式的数据还可以使用 json.NewDecoder 从 io.Reader 创建一个解析器,假使使用 pprof 来分析程序总是会发现 bytes.makeSlice 分配了大量内存,且总是排行第一,今天就这个问题来说一下如何高效优雅的读取 http 中的数据。

more >>
  • net.http
  • http
  • pool
  • bytes
  • buffer
  • makeSlice
  • ioutil
  • go

展开全文 >>

【Go】slice的一些使用技巧

2019-01-23

slice 是 Go 语言十分重要的数据类型,它承载着很多使命,从语言层面来看是 Go 语言的内置数据类型,从数据结构来看是动态长度的顺序链表,由于 Go 不能直接操作内存(通过系统调用可以实现,但是语言本身并不支持),往往 slice 也可以用来帮助开发者申请大块内存实现缓冲、缓存等功能。

在 Go 语言项目中大量的使用 slice, 我总结三年来对 slice 的一些操作技巧,以方便可以高效的使用 slice, 并使用 slice 解决一些棘手的问题。

slice 的基本操作

先熟悉一些 slice 的基本的操作, 对最常规的 : 操作就可玩出很多花样。

  • s=ss[:] 引用一个切片或数组
  • s=s[:0] 清空切片
  • s=s[:10] s=s[10:] s=s[10:20] 截取接片
  • s=ss[0:10:20] 从切片或数组引用指定长度和容量的切片

下标索引操作的一些误区 s[i:l:c] i 是起始偏移的起始位置,l 是起始偏移的长度结束位置, l-i 就是新 slice 的长度, c 是起始偏移的容量结束位置,c-i 就是新 slice 的容量。其中 i 、l 、c 并不是当前 slice 的索引,而是引用底层数组相对当前 slice 起始位置的偏移量,所以是可超出当前 slice 的长度的, 但不能超出当前 slice 的容量,如下操作是合法的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import (
"fmt"
)

func main() {
s := make([]int, 100)
s[20] = 100
s1 := s[10:10]
s2 := s1[10:20]
fmt.Println(s1)
fmt.Println(s2)
}

其中 s1 是 [];s2 是 [100 0 0 0 0 0 0 0 0 0], 这里并不会发生下标越界的情况,一个更好的例子在 csv reader 中的一个例子

more >>
  • go
  • slice
  • 缓存
  • 内存池
  • go

展开全文 >>

【Go】深入剖析slice和array

2019-01-12

array 和 slice 看似相似,却有着极大的不同,但他们之间还有着千次万缕的联系 slice 是引用类型、是 array 的引用,相当于动态数组,
这些都是 slice 的特性,但是 slice 底层如何表现,内存中是如何分配的,特别是在程序中大量使用 slice 的情况下,怎样可以高效使用 slice?
今天借助 Go 的 unsafe 包来探索 array 和 slice 的各种奥妙。

more >>
  • unsafe
  • slice
  • array
  • go

展开全文 >>

【go】一次读锁重入导致的死锁故障

2018-12-25

在两天前第一次遇到自己的程序出现死锁, 我一直非常的小心使用锁,了解死锁导致的各种可能性,
这次的经历让我未来会更加小心,下面来回顾一下死锁发生的过程与代码演进的过程吧。

简述业务背景及代码演进过程

我的程序中有一块缓存,数据会组织好放到内存中,会根据数据源(MySQL)更新而刷新缓存,是读多写少的应用场景。
内存中有一个很大数据列表,缓存模块会按数据维度进行分组,每次访问根据维度查找到这个列表里面的所有数据。
业务模块拿到数据后会根据业务需要再做一次筛选,选出N个符合条件的数据(具体多少个由业务模块的规则决定)。

more >>
  • 读写锁
  • 死锁
  • go

展开全文 >>

« Prev12
© 2021 戚银 京ICP备17038866号-1
Hexo Theme Yilia by Litten
  • 所有文章

tag:

  • chatops
  • devops
  • hubot
  • github
  • gitlab
  • slack
  • rocket.chat
  • linux
  • centos
  • VirtualBox
  • 读写锁
  • 死锁
  • net.http
  • http
  • pool
  • bytes
  • buffer
  • makeSlice
  • ioutil
  • go
  • strings
  • replace
  • unsafe
  • string
  • int
  • numerical
  • uintptr
  • proxy
  • git
  • shell
  • ip
  • net
  • ip2long
  • ip2number
  • client
  • RemoteAddr
  • compress
  • io
  • 压缩
  • substring
  • substr
  • utf8
  • 中文字符串截取
  • sync
  • once
  • OncePointer
  • BufferPool
  • strings.Replacer
  • closeOnce
  • slice
  • array
  • 缓存
  • 内存池
  • 日志
  • csv
  • join
  • round
  • half up
  • exmath
  • math