关于go:Go语言学习笔记06字符与字符串

Go语言学习笔记-06字符与字符串字符Go中的字符是一个Unicode字符,应用UTF-8编码格局,一个字符由一个或多个字节存储在内存中,字符的默认类型为int32 应用rune类型示意一个Unicode码点,一个码点对应一个字符。rune类型实质是int32类型 // $GOROOT/src/builtin.gotype rune = int32应用byte类型示意一个字节以内的字符,byte类型实质是int8类型 // $GOROOT/src/builtin.gotype byte = uint8字面值应用'','a','闲' 应用\x,接十六进制数,最多示意FF,'\x61', 应用\,接八进制数,最多示意377,'\141' 应用\u前缀接四个十六进制数,'\u95f2' 应用\U前缀接四个或八个十六进制数,'\u000095f2','\U000095f2' ch06/main.go package mainimport "fmt"func main() { // 实质上是int32类型 var ch1 rune ch1 = '闲' // 应用%c格式化输入字符 fmt.Printf("闲的Unicode码点值:%d,字符:%c\n", ch1, ch1) ch2 := '渔' fmt.Printf("渔的Unicode码点值:%d,字符:%c\n", ch2, ch2) // 应用八进制数示意字符a ch3 := '\141' // 应用十六进制数示意字符a ch4 := '\x61' fmt.Printf("八进制141示意的字符为:%c\n", ch3) fmt.Printf("十六进制61示意的字符为:%c\n", ch4) // 应用\u接四个十六进制数示意 ch5 := '\u95f2' fmt.Printf("\\u95f2示意的字符为:%c\n", ch5) // 应用\U接四个或八个十六进制数示意 ch6 := '\U000095f2' fmt.Printf("\\u95f2示意的字符为:%c\n", ch6) // 应用byte示意单字节字符 var ch7 byte ch7 = 97 fmt.Printf("97对应的ascii为%c\n", ch7) // 应用rune示意一个Unicode码点 var ch8 rune ch8 = 38386 fmt.Printf("38386对应的Unicode字符为%c", ch8)}输入 ...

February 8, 2023 · 2 min · jiezi

关于go:Golang-类型转换库-cast

0 前言你是否在应用 Go 的过程中因为类型转换的繁琐而苦恼过? 你是否感觉 Go 语言中的类型断言可能会 panic 而对本人写的代码有那么一点点不释怀? 如果你有过如上体验,并且想要找到一个适合的解决方案的话,那么本文举荐的一个用于类型转换的第三方库 cast 相对是一个值得尝试的抉择。 1 castcast 是一个极为简洁的第三方库,github 地址:https://github.com/spf13/cast。 我的项目主页里的头两句介绍就是: Easy and safe casting from one type to another in GoDon’t Panic! ... Cast可见,cast 的次要性能就是类型转换,且没有 panic。 多说一句,Don't panic 在英语中自身就是一个常用语,示意不要慌乱、不要胆怯,所以,在这里其实是一个有意思的双关。 2 上手2.1 装置引入这里只讲 go mod 的引入形式。 在 go.mod 文件中 require github.com/spf13/cast v1.5.0(目前最新版为 1.5.0),接着用 mod 进行 download、tidy 等操作,再在代码中 import "github.com/spf13/cast" 即可应用 cast 关键字应用 cast 的性能了。 2.2 应用2.2.1 惯例用法咱们间接通过几个简略的例子来体验一下 cast: var target interface{} = "123"str := "hello, world!"fmt.Println(cast.ToString(target))fmt.Println(cast.ToInt(target))fmt.Println(cast.ToInt(str))// 输入:1231230咱们创立了一个 interface{} 类型的变量 target,传统形式下如果要将一个 interface{} 转化为 string,须要应用类型断言: ...

February 7, 2023 · 2 min · jiezi

关于go:用go造一个飞书机器人应用帮小学生算数学题数量取胜的go语言学习法

A feishu-bot calculator powered by go(gin) 源代码 A feishu-bot calculator powered by go bilibili 在线吹水⚽️⚽️飞书上的小计算器: Go机器人来啦、⚽️⚽️ 对于反向代理因为须要订阅事件,所以须要在公网上部署, 如果你的服务器没有公网 IP,能够应用反向代理的形式 飞书的服务器在国内对ngrok的访问速度很慢,所以举荐应用一些国内的反向代理服务商 cpolarnatapp 测试部署cpolar http 8080后盾部署go run main.gonohup cpolar http 8080 -log=stdout &查看服务器状态https://dashboard.cpolar.com/... 查问并kill过程ps -ef | grep cpolarkill -9 PID 对于飞书机器人飞书开发者平台 事件订阅的文档 事件订阅的SDK 所有SDK 音讯类型 发送音讯文档 利用审核: https://fork-way.feishu.cn/ad... (须要飞书企业版)

February 6, 2023 · 1 min · jiezi

关于go:20230120-周报

Go 工程化 - JSON 应用技巧 Go 工程化 - 构造体应用技巧 (补充) Go 工程化 - 切片应用技巧 Go 工程化 - 含糊测试 (实践篇) Go 工程化 - 含糊测试 (实际篇) Go 工程化 - 压力测试 (一) Go 高性能 - 字符串 & 切片转换晋升 10 倍+

February 3, 2023 · 1 min · jiezi

关于go:Go框架一文读懂主流web框架中路由的实现原理

大家好,我是渔夫子。本号新推出「Go工具箱」系列,意在给大家分享应用go语言编写的、实用的、好玩的工具。同时理解其底层的实现原理,以便更深刻地理解Go语言。 在理论工作中,大家肯定会用到go的web框架。那么,你晓得各框架是如何解决http申请的吗?明天就支流的web框架gin、beego框架以及go规范库net/http来总结一下http申请的流程。 一、规范库 net/http 的申请流程首先,咱们来看下http包是如何解决申请的。通过以下代码咱们就能启动一个http服务,并解决申请: import ( "net/http")func main() { // 指定路由 http.Handle("/", &HomeHandler{}) // 启动http服务 http.ListenAndServe(":8000", nil)}type HomeHandler struct {}// 实现ServeHTTPfunc (h *HomeHandler) ServeHTTP(response http.ResponseWriter, request *http.Request) { response.Write([]byte("Hello World"))}当咱们输出http://localhost:8000/的时候,就会执行到HomeHandler的ServeHTTP办法,并返回Hello World。 那这里为什么要给HomeHandler定义ServeHTTP办法,或者说为什么会执行到ServeHTTP办法中呢? 咱们顺着http.ListenAndServe办法的定义: func ListenAndServe(addr string, handler Handler) error发现第二个参数是个Handler类型,而Handler是一个定义了ServeHTTP办法的接口类型: type Handler interface { ServeHTTP(ResponseWriter, *Request)}仿佛有了一点点关联,HomeHandler类型也实现了ServeHTTP办法。但咱们在main函数中调用http.ListenAndServe(":8000", nil)的时候第二个参数传递的是nil,那HomeHandler里的ServeHTTP办法又是如何被找到的呢? 咱们接着再顺着源码一层一层的找上来能够发现,在/src/net/http/server.go的第1930行有这么一段代码: serverHandler{c.server}.ServeHTTP(w, w.req)有个serverHandler构造体,包装了c.server。这里的c是建设的http连贯,而c.server就是在http.ListenAndServe(":8000", nil)函数中创立的server对象: func ListenAndServe(addr string, handler Handler) error { server := &Server{Addr: addr, Handler: handler} return server.ListenAndServe()}server中的Handler就是http.ListenAndServe(":8000", nil)传递进来的nil。 好,咱们进入 serverHandler{c.server}.ServeHTTP(w, w.req)函数中再次查看,就能够发现如下代码: ...

February 1, 2023 · 3 min · jiezi

关于go:Go学习二程序组成结构及规范说明

1. 程序示例以理论代码进行解说: package main// 这是引入包 import "fmt"// 入口函数func main() { // 定义变量 str := "hello word" // 输入语句 fmt.Println(str)}2. 程序组成2.1 包名: package mainpackage定义包名,必须在源文件中非正文的第一行指明这个文件属于哪个包。<font color=red>每个 Go 应用程序都蕴含一个名为 main 的包,并且该包蕴含一个叫main()的函数(该函数是Go程序执行的终点,既不能带参数,也不能定义返回值)。</font> 注意事项: 只有package名称为main的包能够蕴含main()函数。一个可执行程序有且仅有一个main包。2.2 导入包: import "fmt"import语句用于导入该程序所依赖的包。因为本示例程序用到了Println()函数,所以须要导入该函数所属的fmt包。fmt包实现了格式化IO(输出/输入)。 注意事项: 通过import关键字来导入其余非main包。能够通过import关键字单个导入,也能够同时导入多个。2.3 主函数: func main()func main()是程序入口。所有Go函数以关键字func结尾,每一个可执行程序都必须蕴含main()函数,通常是程序启动后第一个执行的函数,<font color=red>如果有init()函数则会先执行init()函数。</font> 2.4 正文正文就是对代码的性能进行解释,不便开发人员了解被正文的代码。Go 语言中有以下两种模式。 单行正文: // 。多行正文: /**/,不能够嵌套应用。2.5 语句完结Go语言中<font color=red>一行代表一个语句完结。</font>每个语句不须要像C 家族中的其它语言一样以分号分号; 结尾。 如果打算将多个语句写在同一行,它们则必须应用分号;人为辨别;<font color=red>但在理论开发中并不激励这种做法。</font> 3. 可见性规定Go语言中,应用大小写来决定标识符(常量、变量、类型、接口、构造或函数)是否能够被内部包所调用。 如果标识符<font color=red>以大写字母结尾</font>,那么其对象就能够被内部包的代码所应用(应用时程序须要先导入这个包),如同面向对象语言中的public。如果标识符<font color=red>以小写字母结尾</font>,则对包外是不可见的,然而它们在整个包的外部是可见并且可用的,如同面向对象语言中的private。4.我的项目工程构造GoItem (GOPATH)├── bin (GOBIN)├── pkg└── src ├── app │   ├── controller │   │   └── String.go │   ├── main.go │   ├── model │   ├── service │   └── test └── app2 ├── controller │   └── String.go ├── main.go ├── model ├── service └── test<font color=red>微信搜寻关注【猿码记】查看更多文章。</font> ...

February 1, 2023 · 1 min · jiezi

关于go:godongle-027-版本发布一个轻量级语义化的-golang-编码解码加密解密库

dongle 是一个轻量级、语义化、对开发者敌对的 Golang 编码解码和加密解密库 Dongle 已被 awesome-go 收录, 如果您感觉不错,请给个 star 吧 github.com/golang-module/dongle gitee.com/golang-module/dongle 更新日志 新增 dongle.openssl.RSA.GenPKCS1KeyPair() 办法,生成 PKCS#1 格局 RSA 密钥对新增 dongle.openssl.RSA.GenPKCS8KeyPair() 办法,生成 PKCS#8 格局 RSA 密钥对新增 dongle.openssl.RSA.VerifyKeyPair() 办法,验证 RSA 密钥对是否匹配新增 dongle.openssl.RSA.IsPublicKey() 办法,判断是否是 RSA 公钥新增 dongle.openssl.RSA.IsPrivateKey() 办法,判断是否是 RSA 私钥新增 dongle.openssl.RSA.ParsePublicKey() 办法,解析 RSA 公钥新增 dongle.openssl.RSA.ParsePrivateKey() 办法,解析 RSA 私钥新增 dongle.openssl.RSA.ExportPublicKey() 办法,从 RSA 私钥里导出公钥性能清单 [x] Hex 编码、解码[x] Base16 编码、解码[x] Base32 编码、解码[x] Base45 编码、解码[x] Base58 编码、解码[x] Base62 编码、解码[x] Base64 编码、解码[x] Base64URL 编码、解码[x] SafeURL 编码、解码[x] Base85 编码、解码[x] Base91 编码、解码[x] Base100 编码、解码[x] Morse(摩斯) 编码、解码[x] Md2 加密[x] Md4 加密[x] Md5 加密[x] Sha1 加密[x] Sha3-224 加密[x] Sha3-256 加密[x] Sha3-384 加密[x] Sha3-512 加密[x] Sha224 加密[x] Sha256 加密[x] Sha384 加密[x] Sha512 加密[x] Sha512-224 加密[x] Sha512-256 加密[x] Shake128 加密[x] Shake256 加密[x] Ripemd160 加密[x] Blake2b-256 加密[x] Blake2b-384 加密[x] Blake2b-512 加密[x] Blake2s-256 加密[x] Hmac-md2 加密[x] Hmac-md4 加密[x] Hmac-md5 加密[x] Hmac-sha1 加密[x] Hmac-sha3-224 加密[x] Hmac-sha3-256 加密[x] Hmac-sha3-384 加密[x] Hmac-sha3-512 加密[x] Hmac-sha224 加密[x] Hmac-sha256 加密[x] Hmac-sha384 加密[x] Hmac-sha512 加密[x] Hmac-sha512-224 加密[x] Hmac-sha512-256 加密[x] Hmac-ripemd160 加密[x] Hmac-sm3 加密[ ] Rc2 加密、解密[x] Rc4 加密、解密[ ] Rc5 加密、解密[ ] Rc6 加密、解密[x] Tea 加密、解密[ ] Xtea 加密、解密[x] Aes 加密、解密[x] Blowfish 加密、解密[x] Des 加密、解密[x] 3Des 加密、解密[x] Rsa 加密、解密[ ] Ecc 加密、解密[ ] Sm2 加密、解密[x] Sm3 加密[ ] Sm4 加密、解密[ ] Sm7 加密、解密[ ] Sm9 加密、解密[x] Bcrypt 签名、验签[x] Ed25519 签名、验签[x] Rsa 签名、验签[ ] Dsa 签名、验签

February 1, 2023 · 1 min · jiezi

关于go:Go语言中实现HmacSHA256加密算法

HmacSHA256加密算法比拟罕用的加密算法之一,它比MD5更加平安。HmacSHA256也是微信领取举荐的加密形式。 在Go语言中实现HmacSHA256还是比较简单的,尽管没有PHP的hash_hmac一个函数搞定的形式简略,但比起Java中的实现还是简略不少。 package mainimport ( "crypto/hmac" "crypto/sha256" "encoding/base64" "encoding/hex" "fmt")// HmacSha256 计算HmacSha256// key 是加密所应用的key// data 是加密的内容func HmacSha256(key string, data string) []byte { mac := hmac.New(sha256.New, []byte(key)) _, _ = mac.Write([]byte(data)) return mac.Sum(nil)}// HmacSha256ToHex 将加密后的二进制转16进制字符串func HmacSha256ToHex(key string, data string) string { return hex.EncodeToString(HmacSha256(key, data))}// HmacSha256ToHex 将加密后的二进制转Base64字符串func HmacSha256ToBase64(key string, data string) string { return base64.URLEncoding.EncodeToString(HmacSha256(key, data))}func main() { // secret 是加密要应用的key // apple 是要加密的内容 fmt.Printf("HmacSha256转16字符串: %s\n", HmacSha256ToHex("secret", "apple")) fmt.Printf("HmacSha256转base字符串: %s\n", HmacSha256ToBase64("secret", "apple"))}运行后果: ...

February 1, 2023 · 1 min · jiezi

关于go:Go语言学习笔记01开发环境搭建

Go语言学习笔记-01开发环境搭建下载地址https://go.dev/dl/ windows平台1.依据零碎位数下载对应安装包,64位下载amd64.msi结尾的文件,32位下载386.msi结尾的文件 2.双击关上安装包,一路Next,期待装置完结 3.关上终端,输出go version,若装置胜利,会有以下输入 4.设置GOPROXY环境变量,减速go库的下载在终端输出 go env -w https://mirrors.aliyun.com/goproxy/,https://goproxy.cn,https://goproxy.io,direct查看设置后果 go env 编辑环境搭建Goland1.下载地址https://www.jetbrains.com.cn/...抉择2022.1.4版本,默认收费30天试用依据零碎抉择对应安装包 2.装置完后关上,注册一个账号3.关上编辑器 3.点击New Project,抉择Go(GOPATH),创立一个我的项目 4.装置主题插件 点击左上角File->Settings,找到Plugins 搜寻Atom Material Icons,点击Install 搜寻One Dark theme,点击Install 设置主题,字体,字体大小 5.hello world 右键gotrip新建目录ch01,并在ch01下创立main.go文件 输出以下代码 package mainimport "fmt"func main() { fmt.Print("hello world,咸鱼一下")}点击运行 运行后果 第二种运行办法 在终端输出 go run ch01/main.go 第三种运行办法 在终端输出 go build ch01/main.go此时会编译出一个执行文件main.exe 在终端输出 ./main.exe 笔记地址gitee:https://gitee.com/xianyuyixia... github:https://github.com/xianyuyixi... 交流学习微信号:xianyuyixia 微信公众号:闲渔一下

February 1, 2023 · 1 min · jiezi

关于go:Go字符串操作不是你想的那么简单

重要性字符串解决基本功,无论面试算法还是工作都常常应用到。以下咱们以一个算法+一个理论工作场景的模式来论述字符串解决。 以下算法都来自leecode中国反转字符串先来做下原题 344题反转字符串 原题目要求不容许额定空间原地反转。 输出:s = ["h","e","l","l","o"]输入:["o","l","l","e","h"]间接一个循环反转了。 func reverseString(s []byte) { //双指针,一个放头一个放尾 i:=0 j:=len(s)-1 //反转这两个地位的元素 for i<j { s[i],s[j]=s[j],s[i] i++ j-- } }如果是python间接一个revert就进去了,Go得本人写的确麻烦。 拆分与合并字符串题目间接传入就是字节数组,内部怎么解决呢?就是字符串和byte的来回转换。 s := []byte(str)reverseString(s)fmt.Println(string(s))这样会把字符串变成一个个字节,设想一个场景你的文章有多个标签,全副塞到一个字段里。要拆分显示怎么操作? # 拆分strList := strings.Split("Go语言,channel,并发", ",")fmt.Println(strList)# 合并str := strings.Join(strList,",")fmt.Println(str)strings 是一个包,封装了很多字符串解决的函数。strings.Split 拆分,参数一是字符串,参数二是宰割符strings.Join 合并,参数一是字符串数组,参数二是合并用的宰割符疏忽大小写判等一个验证码的场景,例如验证码是2s5G 用户输出2s5g实际上也是对的。 全副转大写,或者全副转小写判等就行。我写毛糙一点,看不懂留言啊。 strings.ToLower("2s5G") == "2s5g"strings.ToUpper("2s5G") == "2S5G"当然strings间接就提供了不辨别大小写判断是否相等的方法。 fmt.Println(strings.EqualFold("abc", "ABC"))蛇行命名转驼峰命名形式波及知识点:拆分、大小写转换、组合 func main() { name := "ab_cde_as" strList := strings.Split(name,"_") for index,str := range strList{ strList[index] = strings.ToUpper(string(str[0])) + str[1:] } name = strings.Join(strList,"") fmt.Println(name)}输入 AbCdeAs。str[0] 取其中一个字符,str[1:]切片取字符串,失去[1,len(str)]地位闭区间的字符串。以后能够间接用strings.Title("hello")来失去Hello。 ...

February 1, 2023 · 1 min · jiezi

关于go:Go学习一Mac环境下安装配置

1.装置下载地址(https://golang.org/dl/) 下载之后,双击装置; 2.验证2.1 查看版本# 查看版本➜ ~ go versiongo version go1.15.5 darwin/amd642.2 查看Go变量# 查看环境变量➜ ~ go envGO111MODULE=""GOARCH="amd64"GOBIN=""GOCACHE="/Users/hui/Library/Caches/go-build"GOENV="/Users/hui/Library/Application Support/go/env"GOEXE=""GOFLAGS=""GOHOSTARCH="amd64"GOHOSTOS="darwin"GOINSECURE=""GOMODCACHE="/Users/hui/go/pkg/mod"GONOPROXY=""GONOSUMDB=""GOOS="darwin"GOPATH="/Users/hui/go"GOPRIVATE=""GOPROXY="https://proxy.golang.org,direct"GOROOT="/usr/local/go"GOSUMDB="sum.golang.org"GOTMPDIR=""GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"GCCGO="gccgo"AR="ar"CC="clang"CXX="clang++"CGO_ENABLED="1"GOMOD=""CGO_CFLAGS="-g -O2"CGO_CPPFLAGS=""CGO_CXXFLAGS="-g -O2"CGO_FFLAGS="-g -O2"CGO_LDFLAGS="-g -O2"PKG_CONFIG="pkg-config"GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/8f/vnx2y1h57nzbd2p4vtcl6hv80000gn/T/go-build487191191=/tmp/go-build -gno-record-gcc-switches -fno-common"2.3 查看环境变量PATH➜ Go echo $PATH/usr/local/opt/ncurses/bin:/usr/local/opt/icu4c/sbin:/usr/local/opt/icu4c/bin:/Users/hui/.nvm/versions/node/v12.3.1/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/Users/hui/DevEnvSpace/maven-3.6.3/bin# 能够看出/usr/local/go/bin 曾经存在3.环境变量介绍3.1 GOROOTgolang 的装置门路,MAC环境下装置后,默认在(/usr/local/go) 3.2 GOPATH能够了解为工作目录,该目录下约定有三个子目录,别离为:src、pkg、bin; src: 寄存源代码(比方:.go .c .h .s等) 依照golang默认约定,go run,go install等命令的当前工作门路(即在此门路下执行上述命令)。pkg: 寄存编译时生成的两头文件(比方:.a)bin: 寄存编译后生成的可执行文件(为了不便,能够把此目录退出到 $PATH 变量中,如果有多个GOPATH,那么应用${GOPATH//://bin:}/bin增加所有的bin目录) 3.3 GOBIN当咱们应用go install命令编译和打包应用程序时,该命令会将编译后二进制程序文件 寄存到GOBIN目录下,个别咱们将GOBIN设置为$GOPATH/bin目录。 4.批改配置4.1 配置GOPATH、GOBINGo装置后默认GOPATH为: $HOME/go(这里是cd /Users/hui/go); 批改.bash_profile,如果装置了iTerm2客户端须要批改.zshrc; ## Go我的项目工作空间export GOPATH=/Users/hui/Project/Go## 寄存编译后二进制文件的目录export GOBIN=$GOPATH/bin微信搜寻关注【猿码记】查看更多文章

January 31, 2023 · 1 min · jiezi

关于go:Go框架深入理解web框架的中间件运行机制

大家好,我是渔夫子。本号新推出「Go工具箱」系列,意在给大家分享应用go语言编写的、实用的、好玩的工具。同时理解其底层的实现原理,以便更深刻地理解Go语言。 大家在应用iris框架搭建web零碎时,肯定会用到中间件。那么你理解中间件的运行机制吗?你晓得为什么在iris和gin框架的申请处理函数中要加c.Next()函数吗?本文就和大家一起探索该问题的答案。 一、中间件的根本应用在web开发中,中间件起着很重要的作用。比方,身份验证、权限认证、日志记录等。以下就是各框架对中间件的根本应用。 1.1 iris框架中间件的应用package mainimport ( "github.com/kataras/iris/v12" "github.com/kataras/iris/v12/context" "github.com/kataras/iris/v12/middleware/recover")func main() { app := iris.New() //通过use函数应用中间件recover app.Use(recover.New()) app.Get("/home",func(ctx *context.Context) { ctx.Write([]byte("Hello Wolrd")) }) app.Listen(":8080")}1.2 gin框架中应用中间件package mainimport ( "github.com/gin-gonic/gin")func main() { g := gin.New() // 通过Use函数应用中间件 g.Use(gin.Recovery()) g.GET("/", func(ctx *gin.Context){ ctx.Writer.Write([]byte("Hello World")) }) g.Run(":8000")}1.3 echo框架中应用中间件示例package mainimport ( v4echo "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware")func main() { e := v4echo.New() // 通过use函数应用中间件Recover e.Use(middleware.Recover()) e.GET("/home", func(c v4echo.Context) error { c.Response().Write([]byte("Hello World")) return nil }) e.Start(":8080")}首先咱们看下三个框架中应用中间件的共同点: 都是应用Use函数来应用中间件都内置了Recover中间件都是先执行中间件Recover的逻辑,而后再输入Hello World接下来咱们持续剖析中间件的具体实现。 ...

January 31, 2023 · 4 min · jiezi

关于go:go微服务框架Kratos-连载五使用protbuf创建http服务器

一、介绍前几张咱们曾经学了kratos的根本框架。本章咱们来深刻分析一下原理。kratos框架之所以可能应用protbuf创立http服务器,多亏了框架自带的protoc-gen-go-http插件。那么咱们是否能够在其余中央应用这个插件呢,答案是能够,明天咱们就试一下。本文章代码地址在 https://github.com/hisheng/kratos-http 1.1 筹备目录咱们新建一个 kratos-http目录,并且go模块初始化。创立目录: mkdir kratos-http && cd kratos-httpgo我的项目初始化:咱们在kratos-http根目录执行一下代码 go mod init github.com/hisheng/kratos-http1.2 装置protoc-gen-go以及http扩大protoc-gen-go-http咱们在kratos-http根目录执行一下代码,装置扩大。 go install google.golang.org/protobuf/cmd/protoc-gen-go@latestgo install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2@latest

January 31, 2023 · 1 min · jiezi

关于go:Go-基础篇之切片-Slice

明天动工第一天,2023 xdm 什么指标,评论区聊聊。明天咱们来聊聊切片(Slice)。 1. 说在后面在之前的 Go 语言根底篇数组咱们说到数组的长度是固定的,申明了之后就不能扭转其长度。所以数组就会有很多的局限性。举个例子: Go 数组 s 咱们此时曾经申明长度为 5,咱们不能在往数组 s 中增加新的元素了,在业务开发中这样的汇合就不太实用。 2. 什么是切片Go 语言中提供了一种灵便、性能强悍的内置类型切片(又称动静数组)Slice,和数组相比切片的长度是不固定的,能够向其追加元素。 2.1 切片数据结构切片是一个援用类型,底层源码是用构造体来示意的,其中: Data 是指向数组的指针Len 是以后切片的长度Cap 是以后切片的容量,也是 Data 数组的大小Data是一片间断的内存空间,在这片空间中存储着切片的所有元素,底层贮存上也是间断的。咱们能够简略了解成:切片是一片间断的内存空间加上长度与容量的标识。 从上图能够发现切片其实就是数组的援用,咱们能够在运行期间批改其长度与范畴,当切片援用的数组长度有余会触发扩容,此时切片指向的数组会发生变化,然而对用户来说是无感知的。 3. 切片3.1 初始化咱们能够申明一个未指定大小的数组来定义切片: var identifier []type其中:identifier 示意变量名,type 示意切片中的元素类型,举个例子 slice[0:10]slice := []int{1, 2, 3, 4, 5, 6}slice := make([]int, 10)总结一下,大抵有 3 种 通过下标的形式取得数组或者切片的一部分;应用字面量初始化新的切片;应用关键字 make 创立切片;3.2 切片的长度和容量切片是可索引的,Go 语言中切片提供内置的办法。 len() 办法获取长度;cap() 能够计算切片的容量; 以上会输入以下后果为: len=3 cap=5 slice=[0 0 0] 3.3 切片空值判断一个切片在未初始化之前默认为 nil,默认长度为 0,所以判断是否应用 len(s) == 0,不应该应用 s == nil。 ...

January 31, 2023 · 1 min · jiezi

关于go:Golang-AES加密解密

Golang AES加密解密package mainimport ( "bytes" "crypto/aes" "crypto/cipher" "encoding/base64" "errors" "fmt")//加密过程:// 1、解决数据,对数据进行填充,采纳PKCS7(当密钥长度不够时,缺几位补几个几)的形式。// 2、对数据进行加密,采纳AES加密办法中CBC加密模式// 3、对失去的加密数据,进行base64加密,失去字符串// 解密过程相同//16,24,32位字符串的话,别离对应AES-128,AES-192,AES-256 加密办法//key不能泄露var PwdKey = []byte("1234asdf1234asdf")//pkcs7Padding 填充func pkcs7Padding(data []byte, blockSize int) []byte { //判断短少几位长度。起码1,最多 blockSize padding := blockSize - len(data)%blockSize //补足位数。把切片[]byte{byte(padding)}复制padding个 padText := bytes.Repeat([]byte{byte(padding)}, padding) return append(data, padText...)}//pkcs7UnPadding 填充的反向操作func pkcs7UnPadding(data []byte) ([]byte, error) { length := len(data) if length == 0 { return nil, errors.New("加密字符串谬误!") } //获取填充的个数 unPadding := int(data[length-1]) return data[:(length - unPadding)], nil}//AesEncrypt 加密func AesEncrypt(data []byte, key []byte) ([]byte, error) { //创立加密实例 block, err := aes.NewCipher(key) if err != nil { return nil, err } //判断加密快的大小 blockSize := block.BlockSize() //填充 encryptBytes := pkcs7Padding(data, blockSize) //初始化加密数据接管切片 crypted := make([]byte, len(encryptBytes)) //应用cbc加密模式 blockMode := cipher.NewCBCEncrypter(block, key[:blockSize]) //执行加密 blockMode.CryptBlocks(crypted, encryptBytes) return crypted, nil}//AesDecrypt 解密func AesDecrypt(data []byte, key []byte) ([]byte, error) { //创立实例 block, err := aes.NewCipher(key) if err != nil { return nil, err } //获取块的大小 blockSize := block.BlockSize() //应用cbc blockMode := cipher.NewCBCDecrypter(block, key[:blockSize]) //初始化解密数据接管切片 crypted := make([]byte, len(data)) //执行解密 blockMode.CryptBlocks(crypted, data) //去除填充 crypted, err = pkcs7UnPadding(crypted) if err != nil { return nil, err } return crypted, nil}//EncryptByAes Aes加密 后 base64func EncryptByAes(data []byte, key []byte) (string, error) { res, err := AesEncrypt(data, key) if err != nil { return "", err } return base64.StdEncoding.EncodeToString(res), nil}//DecryptByAes base64解码后 Aes 解密func DecryptByAes(data string, key []byte) ([]byte, error) { dataByte, err := base64.StdEncoding.DecodeString(data) if err != nil { return nil, err } return AesDecrypt(dataByte, key)}func main() { var origin = []byte("123456") //加密 encrypt, _ := EncryptByAes(origin, PwdKey) //解密 decrypt, _ := DecryptByAes(encrypt, PwdKey) //打印 fmt.Printf("加密前: %s\n", origin) fmt.Printf("加密后: %s\n", encrypt) fmt.Printf("解密后:%s\n", decrypt)}

January 30, 2023 · 2 min · jiezi

关于go:go微服务框架Kratos-连载四kratos生成的httppbgo文件解读

一、介绍在上一章节 go微服务框架Kratos (连载三) :创立restful接口咱们介绍了 如何来生成一个 restful接口。本章咱们具体理解一下,kratos生成的_http.pb.go文件。咱们关上 user_http.pb.go 文件,次要有两大部分组成。 服务端接口UserHTTPServer,以及路由注册函数RegisterUserHTTPServer()客户端接口UserHTTPClient,以及初始化客户端命令NewUserHTTPClient()供调用方应用。二、创立服务端三、创立客户端

January 30, 2023 · 1 min · jiezi

关于go:还能这样玩Go-将会增强-Go1-向前兼容性

大家好,我是煎鱼。 年前咱们在《醒醒吧,将来不会有 Go2 了!》文章中探讨了 Go2 的将来,明确了将来是以 Go1.x.y 为主的 Go1 时代。 为了实现这个北极星指标,Go 团队采取的策略别离是:加强 Go1 向后兼容(在前文已分享)和 Go1 向前兼容(本文重点内容)。 本次要提到的 “向前兼容”,指的是旧版本的 Go 编译新的 Go 代码。这个方向比拟少被议论,甚至特意设计。 Go1 向前兼容Go 团队的大当家 Russ Cox,针对如下几个方面做了新设计和调整,输入了《Proposal: Extended forwards compatibility in Go》,曾经失去探讨,很大概率落地。 局部重点如下: 新增 GOTOOLCHAIN 环境变量的设置。扭转在工作模块(work module)中解释 go 行的形式,减少了新的工具链(toolchain)行。对 go get 等命令进行联动批改,容许对 GOTOOLCHAIN 和工作模块的 go 版本进行批改。工作模块的 go.mod 和 toolchain申明 Go 版本号咱们会在 go module 生成时,在 Go 工程下生成一个 go.mod 文件。其中会蕴含一个 go 行,将会申明该模块应该利用的 go 版本语义是什么版本。 如下图,申明的是 go1.13: 在该提案落地后,本地装置的 Go 工具链如果比 go 行所申明的 go 版本新时,它将会间接提供所要求的旧语义,而不会从新下载和调用一个旧版本的 Go 工具链。 ...

January 30, 2023 · 2 min · jiezi

关于go:为什么-Go-不支持-T-转换为-interface

在 Go 中,如果 interface{} 作为函数参数的话,是能够传任意参数的,而后通过类型断言来转换。 举个例子: package mainimport "fmt"func foo(v interface{}) { if v1, ok1 := v.(string); ok1 { fmt.Println(v1) } else if v2, ok2 := v.(int); ok2 { fmt.Println(v2) }}func main() { foo(233) foo("666")}不论是传 int 还是 string,最终都能输入正确后果。 那么,既然是这样的话,我就有一个疑难了,拿出我触类旁通的能力。是否能够将 []T 转换为 []interface 呢? 比方上面这段代码: func foo([]interface{}) { /* do something */ }func main() { var a []string = []string{"hello", "world"} foo(a)}很遗憾,这段代码是不能编译通过的,如果想间接通过 b := []interface{}(a) 的形式来转换,还是会报错: cannot use a (type []string) as type []interface {} in function argument正确的转换形式须要这样写: ...

January 30, 2023 · 4 min · jiezi

关于go:go入门grpc第八章-创建grpc客户端

一、介绍在 《go入门grpc》第七章: 创立grpc服务器 咱们介绍了创立grpc服务器,而后咱们应用的BloomRPC作为客户端去发动申请。 本周咱们学习,如何在代码中,新建一个客户端,去调用grpc服务器。创立grpc服务器的时候,咱们应用了hello_grpc.pb.go外面的 server接口和注册办法。在创立客户端的时候更简略,只有调用hello_grpc.pb.go外面的SayHello()办法就行了。咱们也简略分为两大步骤: 创立 grpc客户端链接应用_grpc.pb.go 外面的NewSayClient来新建一个sayClient,而后调用SayHello()办法二、创立grpc客户端咱们在我的项目根目录,同级server,创立一个client目录。而后在client目录里,创立一个 client_test.go文件。如下: ➜ grpc-demo1 git:(master) tree.├── Makefile├── api│   ├── hello.pb.go│   ├── hello.proto│   ├── hello_grpc.pb.go│   ├── user.pb.go│   └── user.proto├── client│   └── client_test.go├── go.mod├── go.sum└── server ├── hello.go └── main.go3 directories, 11 files如要参考整个我的项目的代码,能够拜访以下地址https://github.com/hisheng/grpc-demo1

January 29, 2023 · 1 min · jiezi

关于go:go入门grpc第七章-创建grpc服务器

一、介绍通过后面的基础知识的解说,咱们理解到了 protoc 命令的作用,帮咱们自动化生成go代码。次要有.pb.go 以及_grpc.pb.go 文件。目前的代码我放到了github上,能够查看残缺的代码。https://github.com/hisheng/grpc-demo1咱们再温习一下以后的目录构造如下: ➜ grpc-demo1 git:(master) ✗ tree.├── Makefile├── api│   ├── hello.pb.go│   ├── hello.proto│   ├── hello_grpc.pb.go│   ├── user.pb.go│   ├── user.pb_test.go│   └── user.proto├── go.mod└── go.sum1 directory, 9 files

January 29, 2023 · 1 min · jiezi

关于go:GO-web-开发-实战二数据库相关

xdm 上次有分享到GO web 开发 中 http 包中的简略办法应用,最初还有一个 模板 , 在这里补充一下 间接上案例 模板咱们在 main.go 外面写一个 服务端的 demo,应用模板来将冬天的数据写入到 html 文件中对应的须要写一个 html 文件,并设置好 须要模板注入的数据地位main.go package mainimport ( "fmt" "html/template" "net/http")var myTemp *template.Templatetype Person struct { Name string Title string Age int}//开始解决数据和做响应func userInfo(w http.ResponseWriter, req *http.Request) { defer req.Body.Close() var pp []Person // 简略模仿数据 p1 := Person{ Name: "xmt 1号", Title: "1 号 展示台", Age: 18, } p2 := Person{ Name: "xmt 2号", Title: "2 号 展示台", Age: 15, } p3 := Person{ Name: "xmt 3号", Title: "3 号 展示台", Age: 29, } pp = append(pp, p1, p2, p3) // 将数据写到模板中 err := myTemp.Execute(w, pp) if err != nil { fmt.Println("Execute err ;%v", err) return }}func main() { //初始化模板 var err error myTemp, err = template.ParseFiles("./index.html") if err != nil { fmt.Println("ParseFiles err ;%v", err) return } //注册解决模板的函数 并 开启监听 http.HandleFunc("/", userInfo) err = http.ListenAndServe("0.0.0.0:9999", nil) if err != nil { fmt.Println("ListenAndServe err ;%v", err) return }}index.html ...

January 28, 2023 · 3 min · jiezi

关于go:go入门grpc第六章protoc生成的grpcpbgo文件解读

更不便的在微信公众号阅读文章能够关注公众号:海生的go花园 一、介绍在第五章,咱们学习了.pb.go文件《go入门grpc》第五章:protoc生成的.pb.go文件解读本章咱们学习下protoc --go-grpc_out 命令生成的_grpc.pb.go文件。咱们以hello.proto文件为例,代码如下: syntax = "proto3";package hello;import "google/protobuf/timestamp.proto";option go_package = "github/hisheng/grpc-demo1/api";service Say { rpc SayHello (HelloRequest) returns (HelloReply) {}}message HelloRequest { string name = 1;}message HelloReply { string message = 1; google.protobuf.Timestamp last_updated = 2;}应用protoc --go-grpc_out命令生成了 hello_grpc.pb.go文件。 package api......type SayClient interface { SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)}......type SayServer interface { SayHello(context.Context, *HelloRequest) (*HelloReply, error) mustEmbedUnimplementedSayServer()}......次要有三局部 packageServer服务端接口,以及实现Client客户端接口,以及实现二、Server服务端接口,以及实现三、Client客户端接口,以及实现SayClient 是 SayService 的 客户端。次要包含定义了一个SayClient接口,以及一个sayClient构造体。sayClient构造体实现了SayClient接口。对外提供一个 NewSayClient()来生成初始化SayClient客户端。 NewSayClient(cc grpc.ClientConnInterface) SayClienttype SayClient interface { ...

January 28, 2023 · 1 min · jiezi

关于go:PHP转Go实践xjson解析神器开源工具集

前言近期会更新一系列开源我的项目的文章,新的一年会和大家做更多的开源我的项目,也欢送大家退出进来。xutil明天分享的文章源自于开源我的项目jinzaigo/xutil的封装。 在封装过程中,劲仔将实现原理以及相干实际思考,写成文章分享进去,从而汇总系列文章汇合。 PHP转Go我和劲仔都是PHP转Go,身边越来越多做PHP的敌人也逐步在用Go进行重构,重构过程中,会发现php的json解析操作(系列化与反序列化)是真的香,弱类型语言的各种隐式类型转换,很大水平的减低了程序的复杂度。 反观go应用规范库encoding/json,来做json解析就没有那么欢快了(只有数据类型定义不对,就很容易抛error) JSON解析实际案例:用go重构的服务,对接的上游还是php服务,这时php接口输入的json串为{"name":"AppleWatchS8","price":"3199"} 。 其中price字段应该得为float类型,但因为php弱类型语言,没有强制束缚输入类型的机制,就很容易呈现这种输入类型不对的状况,而后到go服务里得怎么解决呢? 规范库encoding/jsonpackage mainimport ( "encoding/json" "fmt")type ProductInfo struct { Name string `json:"name"` Price float32 `json:"price"`}func main() { str := "{"name":"AppleWatchS8","price":"3199"}" data := ProductInfo{} if err := json.Unmarshal([]byte(str), &data); err != nil { fmt.Println("error: " + err.Error()) } else { fmt.Println(data) }}//输入后果//error: json: cannot unmarshal string into Go struct field ProductInfo.price of type float32显然,应用go规范库做json解析,是应答不了这种类型不统一的状况的。上面则借助第三方库的能力来做解决 第三方库json-iterator简略介绍: 执行速度:jsoniter 的 Golang 版本能够比规范库(encoding/json)快 6 倍之多 两个特点: 齐全兼容规范库,也就是API用法齐全一样,原有逻辑代码不须要改变,只须要替换import包名提供了一个PHP兼容模式,能够主动转换字符串/数字弱类型问题,能够将空数组[]转换为空构造体(解决PHP中的array输入为[]的问题)。留神,该兼容模式须要手动开启装置形式: go get -u github.com/json-iterator/go具体代码实现: ...

January 28, 2023 · 1 min · jiezi

关于go:Go存储引擎资料分享

背景最近逛知乎的时候看到了这个问题,“Go语言如何写数据库?”。说来我业余时间在这个畛域有一些工夫精力的投入了,所以想答复一下。我投入的方向是存储引擎方面,所以这篇文章次要是总结一下我看过的一些比拟好的Go存储引擎的材料。列举一些论文,开源我的项目。读者能够自行去理解。 什么是存储引擎?简略来说存储引擎就是寄存和读取用户数据的中央,对于长久化的存储引擎而言,数据的归宿是非易失性的存储介质(艰深意义上来说就是磁盘)所以该以什么模式组织和存储数据,这就是存储引擎设计的艺术所在。这一块波及到和操作系统打交道(次要是IO操作),还有如何更快的解决数据,这里波及到并发事物如何解决,另外思考空间局部性和工夫局部性原理,这里波及到对数据缓存的设计。整体来说scope还是比拟大的,钻研空间比拟广。上面举荐的是磁盘IO相干的文章和数据存储相干的视频材料。而这篇文章次要列举的是Hash,B+Tree,LSM-Tree三种存储引擎的材料。 磁盘IO那些事数据存储与检索(详解b+树存储引擎(innodb、boltdb、buntdb等)、lsm树存储引擎(bitcask、moss、pebble、leveldb等)1. HashHash存储引擎绝对实现比较简单,这里就放在第一个讲了。Bitcask是hash存储引擎的典型实现,而Bitcask在go中有两个实现,nutsdb和rosedb,而nutsdb是我去年开始参加保护的,tiny-bicask是我写的一个简略版bitcask实现,目标是不便nutsdb社区小伙伴疾速上手我的项目。上面是我举荐的bitcask相干材料和我的项目: Bitcask papernutsdbrosedbtiny-bitcasknutsdb设计与实现 Go夜读分享rosedb 设计与实现Go夜读分享2. B+TreeB+ Tree是大家耳熟能详的一种存储引擎架构,赫赫有名的MySQL innodb存储引擎就是基于B+ Tree实现的。在Go中Boltdb是B+Tree的典型实现,其中驰名的分布式存储etcd,底层用的是boltdb存储元数据。上面是B+Tree存储引擎的一些相干材料: Boltdb自底向上剖析 BoltDB 源码Google B-Tree实现3. LSM-TreeLSM-Tree的典型代表有leveldb和rocksdb,目前支流的NoSQL数据库底层采纳的存储引擎个别都是基于LSM-Tree实现的。而在go中有goleveldb和badgerdb两个实现,而badger是基于论文WiscKey实现的Key Value拆散的LSM架构存储。 LSM paperWisckey papergoleveldbbadgerdbleveldb hand-book总结其实要怎么写数据库,我感觉这个问题还是太宽了,然而如果你对这方面的确感兴趣,能够先从学习相干实践,并且选一些开源我的项目去钻研源码,必要时候能够参加到开源我的项目的开发之中。没有比理论入手写更好的学习形式了。另外在前面的学习过程中还会有更多优良的学习材料,所以打算把这些材料整顿到github我的项目外面,前面不便保护,https://github.com/elliotchen...,大家对这方面感兴趣的话能够star和提PR,感激。

January 27, 2023 · 1 min · jiezi

关于go:Golang-遇到-note-module-requires-Go-1nn-解决之道不升go

Golang 遇到 note: module requires Go 1.xx 解决之道,不升go在应用多版本的golang的小伙伴,往往会遇到这个问题。本文就如何不降级 go 版本来解决该问题。 怎么产生的同时应用IDE和命令行,命令行go版本和IDE的go不是同一个版本。多人合作同一个我的项目,他人应用不同版本的go退出了一个包且写入了一个较高版本号。go get 时抉择了较高版本。网上的大部分解决方案都是降级本人的go版本。那么如果不想降级有方法解决么? 不升Go版本例如我遇到了: # golang.org/x/sys/unix../../go/pkg/mod/golang.org/x/sys@v0.3.0/unix/syscall.go:83:16: undefined: unsafe.Slice../../go/pkg/mod/golang.org/x/sys@v0.3.0/unix/syscall_darwin.go:95:8: undefined: unsafe.Slice../../go/pkg/mod/golang.org/x/sys@v0.3.0/unix/syscall_unix.go:118:7: undefined: unsafe.Slice../../go/pkg/mod/golang.org/x/sys@v0.3.0/unix/sysvshm_unix.go:33:7: undefined: unsafe.Slicenote: module requires Go 1.17尝试把 go.sum 删掉,再 go mod tidy 还是没用,仍然报这个错。 这时看看 go.mod 文件 module github.com/PaulXu-cn/xxxgo 1.15require ( github.com/go-faker/faker/v4 v4.0.0-beta.4 github.com/golang/protobuf v1.5.2 github.com/snksoft/crc v1.1.0 github.com/spf13/cobra v1.6.1 github.com/spf13/viper v1.15.0)也就是说以后我的 go runtime 是 1.15 的,是援用了基于 go1.17 的包,须要把这个包降为依赖 go1.15的即可。那这里的哪个包须要降版本呢? 该我的项目简略,只有5个间接依赖,能够通过顺次删除增加测进去,如果有很多依赖的话,又该怎么解决呢? 包前面带 // indirect 是间接依赖,删掉这一行不影响。 参考 https://go.dev/ref/mod上工具这里介绍个工具 gmchart , go mod 图像化展现工具 —— https://github.com/PaulXu-cn/... ...

January 26, 2023 · 1 min · jiezi

关于go:近期Psql相关业务的收获agg函数对于null值的处理-arrayagg-Unmarshal的性能消耗和工作原理

【case 1】我的项目背景:须要返回一些GC的统计数据。相干数据存在frame这张表内,表中的数据一行就是一帧的数据,能够了解为记录了这一帧内的性能信息。与需要相干的col是GcChartSample,是一个json类型的数据,外面存的是该帧触发的各个品种的GC的大小,没有触发的GC的字段将不会列在这个GC中。例如:{"Internal":252,"Other":192,"Scripts":7832},就是InternalGC是252字节,OtherGC是192字节,ScriptsGC是7832字节。求:各类GC的无效帧均值(即:非0帧的均值)和最大值 我的第一版解法:将区间内的所有帧的GcChartSample字段取出放入go中,在go中进行解决。即:先开一个gcLineMap记录所有呈现过的GC品种,而后再依据gcLineMap建设gcItemArray,分类push 非0的GC值,最初依据各个数组算出统计数据。 弱化局部需要后,mentor举荐的解法:用户在查看性能报告的时候,通常只会关注局部GC的值,例如:ScriptsGC,RenderingGC等。因而,并不一定要求出所有GC的统计。并且sql善于做统计的操作。将统计的工作放在sql里做,可能缩小IO。因而,sql批改如下: select sum(cast(GcChartSample ->> 'Scripts' as Integer)) as ScriptsGCMax, round(count(cast(GcChartSample ->> 'Scripts' as Integer)), 2) as ScriptsGCMean, max(cast(GcChartSample ->> 'Rendering' as Integer)) as RenderingGCMax, round(avg(cast(GcChartSample ->> 'Rendering' as Integer)), 2) as RenderingGCMean, max(cast(GcChartSample ->> 'GUI' as Integer)) as GUIGCMax, round(avg(cast(GcChartSample ->> 'GUI' as Integer)), 2) as GUIGCMean, max(cast(GcChartSample ->> 'Animation' as Integer)) as AnimationGCMax, round(avg(cast(GcChartSample ->> 'Animation' as Integer)), 2) as AnimationGCMeanfrom upa.frame where partitionkey = 5;起初放心,应用sql里的avg操作只能返回均值,无奈返回无效帧均值。然而,翻阅sql文档后发现,sum会主动疏忽值为null的字段。 ...

January 25, 2023 · 1 min · jiezi

关于go:如何在-Go-语言开发的宿主程序中嵌入-WebAssembly

在 WebAssembly的官网定义中,for a stack-based virtual machine 这句话也值得关注,因为它引领了 WebAssembly 这一本来为 Web 设计的技术(名字中就蕴含了Web一词),最终进入后端畛域。 这是因为,从晚期的 VMWare WorkStation、VirtualBox,到明天的 Docker,虚拟化技术始终是云计算的根底。 因而,作为一种具备诸多劣势的虚拟机代码格局,WebAssembly 进入后端应用领域是必然趋势。 Docker 创始人 Solomon Hykes 在 2019 年示意: 如果 WASM+WASI 在 2008 年就存在,咱们就不须要创立 Docker可见 WebAssembly 在后端利用中的确具备广大的利用前景。 当然,Solon Hykes 示意,他的意思并不是稍后 WebAssembly 将取代 Docker. 这也是当今业界广泛的认识:WebAssembly 和 Docker 各有劣势,井水不犯河水。 具体来说: WebAssembly 程序的大小通常在 1M 左右,而 Docker 镜像往往很容易超过 100M,因而 WebAssembly 的加载速度要快得多。WebAssembly 程序的冷启动速度比 Docker 容器快约 100 倍。WebAssembly 运行在沙箱中,任何与外界的交互都须要取得明确的许可后能力进行,安全性极佳。WebAssembly 模块只是一个二进制程序,不蕴含操作系统环境,所以它不能像咱们在 Docker 中那样编译后执行。如下图所示,无论是 Web 利用还是非 Web 利用,咱们都须要在宿主程序中嵌入WebAssembly Runtime(运行时)能力应用 WebAssembly. 惟一不同的是,在 web 利用中,宿主程序是浏览器,而在非 web 场景中,宿主程序是咱们本人的利用,具体到后端利用,宿主程序则是咱们的后端服务。 ...

January 23, 2023 · 1 min · jiezi

关于go:Go语言2023年开发者调研来了文末附上2022年精彩文章合集

2023年Go语言调研Go团队的Alice Merrick在2023.01.18公布了2023年一月份开发者调研的线上链接地址。 过来7年,Go团队每年都会对Go开发者做调研。 从2022年开始,为了加重大家填写问卷调查的累赘以及更好地晋升调研成果,调研频率从一年一次变为一年两次。 开发者的调研反馈帮忙扭转了Go语言的生态。 例如,Go语言的依赖治理(dependency management)、破绽扫描(vulnerability scanning)和泛型(generics)等重要设计都来源于调研后果。 本次线上调研地址为: the January 2023 edition of the Go Developer Survey。 调研工夫从2023.01.18继续到2023.02.08。 2022年精彩文章合集Go语言面试题系列Go开发常见谬误和最佳实际系列Go泛型设计原理以及最佳实际系列Go工作区模式Go语言版本演进系列,读懂各个版本的演进历史开源地址文章和示例代码开源在GitHub: Go语言高级、中级和高级教程。 公众号:coding进阶。关注公众号能够获取最新Go面试题和技术栈。 集体网站:Jincheng's Blog。 知乎:无忌。 福利我为大家整顿了一份后端开发学习材料礼包,蕴含编程语言入门到进阶常识(Go、C++、Python)、后端开发技术栈、面试题等。 关注公众号「coding进阶」,发送音讯 backend 支付材料礼包,这份材料会不定期更新,退出我感觉有价值的材料。还能够发送音讯「进群」,和同行一起交流学习,答疑解惑。 Referenceshttps://go.dev/blog/survey202...

January 22, 2023 · 1 min · jiezi

关于go:go入门grpc第五章protoc生成的pbgo文件解读

----先把题目定好,有工夫写,要上班了。《go入门grpc》第五章:protoc生成的.pb.go文件解读

January 18, 2023 · 1 min · jiezi

关于go:我的个人微信也迅速接入了-ChatGPT

本文次要来聊聊如何疾速应用集体微信接入 ChatGPT,欢送 xdm 尝试起来,仅供学习参考,切莫用于做不正当的事件 对于 ChatGPT 咱们每个人都能够简略的应用上,不须要你有很强的技术背景,不须要你有公众号,甚至不须要你本人接入,只有你有一个微信号,就能够享受到 ChatGPT 带给你的惊喜,那么咱们开始吧 本文别离从如下几个方面来聊: ChatGPT 是什么<!----> 集体微信如何疾速接入 ChatGPT<!----> 对于 ChatGPT 的思考ChatGPT 是什么 ChatGPT 实际上一个以对话的模式来答复各种问题的模型,他的名字叫做 ChatGPT ,简略了解,他就是一个聊天机器人 事实中,咱们印象中的机器人总是那么死板和执著,然而 ChatGPT 却是一个十分人性化的对话模型,他能够和咱们聊天,答复咱们的各种问题,并且上下文他是能够做到关联的 甚至在将来你在应用各种应用软件的时候,与你对接的客服,或者就是这样的机器人,你可能齐全感触不到他竟然可能像人一样,甚至比人还聪慧,比人还博学 集体微信如何疾速接入 ChatGPT集体微信一样可能轻松的接入 ChatGPT ,不须要你有公众号,只须要做对接的人满足如下资源即可: 通过实名认证的微信号<!----> Openai 的账号密码<!----> 个人电脑或者一台 linux 虚拟机做服务器与 Chatgpt 对话首先,对于 openai 的账号如何注册此处就不过多赘述了,网络上的材料还是十分多的,xdm 理论注册的时候留神几点即可 账号所选的国家尽可能抉择海内,例如我注册的时候就抉择了 India<!----> 手机号接码的时候可能会有肯定的提早,实际操作并不是每一次都能迅速的接管到码的,来回操作了5 - 10 分钟左右收到了一个码,xdm 要急躁chatgpt:登录地址 https://chat.openai.com/ 即可享受与 chatgpt 进行进行对话 实际上,ChatGPT 还能够帮咱们写代码,写算法,写诗,答复最新的股票信息等等 集体微信接入ChatGPT集体微信接入ChatGPT ,网上材料十分的多,实际了一遍之后,并不是每一个形式都能够正确运行的,或者是姿态不对,目前发现一个应用 Go 实现的我的项目比拟香,能够非常简单疾速的达到咱们的目标 接入前提先去 openai 上创立创立一个 API Keys,这个十分重要,没有这个 API Keys ,对于本案例,是没有方法接入胜利的 登录 openai:https://beta.openai.com/login/ ...

January 18, 2023 · 1 min · jiezi

关于go:go入门grpc第四章使用Makefile优化protoc命令

更不便的在微信公众号阅读文章能够关注公众号:海生的go花园 一、前言在第三章,咱们曾经学会了应用protoc命令,生成go文件。代码如下: protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ api/hello.protoprotoc命名须要列出 .proto文件,如果咱们有多个文件,或者咱们想多个文件夹,怎么办?此时咱们能够借助Makefile来,执行一些脚本,主动生成go代码。 二、应用Makefile来生成protoc命令。咱们在grpc-demo1目录新建一个Makefile文件。 touch Makefile此时查看grpc-demo1目录,构造如下: ➜ grpc-demo1 git:(master) ✗ tree.├── Makefile├── api│   ├── hello.pb.go│   ├── hello.proto│   └── hello_grpc.pb.go├── go.mod└── go.sum1 directory, 6 files多了一个 Makefile文件。咱们生成一个make protoc命令,代码如下,写入到Makefile文件中。 protoc: protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ api/hello.proto写好后,咱们在grpc-demo1目录执行下: $ make protoc此时这个make protoc命名代替了 protoc 命令一大堆参数,简化了咱们的复杂度。要生成go文件只有执行一下就行。

January 18, 2023 · 1 min · jiezi

关于go:go入门grpc第三章从-proto-文件自动生成go代码

更不便的在微信公众号阅读文章能够关注公众号:海生的go花园 一、装置protoc以及插件在第二章,咱们介绍了,如何写一个.proto文件。当咱们有了一个.proto文件,揭晓来,咱们就是应用protoc命令编译.proto文件,生成对应go文件。 1.1 装置protoc命令brew install protobuf1.2 装置protobuf插件1.2.1、装置protoc-gen-go插件,--go_out选项用来生成.pb.go文件,用来解决message等失常的类型。 go install google.golang.org/protobuf/cmd/protoc-gen-go1.2.2、装置protoc-gen-go-grpc插件,--go-grpc_opt选项用来解决grpc相干的程序。 google.golang.org/grpc/cmd/protoc-gen-go-grpc二、应用protoc命令生成go代码2.1 初始化go我的项目首先咱们关上grpc-demo1目录(在第二章创立的),而后go mod init。初始化这个go我的项目。 $ cd grpc-demo1$ go mod init github/hisheng/grpc-demo1此时查看咱们的目录,执行tree命令。 ➜ grpc-demo1 git:(master) $ tree.├── api│   └── hello.proto├── go.mod└── go.sum1 directory, 3 files咱们的目录多了 go.mod文件以及go.sum。 2.2 应用protoc命令生成go代码当初终于到了咱们生成理论go代码的时候了,让咱们在grpc-demo1执行如下命令。 protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ api/hello.proto咱们终于执行了protoc命令了,此时咱们减少了两个参数选项。 --go_out 生成了 hello.pb.go 文件--go-grpc_out 生成了 hello_grpc.pb.go 文件此时咱们再查看grpc-demo1,执行tree命令 ➜ grpc-demo1 git:(master) ✗ tree.├── api│   ├── hello.pb.go│   ├── hello.proto│   └── hello_grpc.pb.go├── go.mod└── go.sum1 directory, 5 files能够看到刚生成的hello.pb.go和hello_grpc.pb.go两个go文件。 ...

January 18, 2023 · 1 min · jiezi

关于go:go入门grpc第二章在proto文件中定义gPRC服务

一、介绍Protocol Buffers是一种语言中立、跨平台,用来序列化结构化数据的一阵协定。次要定义了一个proto文件,就能够在多种编程语言,多种操作系统应用。咱们应用最新的proto3版本。咱们先新建一个 hello.proto文件 mkdir grpc-demo1 && cd grpc-demo1 && mkdir api && cd api && touch hello.proto最初咱们看到一个目录 ➜ grpc-demo1 git:(master) ✗ tree.└── api └── hello.proto1 directory, 1 file二、proto文件基础知识咱们先关上hello.proto文件,写入以下代码,而后解说一下。一个proto文件的次要形成有 三 局部。 syntax,package,import 定义协定格局以及proto命名空间,加载其余的proto包名go_package 生成go文件 package 名称service,message proto文件的内容,service定义grpc,message定义音讯syntax = "proto3";package hello;import "google/protobuf/timestamp.proto";option go_package = "./api;api";service Say { rpc SayHello (HelloRequest) returns (HelloReply) {}}message HelloRequest { string name = 1;}message HelloReply { string message = 1; google.protobuf.Timestamp last_updated = 2;}

January 18, 2023 · 1 min · jiezi

关于go:go入门grpc第一章什么是gRpc

更不便的在微信公众号阅读文章能够关注公众号:海生的go花园 一、介绍当初微服务,有次要的两种形式 rest api 以及 grpc。相比rest api ,grpc有更快的速度,更小的体积,能够显著的替身性能。 1、什么是gRpcgrpc是一个”近程调用过程“RPC框架。rpc是从近程调用一个微服务的函数。grpc是一种围绕protobuf协定,进行过程间通信的一种形式。通过protobuf来解决客户端和服务端的 音讯message。如下图:通过protobuf,咱们生成客户端和服务端函数,以及message。一切都是建设在protobuf协定上的。所以应用grpc,咱们个别都是先定义proto文件,而后转成客户端以及服务端go代码。 这种架构,非常适合 ”客户端-服务器“ 应用程序。 2、如何用protobuf形容grpc一个grpc服务应用 service,以及message两个关键字形容。 service HelloService { rpc SayHello (HelloRequest) returns (HelloResponse);}message HelloRequest { string greeting = 1;}message HelloResponse { string reply = 1;}在这里咱们先定义一个 HelloService,提供一个SayHello办法,供其余的服务调用。申请的message为HelloRequest,供client申请参数应用。返回message为HelloResponse,server返回给client。

January 17, 2023 · 1 min · jiezi

关于go:Golang逃逸分析理解

逃逸剖析(Escape analysis)是Golang中一个非常重要的概念。Golang会在两个中央为变量分配内存,一个是全局的堆(heap)空间用来动静分配内存,另一个是goroutine的栈(stack)空间,因为Golang的内存治理是主动的,开发者并不需要关怀内存在堆或栈上调配,但从性能角度登程,在栈或堆上分配内存性能差别非常微小 逃逸剖析指由编译器决定内存调配的地位 *调配在栈(Stack)中,则函数完结后可主动将内存回收 *调配在堆(Heap)中,则函数执行完结可交给GC(垃圾回收)解决程序的执行效率与上述两种调配规定关联严密传值与传指针的次要区别在于底层值是否须要拷贝,传指针看似不波及值的拷贝,效率会更高,然而理论状况是传递指针会波及到变量逃逸到堆上,同时减少GC的累赘 Golang在栈上的开销和回收内存的开销很低,只须要PUSH和POP两个指令,耗费的仅是将数据拷贝至内存的工夫 而在堆上分配内存,很大的额定开销就是垃圾回收(GC),Golang应用的垃圾回收机制是标记分明算法,同时在此基础上应用三色标记法和写屏障技术,以提高效率。 标记革除收集器是跟踪式垃圾收集器,其执行过程能够分成标记(Mark)和革除(Sweep)两个阶段* 标记阶段-从根对象登程查找并标记堆中所有的存活对象* 革除阶段-遍历堆中的全副对象,回收未被标记的垃圾对象并将回收的内存退出闲暇链表标记分明算法的一个典型耗时是在标记期间,须要暂停程序,标记完结之后,用户程序才能够继续执行逃逸剖析不是间接的优化伎俩,而是通过动态分析对象的作用域,为其它优化伎俩提供根据的剖析技术,逃逸剖析是一种确定指针动静范畴的动态剖析,能够剖析在程序的哪些地方能够拜访到指针 逃逸类型*办法逃逸(对象跳出以后办法) 当一个对象在办法中被定义后,它可能被内部办法所援用,例如作为调用参数传递到其它中央*线程逃逸(对象逃出以后线程) 这个对象甚至可能被其它线程拜访到,例如赋值给类变量或能够在其它线程中拜访的实例变量变量逃逸状况: 指针逃逸 在函数中创立了一个对象,返回该对象的指针,在该状况下,函数尽管退出,但因为指针的存在,对象的内存不能随着函数完结而回收,只能调配在堆上栈空间有余逃逸 操作系统对内核线程应用的栈空间有大小限度,因为栈空间通常较小,当递归函数实现不过后,容易导致栈溢出。对于Golang,运行时(runtime)尝试在goroutine须要的时候动静地调配栈空间,goroutine的初始栈大小为2KB,当goroutine被调度时,会绑定内核线程执行,栈空间大小也不会超过操作系统的限度,超过肯定大小的局部变量将逃逸到堆上动静类型逃逸,函数参数为interface类型 空接口即interface{}能够示意任意类型,当函数参数为interface{},编译期间难以确定其参数的具体类型,会产生逃逸闭包援用对象逃逸,其实实质还是共享栈上的值 函数的返回值是一个闭包函数,闭包函数拜访内部变量,则内部变量将会始终存在,直到闭包函数销毁,内部变量不能随着函数的退出而回收,逃逸至堆上 编译时能够借助选项 -gcflags=-m,查看变量逃逸的状况 能够应用ulimit -a查看机器上栈容许占用的内存的大小编译器能够通过逃逸剖析对代码做如下优化:(Wekipedia) 同步省略或锁打消(Synchronization Elimination),如果一个对象被发现只能从一个线程被拜访到,那么对于这个对象的操作能够不思考同步将堆调配转化为栈调配(Stack Allocation),如果一个对象在子程序中被调配,要使指向该对象的指针永远不会逃逸,对象可能是栈调配的候选,而不是堆调配拆散对象或标量替换(Scalar Replacement),有的对象可能不须要作为一个间断的内存构造存在也能够被拜访到,那么对象的局部(或全副)能够不存储在内存,而是存储在CPU寄存器中逃逸剖析论断 栈上分配内存比在堆中分配内存有更高的效率栈上分配内存不须要GC解决,函数执行后主动回收堆上调配的内存应用结束后会交给GC解决产生逃逸时,会把栈上申请的内存挪动到堆上指针能够缩小底层值的拷贝,提高效率,然而会产生逃逸,如果拷贝的数据量小,逃逸造成的累赘(堆内存调配+GC回收)会升高效率抉择值传递或指针传递关键在于要以变量的大小作为剖析指标 个别状况下,对于须要批改原对象值,或占用内存比拟大的构造体,抉择传指针。对于只读的占用内存较小的构造体,间接传值可能取得更好的性能

January 17, 2023 · 1 min · jiezi

关于go:mac系统go环境安装借助goland

一、下载go我的项目xormmodel介绍一下我的电脑是apple m2,上面的环境是在这个根底上装置的。咱们这里应用我的开源我的项目https://github.com/hisheng/xo...来介绍应用。 git clone git@github.com:hisheng/xormmodel.git当咱们下载完我的项目后,咱们应用goland关上xormmodel我的项目。 ---残余的今天写,上班了。

January 16, 2023 · 1 min · jiezi

关于go:醒醒吧未来不会有-Go2-了

大家好,我是煎鱼。 马上春节了,节前最初一更。提前预祝大家春节快乐! 本周末在学习的时候,看到 Go 团队大当家 Russ Cox(下称:rsc)在近期分享的《GopherCon 2022: Russ Cox - Compatibility: How Go Programs Keep Working》,讲的是 Go 在兼容性方面的现有问题和思考,还埋了个新预期。 如下图: 他提出了一个新的 Slogan:“Go is boring, and that's good.(Go 很无聊,这很好)”,起因在于 Go 无聊是好的,因为无聊代表稳固的。无聊意味着你可能专一于你的工作,而不是咱们的工作。 外围来讲,Go 团队心愿 Go 足够简洁,Gopher 不要终日卷 Go 的各种奇思妙计,要把精力都关注到本人的工作上,不要关注他们。 我一开始听起来多少有点情理和本人的想法,听着听着这个车就刹不住了。 在最初的最初,rsc 冷不丁的正式官宣:不会有 Go2 了,会始终放弃 Go1,将会加倍投入对 Go1 兼容性的建设,这将十分有价值。 如下图: 当然,他也讲了,广义里的 Go2 可能曾经产生了,只是缓缓转为了 Go1 的新个性融入到了 Go 之中。 最重要的,那些没法兼容的 “新” 货色怎么办?大方向的大招曾经在前文《加大力度!Go 将会加强 Go1 向后兼容性》有介绍过。 外围之一:应用 Go 工程中的 go.mod 文件内的 go 版本号来管制编译的抉择,决定各个库在不同 Go 版本下以不同的体现来利用其个性,将会影响编译时的决定。 ...

January 16, 2023 · 1 min · jiezi

关于go:GO-语言-Web-开发实战一

xdm,咱明天分享一个 golang web 实战的 demo go 的 http 包,以前都有或多或多的提到一些,也有一些笔记在咱们的历史文章中,明天来一个简略的实战 HTTP 编程 Get先来一个 小例子,简略的写一个 Get 申请 拿句柄设置监听地址和端口进行数据处理 package mainimport ( "fmt" "net/http")func myHandle(w http.ResponseWriter, req *http.Request){ defer req.Body.Close() par := req.URL.Query() fmt.Println("par :",par) //回写数据 fmt.Fprintln(w,"name",par.Get("name"),"hobby",par.Get("hobby"))}// server 端func main() { http.HandleFunc("/", myHandle) err := http.ListenAndServe("0.0.0.0:9999", nil) if err != nil{ fmt.Printf("ListenAndServe err : %v",err) return }}上述的代码比较简单,就是一个简略的 http get 申请 , 次要解决数据的是 myHandle 函数 Client 客户端 实现办法 getclient.go get办法、post办法、patch办法、head办法、put办法等等,用法基本一致设置urlget (或者其余办法)办法申请 url解决数据package mainimport ( "fmt" "io/ioutil" "net/http" "net/url")//httpserver 端func main() { //1.解决申请参数 params := url.Values{} params.Set("name", "xiaomotong") params.Set("hobby", "乒乓球") //2.设置申请URL rawUrl := "http://127.0.0.1:9999" reqURL, err := url.ParseRequestURI(rawUrl) if err != nil { fmt.Printf("url.ParseRequestURI() 函数执行谬误,谬误为:%v\n", err) return } //3.整合申请URL和参数 reqURL.RawQuery = params.Encode() //4.发送HTTP申请 // reqURL.String() String将URL重构为一个非法URL字符串。 fmt.Println("Get url:", reqURL.String()) resp, err := http.Get(reqURL.String()) if err != nil { fmt.Printf("http.Get()函数执行谬误,谬误为:%v\n", err) return } defer resp.Body.Close() //5.一次性读取响应的所有内容 body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Printf("ioutil.ReadAll()函数执行出错,谬误为:%v\n", err) return } fmt.Println("Response: ", string(body))}上述编码中有应用到 reqURL.RawQuery = params.Encode() ...

January 15, 2023 · 3 min · jiezi

关于go:tinyrpc源码阅读

tinyrpc是一个高性能的基于protocol buffer的rpc框架。我的项目代码非常少,很适宜初学者进行golang的学习。 tinyrpc性能tinyrpc基于TCP协定,反对各种压缩格局,基于protocol buffer的序列化协定。其rpc是基于golang原生的net/rpc开发而成。 tinyrpc我的项目构造tinyrpc基于net/rpc开发而成,在此基础上集成了额定的能力。我的项目构造如图: 性能目录如下: codec 编码模块compressor 压缩模块header 申请/响应头模块protoc-gen-tinyrpc 代码生成插件serializer 序列化模块tinyrpc源码解读客户端和服务端构建客户端是以net/rpc的rpc.Client为根底构建,在此基础上定义了Option以配置压缩形式和序列化形式: type Option func(o *options)type options struct { compressType compressor.CompressType serializer serializer.Serializer}在创立客户端的时候将配置好的压缩算法和序列化形式作为创立客户端的参数: func NewClient(conn io.ReadWriteCloser, opts ...Option) *Client { options := options{ compressType: compressor.Raw, serializer: serializer.Proto, } for _, option := range opts { option(&options) } return &Client{rpc.NewClientWithCodec( codec.NewClientCodec(conn, options.compressType, options.serializer))}}服务端是以net/rpc的rpc.Server为根底构建,在此基础上扩大了Server的定义: type Server struct { *rpc.Server serializer.Serializer}在创立客户端和开启服务时传入序列化形式: func NewServer(opts ...Option) *Server { options := options{ serializer: serializer.Proto, } for _, option := range opts { option(&options) } return &Server{&rpc.Server{}, options.serializer}}func (s *Server) Serve(lis net.Listener) { log.Printf("tinyrpc started on: %s", lis.Addr().String()) for { conn, err := lis.Accept() if err != nil { continue } go s.Server.ServeCodec(codec.NewServerCodec(conn, s.Serializer)) }}压缩算法compressor压缩算法的实现中首先是定义了压缩的接口: ...

January 14, 2023 · 5 min · jiezi

关于go:为什么使用-golang-http包-会把-linux-句柄打满

最近工作的时候一个接入服务须要测性能测试,万万没想到测出了一个把 linux 句柄打满的问题 具体是什么问题呢,咱们一起来看看 失常操作我的项目中,有一些 http 申请是这样写的: 申请 https 的地址,为了绕过 tls ,加上了 TLSClientConfig: &tls.Config{InsecureSkipVerify: true} 配置失常拜访咱们须要的申请的地址失常获取咱们的冀望的数据,失常解析func main() { client := http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, }, } resp, err := client.Get("https://www.xxxxxx.com") if err != nil { fmt.Println("Get err : ", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(string(body))}例如如下是拜访百度的后果,没有什么故障 t# go run main.go<html><head> <script> location.replace(location.href.replace("https://","http://")); </script></head><body> <noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript></body></html>发现问题可是例如这样的申请代码拿去做性能测试的话,咱们理论遇到的问题是,linux 句柄数被打满了 句柄数被打满了,简略的思考有如下 2 个初步的可能: linux 句柄数设置过小http 代码没有开释连贯我晓得的有如下 3 种形式,能够批改 linux 的句柄数: ...

January 13, 2023 · 2 min · jiezi

关于go:万万没想到go也能使用对象来操作数据库了网友直呼健壮性有保证了

Hi,各位go的小伙伴,大家新年好。 之前给大家介绍的Aorm库,都用上了吗?这可是迄今为止我见过的,go畛域最好用的数据库操作库了。 去年的时候(实际上是半个月前),我发了一篇文章来介绍Aorm的链式操作,展现了它的易用性。 《万万没想到,go的数据库操作,也能像php一样溜了》 不少敌人加我,示意了反对,并且提出了殷切希望。其中有一点,心愿能够减少应用对象来操作数据库。 通过我半个月的钻研与致力,当初它来了,它来了,它踏着魔鬼步调走来了。 什么是应用对象操作数据库有很多敌人可能没听过说过这个事件,我就先拿别的语言的代码例子来简略介绍下 $users = DB::table('users')->whereIn('id', [1, 2, 3])->orderBy('name', 'desc')->get();如上,PHP的代码里,一个简略的数据库查问语句,php的敌人很眼生吧。 这里的呈现的users, id, name都是字符串,都须要手动编写进去,弊病很显著 1. 开发的时候,容易产生拼写错误。 2. 重构的时候,或者字段名以及表名有更改的时候,那可就苦逼了。因为他们散布在我的项目的各个中央,你须要极其小心的,正确的找进去他们,而后批改。漏掉一个那就是一颗定时炸弹。 咱们再来看看 .NET 里,如何解决这个问题 dbContext .Person .GroupJoin( dbContext.Products, person => person.Id, product => product.Id, (person, products) => new { Person = person, Products = products } ) .SelectMany( combination => combination.Products.DefaultIfEmpty(), (person, products) => new { PersonId = person.Person.Id, PersonName = person.Person.Name, ProductsId = products.Id, ProductsName = products.Product } ) .ToList();以上你看到的代码,外面没有一个手写的字符串,全都是对象类型,或者对象的属性。 ...

January 13, 2023 · 1 min · jiezi

关于go:20230113-周报

Go 工程化 - 编译文件体积优化 Go 工程化 - 单元测试根底必知必会 Go 工程化 - 单元测试覆盖率 Go 工程化 - 单元测试之 Fixture Go 工程化 - 基准测试数据分析

January 13, 2023 · 1 min · jiezi

关于go:go使用jwt入门教程

更不便的在微信公众号阅读文章能够关注公众号:海生的go花园 一、介绍go应用jwt目前,支流应用的jwt库是golang-jwt/jwt1.1 如何装置 go get -u github.com/golang-jwt/jwt/v41.2 import到我的项目里 import "github.com/golang-jwt/jwt/v4"1.3 支流2类加密算法介绍 加密算法代表算法加解密对称加密算法 hsaHS256(最罕用), HS384, HS512冀望[]byte用于签名和验证的值非对称签名办法 rsaRS256(最罕用), RS384,RS512rsa.PrivateKey用于签名和*rsa.PublicKey验证

January 13, 2023 · 1 min · jiezi

关于go:如何在Golang中为字符串添加单引号

我在Go中有一个字符串切片,我想将其示意为逗号分隔的字符串。这是切片 example := []string{"apple", "Bear", "kitty"}如何输入字符串 'apple', 'Bear', 'kitty' commaSep := "'" + strings.Join(example, "', '") + "'"

January 13, 2023 · 1 min · jiezi

关于go:go使用nethttp必知必会4种ContentType类型

一、介绍Content-Type示意header头中,用来批示资源的原始媒体类型mime type。他就像一个说明书,阐明了服务端/或浏览器应该怎么解决这次申请。 在申请中,例如get和post,客户端通知服务器理论发送的数据类型。在返回中,Content-Type标头示意,服务端返回内容的理论类型。1.1 语法Content-Type: text/html; charset=utf-8Content-Type: multipart/form-data; boundary=somethingmedia-type : 资源或数据的MIME 类型字符集 : 字符编码标准。不辨别大小写,首选小写。边界: 对于多局部实体,boundary指令是必须的。该指令由一组字符(不以空格结尾)中的1到70个字符组成,这些字符在电子邮件网关中十分牢靠。它用于封装音讯的多个局部的边界。通常,题目边界后面有两个破折号,最终边界的开端有两个破折号。1.2 四种常见的Content-Type区别

January 12, 2023 · 1 min · jiezi

关于go:go使用nethttp发送post请求

一、介绍上一篇咱们介绍过 go应用net/http库发送GET申请本期介绍post申请。post和get申请不同,次要在于 header局部,而net/http也帮咱们封装了快捷的形式来发送post申请。咱们这里产生post申请,这里次要通过两种形式 http.Post()DefaultClient.Do()二、2种实现形式

January 12, 2023 · 1 min · jiezi

关于go:GO-实现优先队列

在php中提供了SplPriorityQueue来实现优先队列操作。在Go中,尽管没有间接提供优先队列的实现,不过通过规范库container/heap能够很不便的实现一个简略的优先队列。 heap 提供了堆的数据结构,通过实现heap.Interface接口,能够疾速实现最大堆或者最小堆。而优先队列通常是在最大堆上做封装即可。在go官网heap包的文档中,提供了一个简略的优先队列演示,以下基于go官网文档中的代码做从新调整实现优先队,用go实现了php优先队列代码中的演示。 package mainimport ( "container/heap" "fmt")type Item struct { value string // The value of the item; arbitrary. priority int // The priority of the item in the queue.}type PriorityQueue []*Itemfunc (pq PriorityQueue) Len() int { return len(pq) }func (pq PriorityQueue) Less(i, j int) bool { return pq[i].priority > pq[j].priority}func (pq PriorityQueue) Swap(i, j int) { pq[i], pq[j] = pq[j], pq[i]}func (pq *PriorityQueue) Push(x interface{}) { item := x.(*Item) *pq = append(*pq, item)}func (pq *PriorityQueue) Pop() interface{} { old := *pq n := len(old) item := old[n-1] old[n-1] = nil *pq = old[0 : n-1] return item}func main() { queue := new(PriorityQueue) heap.Init(queue) heap.Push(queue, &Item{value: "A", priority: 3}) heap.Push(queue, &Item{value: "B", priority: 6}) heap.Push(queue, &Item{value: "C", priority: 1}) heap.Push(queue, &Item{value: "D", priority: 2}) len := queue.Len() fmt.Println("优先队列长度:", len) item := (*queue)[0] fmt.Println("top 提取值: ", item.value) fmt.Println("top 提取优先级: ", item.priority) fmt.Println("遍历") for queue.Len() > 0 { fmt.Println(heap.Pop(queue).(*Item).value) }}更多代码 点击这里 ...

January 11, 2023 · 1 min · jiezi

关于go:go使用nethttp库发送GET请求

一、概述http 包提供 HTTP 客户端和服务器实现。官网文档 https://pkg.go.dev/net/http 咱们能够多看几遍。次要的提供的办法有 Get、Head、Post 和 PostForm 。咱们实现的话get申请的话,次要有2种形式 http.Get()client.Get()而后咱们会介绍封装参数,header,transport 二、2种实现形式2.1 最简略的 http.Get()办法咱们应用http的Get()函数 func Get(url string ) (resp * Response , err error )Get办法 向指定的 URL 收回 GET。Get 是 DefaultClient.Get 的包装器。用于没有自定义header的疾速申请。 func Test1(t *testing.T) { url := fmt.Sprintf("http://localhost:8080/v1/user?id=%d", 1010) resp, err := http.Get(url) if err != nil { } // 客户端发动的申请必须在完结的时候敞开 response body defer resp.Body.Close() body, err := io.ReadAll(resp.Body) t.Log(resp, err) t.Log(string(body))}这个代码,咱们能够等价替换为DefaultClient.Get如下 func Test1t(t *testing.T) { url := fmt.Sprintf("http://localhost:8080/v1/user?id=%d", 1010) resp, err := http.DefaultClient.Get(url) if err != nil { } // 客户端发动的申请必须在完结的时候敞开 response body defer resp.Body.Close() body, err := io.ReadAll(resp.Body) t.Log(resp, err) t.Log(string(body))}2.2 封装header以及param参数

January 11, 2023 · 1 min · jiezi

关于go:centos8-安装golang

以下为centos8装置golang的binary版本的办法绝对于间接从yum源装置,能够装置更新的版本 root下 $ rm -rf /usr/local/go && tar -C /usr/local -xzf go1.19.5.linux-amd64.tar.gz$ export PATH=$PATH:/usr/local/go/bin$ go versiongolang 的commandhttps://pkg.go.dev/cmd/go 参考文献https://go.dev/dl/https://go.dev/doc/install

January 11, 2023 · 1 min · jiezi

关于go:Go-语言解析-JSON

本文将阐明如何利用 Go 语言将 JSON 解析为构造体和数组,如果解析 JSON 的嵌入对象,如何将 JSON 的自定义属性名称映射到构造体,如何解析非结构化的 JSON 字符串。 JSON 解析为构造体JSON 的构造是 key-value,最直观的就是将 JSON 解析为构造体,如下 JSON : { "name": yuzhou1u, "age": 18}Go 语言中,提供了一个专门的包 encoding/json ,所以咱们在应用这个 JSON 包之前须要在头文件导入: package mainimport ( "encoding/json" "fmt")而后,咱们须要定义一个 Go 语言的构造体以便咱们能与 JSON 一一对应,比方在 JSON 中咱们定义了姓名 name 和年龄 age ,所以须要定义一个构造体(命名能够随便,但最好通俗易懂)的字段与 JSON 字符串中的键相匹配: type Person struct { Name string Age int}而后应用 json.Umarshal() 函数来解析 JSON 字符串,残缺代码如下: package mainimport ( "encoding/json" "fmt")type Person struct { Name string Age int}func main() { var p Person jsonString := `{"name": "yuzhou1su", "age" : 18}` err := json.Unmarshal([]byte(jsonString), &p) if err == nil { fmt.Println(p.Name) fmt.Println(p.Age) } else { fmt.Println(err) }}当初来解释一下下面 main 函数的代码: ...

January 10, 2023 · 3 min · jiezi

关于go:Go-读取文本文件的三种方式

Go 读取文本文件工作中时不时须要读取文本,文本文件是最常见的文件类型。 本文将从逐行、一一单词和一一字符三个办法读取文件: byLine.gobyWord.gobyCharacter.go1 逐行读取文本文件逐行读取文件是最为常见的文本文件,也是最为简略的形式。首先咱们须要导入几个常见的包: bufio:缓存区读写文件flag:命令行参数解析package mainimport ( "bufio" "flag" "fmt" "io" "os")func lineByLine(file string) error { var err error f, err := os.Open(file) if err != nil { return err } defer f.Close() r := bufio.NewReader(f) for { line, err := r.ReadString('\n') if err == io.EOF { break } else if err != nil { fmt.Printf("error reading file %s", err) break } fmt.Print(line) } return nil}func main() { flag.Parse() if len(flag.Args()) == 0 { fmt.Printf("usage: byLine <file1> [<file2> ...]\n") return } for _, file := range flag.Args() { err := lineByLine(file) if err != nil { fmt.Println(err) } }}代码解释: ...

January 10, 2023 · 2 min · jiezi

关于go:Go-容器之数组

在 Java 的外围库中,汇合框架堪称鼎鼎大名:Array 、List、Set、Queue、HashMap 等等,轻易拎一个进去都值得开发者好好学习如何应用甚至是背地的设计源码(这类文章也挺多,大家上网轻易一搜)。 尽管 Go 语言没有如此丰盛的容器类型。 1 序列容器序列容器存储特定类型的数据元素。目前有 5 种序列容器的实现: arrayvectordequelistforward_list这些序列容易能够用程序的形式保留数据,利用这些序列容易可能编写无效的代码,重复使用规范库的模块化。 1.1 数组Go 语言中的数组类型有点相似 C++ 中的数据,Go 的数组初始化定义后,在编译时就不会再变更。 定义数组的形式如下: var a [10]intb := [5]string {"H", "e", "l", "l", "o"}[n]T 类型就示意含有 n 个类型为 T 的数组,本例中就是 a 变量示意含有 10 个 int 类型的整型数组;b 变量示意含有 5 个 string 类型的字符串数组。数组的长度作为其类型的一部分,因而数组的长度是无奈调整的。 package mainimport "fmt"func main() { var a [10]int a[0] = 2022 a[1] = 2023 fmt.Println(a[0], a[1]) fmt.Println(a) b := [5]string {"H", "e", "l", "l", "o"} fmt.Println(b)}运行后果如下: ...

January 10, 2023 · 3 min · jiezi

关于go:go语言解析excel

go get github.com/xuri/excelize/v2 package mainimport ( "fmt" "strings" "github.com/xuri/excelize/v2")func main() { f, err := excelize.OpenFile("/Users/test/abc.xlsx") if err != nil { fmt.Println(err) return } rows, err := f.GetRows("Sheet1") if err != nil { fmt.Println(err) return } fmt.Println("rows:", len(rows)) var sql strings.Builder sql.WriteString("INSERT INTO test (a, b, c, d, e) VALUES\n") for idx, row := range rows { if idx == 0 { continue } var a, b, c, d string for colIdx, colCell := range row { switch colIdx { case 0: a = colCell case 1: b = colCell case 2: c = colCell case 4: d = colCell } } sql.WriteString("('" + a + "', '" + b + "', '" + c + "', '" + d + "', '2023-01-10 00:00:00'), \n") } fmt.Println(sql.String())}

January 10, 2023 · 1 min · jiezi

关于go:加大力度Go-将会增强-Go1-向后兼容性

大家好,我是煎鱼。 前段时间咱们在写 Go1.20 新个性和变更时,发现了一个问题有悖论。 Go1 有兼容性承诺,但如果发现了 BUG,会毁坏兼容性。那怎么办?是大胆批改,毁坏掉,还是说设计如此,打死不改? 写了个结尾后果阳了,当初阳半康回来更。 Go1 兼容性保障在 Go1 引入了 Go 兼容性保障《Go 1 and the Future of Go Programs》,也就是旧版本的 Go 程序也能够在持续 Go 的新版本中正确运行。当然,凡事有例外,像是平安问题就是例外。 具体的残缺细则如下图: 咱们常接触到的有以下几个: 平安问题:Go 标准或施行中的平安问题可能会被发现,其解决须要毁坏兼容性。将会保留解决这些平安问题的权力。未指定的行为:尽管 Go 标准中尝试明确所有已知行为,然而意料之外是会存在一些方面是未定义的。这方面可能会呈现问题。标准谬误:如果有必要解决标准(spec)中呈现的不统一、不残缺,将会保留解决此类问题的权力。除了平安问题,不会对标准进行不兼容的批改。问题/缺点:如果编译器、库有违反标准的缺点,会保留修复这些缺点的权力。应用 import . 导入:如果在 程序应用 import . "path",在将来的版本中,在导入的包中定义的其余名字可能会与程序中定义的其余名字相冲突。咱们不举荐在测试之外应用 import .,应用它可能会导致程序在将来的版本中无奈编译。援用 unsafe 库:导入 unsafe 的包可能依赖于 Go 实现的外部属性。会保留批改的权力。Go 外围团队自述曾经有 10+ 年的 Go1 兼容性保障的教训,对 Go 团队和用户来说都十分的有价值。 甚至近两年,Go 团队和业内也有把 Go 的高速倒退归因于对 Go1 兼容性的保障的落地施行。 看起来还是一板一眼的。 扩大 Go 向后兼容性背景尽管主观上 Go 团队认为做的比拟好,但发现依然存在进行了兼容性毁坏的状况。因而 Go 现任当家 @Russ Cox 发动了《extending Go backward compatibility》。 ...

January 10, 2023 · 2 min · jiezi

关于go:20230106-周报

Go 工程化 - 根底开发配置 Go 工程化 - 命令工具必知必会 Go 工程化 - 穿插编译 Go 工程化 - 条件编译

January 10, 2023 · 1 min · jiezi

关于go:godongle-026-版本发布一个轻量级语义化的-golang-编码解码加密解密库

dongle 是一个轻量级、语义化、对开发者敌对的 Golang 编码解码和加密解密库 Dongle 已被 awesome-go 收录, 如果您感觉不错,请给个 star 吧 github.com/golang-module/dongle gitee.com/golang-module/dongle 更新日志 减少对 tea 超长文本的加密、解密反对,如果加密明文超过 8 字节,进行空字符串填充分段加密减少 Empty 空字符串填充模式的反对更改 github.com/tjfoc/gmsm/sm3 为 github.com/emmansun/gmsm/sm3将 encrypt 办法从 encrypter.go 挪动到 cipher.go, 将 decrypt 办法从 decrypter.go 挪动到 cipher.go移除 invalidTeaSrcError、invalidModeError 和 invalidPaddingError性能清单 [x] Hex 编码、解码[x] Base16 编码、解码[x] Base32 编码、解码[x] Base45 编码、解码[x] Base58 编码、解码[x] Base62 编码、解码[x] Base64 编码、解码[x] Base64URL 编码、解码[x] SafeURL 编码、解码[x] Base85 编码、解码[x] Base91 编码、解码[x] Base100 编码、解码[x] Morse(摩斯) 编码、解码[x] Md2 加密[x] Md4 加密[x] Md5 加密[x] Sha1 加密[x] Sha3-224 加密[x] Sha3-256 加密[x] Sha3-384 加密[x] Sha3-512 加密[x] Sha224 加密[x] Sha256 加密[x] Sha384 加密[x] Sha512 加密[x] Sha512-224 加密[x] Sha512-256 加密[x] Shake128 加密[x] Shake256 加密[x] Ripemd160 加密[x] Blake2b-256 加密[x] Blake2b-384 加密[x] Blake2b-512 加密[x] Blake2s-256 加密[x] Hmac-md2 加密[x] Hmac-md4 加密[x] Hmac-md5 加密[x] Hmac-sha1 加密[x] Hmac-sha3-224 加密[x] Hmac-sha3-256 加密[x] Hmac-sha3-384 加密[x] Hmac-sha3-512 加密[x] Hmac-sha224 加密[x] Hmac-sha256 加密[x] Hmac-sha384 加密[x] Hmac-sha512 加密[x] Hmac-sha512-224 加密[x] Hmac-sha512-256 加密[x] Hmac-ripemd160 加密[x] Hmac-sm3 加密[ ] Rc2 加密、解密[x] Rc4 加密、解密[ ] Rc5 加密、解密[ ] Rc6 加密、解密[x] Tea 加密、解密[ ] Xtea 加密、解密[x] Aes 加密、解密[x] Blowfish 加密、解密[x] Des 加密、解密[x] 3Des 加密、解密[x] Rsa 加密、解密[ ] Ecc 加密、解密[ ] Sm2 加密、解密[x] Sm3 加密[ ] Sm4 加密、解密[ ] Sm7 加密、解密[ ] Sm9 加密、解密[x] Bcrypt 签名、验签[x] Ed25519 签名、验签[x] Rsa 签名、验签[ ] Dsa 签名、验签

January 10, 2023 · 1 min · jiezi

关于go:Excelize-开源基础库-270-发布-2023-年首个更新

Excelize 是 Go 语言编写的用于操作 Office Excel 文档根底库,基于 ECMA-376,ISO/IEC 29500 国际标准。能够应用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创立的电子表格文档。反对 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格局,高度兼容带有款式、图片(表)、透视表、切片器等简单组件的文档,并提供流式读写 API,用于解决蕴含大规模数据的工作簿。可利用于各类报表平台、云计算、边缘计算等零碎。入选 2020 Gopher China - Go 畛域明星开源我的项目(GSP)、2018 年开源中国码云最有价值开源我的项目 GVP (Gitee Most Valuable Project),目前已成为 Go 语言最受欢迎的 Excel 文档根底库。 开源代码GitHub: github.com/xuri/excelize Gitee: gitee.com/xurime/excelize 中文文档: xuri.me/excelize/zh-hans 2023年1月9日,社区正式公布了 2.7.0 版本,该版本蕴含了多项新增性能、谬误修复和兼容性晋升优化。上面是无关该版本更新内容的摘要,残缺的更改列表可查看 changelog。 版本阐明此版本中最显著的变动包含: 兼容性提醒降级至该版本须要您应用的 Go 语言为 1.16 或更高版本,以迁徙不再反对的规范库 ioutil当给定工作表名称中存在有效字符时将返回谬误,不再主动疏忽有效字符GetCellStyle 函数不再返回合并单元格区域左上角单元格的款式重命名以下 5 个导出数据类型和谬误常量,具体更改详见官网文档中的更新阐明移除了 54 项导出类型,具体更改详见官网文档中的更新阐明移除了 2 个导出常量:OrientationPortrait 和 OrientationLandscape批改了以下 21 个函数的签名,应用构造体援用代替此前以 JSON 格局示意的选项参数,具体更改详见官网文档中的更新阐明引入了 8 项新的函数代替现有函数,具体更改详见官网文档中的更新阐明在 CellType 枚举值中增加 CellTypeFormula, CellTypeInlineString, CellTypeSharedString 并移除了 CellTypeString对增加批注 AddComment 函数的签名进行了更改,反对创立富文本批注,相干 issue #1204当 XML 反序列化异样时将返回谬误以代替输入日志,函数 GetComments, GetDefaultFont 和 SetDefaultFont 减少了 error 类型的谬误返回值新增性能新增 GetDataValidations 和 GetConditionalFormats 函数以反对获取数据验证设置和条件格局,相干 issue #827新增 ProtectWorkbook 和 UnprotectWorkbook 以提供工作簿爱护设置反对新增 SetSheetCol 函数以反对按列设置单元格的值,相干 issue #1247新增 GetColStyle 函数以反对设置列款式,相干 issue #1293新增 SetSheetBackgroundFromBytes 函数以反对依据给定的图片数据设置工作表背景图片,相干 issue #1405新增导出变量 IndexedColorMapping 以反对内建索引色彩转换新增 20 项导出类型: AutoFilterListOptions, AutoFilterOptions, Chart, ChartAxis, ChartDimension, ChartLegend, ChartLine, ChartMarker, ChartPlotArea, ChartSeries, ChartTitle, ConditionalFormatOptions, PaneOptions, Panes, GraphicOptions, Shape, ShapeColor, ShapeLine, ShapeParagraph 和 TableOptions新增 2 项公式函数: AGGREGATE 和 SUBTOTALSave、Write 和 WriteTo 函数反对指定保留选项,相干 issue #744应用 AddChart 函数增加图表时,反对为折线图设置是否应用平滑折线,相干 issue #1290应用 AddChart 函数增加图表时,反对设置自定义折线图线条色彩,相干 issue #1345应用 AddChart 函数增加图表时,反对设置自定义坐标轴字体款式,相干 issue #320增加图表函数 AddChart 反对创立三维折线图以下函数新增并发平安反对:SetColWidth、GetColWidth、SetColVisible、GetColVisible、SetColStyle 和 GetColStyle设置款式时,当给定的款式 ID 不存在时将返回谬误,相干 issue #1323流式按行赋值时,若行号未递增将返回谬误,以防止生成的工作簿损坏,相干 issue #1139按行流式写入工作表时,反对通过指定 RowOpts 为单元格设置款式,相干 issue #1354反对流式设置窗格,相干 issue #1047反对流式设置行内富文本单元格反对流式插入分页符新增 7 项导出错误信息: ErrUnprotectWorkbook、ErrUnprotectWorkbookPassword、ErrStreamSetPanes、ErrSheetNameBlank、ErrSheetNameInvalid、ErrSheetNameLength 和 ErrSheetNameSingleQuote,以便开发者可依据不同的谬误类型进行采取相应解决新增 5 项导出数据类型: HeaderFooterOptions、PageLayoutMarginsOptions、PageLayoutOptions、SheetPropsOptions 和 ViewOptions反对设置分级显示的明细数据方向反对读取和设置单元格字体的主题色彩和色调,相干 issue #1369反对读取带有合乎 ISO 8061 规范的工夫类型单元格的值反对设置和读取带有内建色彩索引的字体色彩工作簿敞开函数将清理由流式写入器生成的磁盘缓存文件反对增加或删除列时主动调整受影响的列款式通过 AddPicture 增加图片时,现已容许插入 SVG 格局图片兼容性晋升流式写入单元格时将以行内字符类型存储字符型单元格的值,相干 issue #1377保留工作簿时将跳过工作表中的不带有款式和属性的空白行,以缩小生成文档的体积,相干 issue #1383问题修复修复局部状况下读取带有内建数字格局款式的浮点数精度有误问题,解决 issue #1328,#1368 和 #1373修复局部状况下读取带有 AM/PM 数字格局款式的单元格有误问题,解决 issue #1338修复局部状况下删除批注时因为数组下标越界导致的 panic,解决 issue #1343修复局部状况下读取单元格的值时呈现 panic 的问题,解决 issue #1384 和 #1415修复局部状况下误将文本解析为浮点型数值的问题,解决 issue #1360修复应用空字符创立工作表后生成的工作簿损坏问题,解决 issue #1361修复向工作表增加图片后,获取该图片内容为空的问题修复局部状况下插入行列后生成的工作簿损坏问题删除单元格公式时将删除公式计算链中的共享单元格援用,以修复局部状况下生成的文档损坏问题修复局部状况下未对工作表名称特殊字符及长度做正确处理的问题,解决 issue #1328修复局部状况下公式函数 OR 计算结果有误的问题修复在带有繁多单元格区域援用的工作表中插入行列时,将收到异样的问题修复获取带有繁多单元格区域援用合并单元格区域时,收到异样的问题修复局部状况下读取富文本单元格的值不残缺问题修复流式写入时未本义 XML 字符导致的文档损坏问题,解决 issue #1391修复公式计算函数 ADDRESS 在工作表名称为空时计算结果有误的问题,解决 issue #1396修复局部状况下增加图片后果有误的问题,解决 issue #1404性能优化进步流式合并单元格性能,相较于上一版本,耗时最高升高约 90%,内存应用最高缩小约 86%优化按行流式写入工作表 SetRow 函数的性能,相较于上一版本,耗时最高升高约 19%其余Go Modules 依赖模块更新单元测试与文档更新优化外部变量与函数命名蕴含简体中文、英语、法语、俄语、日语、韩语、阿拉伯语、德语和西班牙语的多国语言文档网站更新致谢感激 Excelize 的所有贡献者,以下是为此版本提交代码的贡献者列表: ...

January 9, 2023 · 2 min · jiezi

关于go:gocarbon-223版本发布-轻量级语义化对开发者友好的Golang时间处理库

carbon 是一个轻量级、语义化、对开发者敌对的 golang 工夫解决库,反对链式调用。 目前已被 awesome-go 收录,如果您感觉不错,请给个 star 吧 github.com/golang-module/carbon gitee.com/golang-module/carbon 装置应用Golang 版本大于等于1.16// 应用 github 库go get -u github.com/golang-module/carbon/v2import ( "github.com/golang-module/carbon/v2" )// 应用 gitee 库go get -u gitee.com/golang-module/carbon/v2import ( "gitee.com/golang-module/carbon/v2")Golang 版本小于1.16// 应用 github 库go get -u github.com/golang-module/carbonimport ( "github.com/golang-module/carbon" )// 应用 gitee 库go get -u gitee.com/golang-module/carbonimport ( "gitee.com/golang-module/carbon" )更新日志新增 Time2Carbon 的别名办法 FromStdTime,  Carbon2time 的别名办法ToStdTime 办法,将来将弃用 Time2Carbon 和 Carbon2 办法修复 Format 办法里 W 和 N 符号输入谬误的 bug修复文档形容谬误

January 9, 2023 · 1 min · jiezi

关于go:Go常见错误第16篇any的常见错误和最佳实践

前言这是Go常见谬误系列的第16篇:any的常见谬误和最佳实际。 素材来源于Go布道者,现Docker公司资深工程师Teiva Harsanyi。 本文波及的源代码全副开源在:Go常见谬误源代码,欢送大家关注公众号,及时获取本系列最新更新。 常见谬误和最佳实际Go语言中,没有办法的接口类型是空接口,也就是大家熟知的interface{}。 从Go 1.18开始,定义了一个预申明标识符(Predeclared identifiers):any。 any实际上是空接口的别名,所以任何用了interface{}的中央都能够把interface{} 替换为any。 func main() { var i any i = 42 i = "foo" i = struct { s string }{ s: "bar", } i = f _ = i} func f() {}很多场景里,如果间接用any,会带来代码的适度形象。 Rob Pike在Gopherfest 2015上,已经分享过他的观点: interface{} says nothing.常见谬误给any类型的变量赋值的时候,咱们其实失去了所有类型信息,须要依赖类型断言(type assertion)来获取类型信息。 类型断言即t, ok := i.(T),代码示例如下所示: package mainimport "fmt"func main() { var i interface{} = "hello" s := i.(string) fmt.Println(s) s, ok := i.(string) fmt.Println(s, ok) f, ok := i.(float64) fmt.Println(f, ok) f = i.(float64) // panic fmt.Println(f)}咱们看看上面这个例子,领会下应用any带来的问题。 ...

January 8, 2023 · 2 min · jiezi

关于go:客服系统即时通讯IM开发三访客实现一对一聊天访客生成唯一id标识存储到全局变量唯一客服网站在线客服系统

在访客进入聊天界面的时候,就要调用接口生成一个惟一ID标识 而后前端链接WebSocket的时候,传递这个访客ID进来 如果你想在前端访客连贯时生成一个 UUID,能够应用 Go 语言的第三方库来生成 UUID。 举荐应用 http://github.com/satori/go.uuid 库。它是一个简略易用的 UUID 生成库,反对生成罕用的几种 UUID 版本。 例如,你能够应用上面的代码生成一个 UUID V4: package mainimport ( "fmt" "github.com/satori/go.uuid")func main() { u := uuid.NewV4() fmt.Printf("UUID: %s\n", u)}在进入界面的时候,调用接口,接口中生成好访客ID,而后带着访客ID GET申请链接WebSocket package mainimport ( "net/http" "github.com/gin-gonic/gin" "github.com/gin-gonic/websocket")var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true },}// 定义一个全局的 map 类型变量来保留连贯var connections = make(map[string]*websocket.Conn)func main() { r := gin.Default() r.GET("/ws", func(c *gin.Context) { conn, err := upgrader.Upgrade(c.Writer, c.Request, nil) if err != nil { http.NotFound(c.Writer, c.Request) return } // 获取访客 ID visitorID := c.Query("visitor_id") // 将连贯保留到全局变量中 connections[visitorID] = conn for { // 读取音讯 _, message, err := conn.ReadMessage() if err != nil { delete(connections, visitorID) break } // 发送音讯 err = conn.WriteMessage(websocket.TextMessage, message) if err != nil { delete(connections, visitorID) break } } })这样就能够在程序的其余中央,拿着访客ID去给指定的访客发送音讯,或者应用for循环去播送音讯 ...

January 7, 2023 · 1 min · jiezi

关于go:客服系统即时通讯IM开发二Golang-Gin框架实现服务端WebScoket唯一客服网站在线客服系统

我的客服零碎应用的Golang+ Gin作为后端服务,所以上面的代码是演示demo 在 Go 语言中应用 Gin 框架实现 WebSocket 的办法如下: 装置 gin-gonic/websocket 库。在 Gin 的路由处理函数中应用 ws.Upgrade 函数将 HTTP 连贯降级为 WebSocket 连贯。在路由处理函数中应用 conn.ReadMessage 和 conn.WriteMessage 函数接管和发送音讯。例如: package mainimport ( "net/http" "github.com/gin-gonic/gin" "github.com/gin-gonic/websocket")var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true },}func main() { r := gin.Default() r.GET("/ws", func(c *gin.Context) { conn, err := upgrader.Upgrade(c.Writer, c.Request, nil) if err != nil { http.NotFound(c.Writer, c.Request) return } for { // 读取音讯 _, message, err := conn.ReadMessage() if err != nil { break } // 发送音讯 err = conn.WriteMessage(websocket.TextMessage, message) if err != nil { break } } }) r.Run()}下面的代码中,咱们在 /ws 路由处理函数中应用 upgrader.Upgrade 函数将 HTTP 连贯降级为 WebSocket 连贯。而后,咱们应用 conn.ReadMessage 函数读取音讯,应用 conn.WriteMessage 函数发送音讯。 ...

January 7, 2023 · 2 min · jiezi

关于go:go118-安装godoc报错

最近在试着写go库,想看看godoc成果,而后发现命令无奈找到 查了下网上拷贝来拷贝去的材料,发现go 1.1.13版本之后就从外围包中移除了须要本人装置 而后尝试go get装置,go get golang.org/x/tools/cmd/godoc 发现报错如下 go: go.mod file not found in current directory or any parent directory. 'go get' is no longer supported outside a module. To build and install a command, use 'go install' with a version, like 'go install example.com/cmd@latest' For more information, see https://golang.org/doc/go-get-install-deprecation or run 'go help get' or 'go help install'.搜寻无果,认真读了下报错信息,发现新版本勾销了go get装置内部模块,用go get命令必须有go mod,就算开启了go env -w GO111MODULE=on也不行 所以新版装置godoc的正确命令是 go install golang.org/x/tools/cmd/godoc@latest留神,必须在最初指定版本 ...

January 6, 2023 · 1 min · jiezi

关于go:B2B2C多商家商城系统-对接多商家在线客服系统IM-唯一客服系统

多商家商城零碎与多商家客服零碎对接多商家商城零碎和客服零碎能够通过API进行数据对接其中的重点就是: 新商城商家注册后主动同步成为客服零碎商家老商城商家数据与客服零碎商家同步商城商家零碎登录后,能够单点登录到客服零碎 商城新商家账号注册到客服平台调用注册客服接口 商城中的老商家数据如何同步这外面的问题是,商家商家的明码必定是加密存储的,拿不到原始明码。商城商家的明码规定可能与客服零碎的明码规定不统一,也不可能间接导数据 解决办法是: 调用客服零碎注册商家接口,明码局部给一个初始密码,商城商家登录客服零碎后去批改商城如果须要单点登录到客服零碎,明码规定不统一的状况下,不可能通过账号密码登录,须要调用外部接口,去间接获取客服零碎商家身份token 商家商家应用账号密码获取token(一)调用获取token接口客户登录到商家后盾的时候,在登录验证那里被动调用一下获取token,存储在浏览器缓存中。token的有效期是一天。 商家商家通过外部接口获取token(二)调用获取token接口客户登录到商家后盾后,点击客服零碎标签时,通过外部接口被动调用一下获取token,存储在浏览器缓存中。token的有效期是一天。该外部接口,只须要传递账号就能获取到tokken,所以须要配置IP白名单,只容许内网IP进行调用 商家后盾单点登录客服平台带token一键跳转登录点击进去客服平台的时候,从浏览器缓存中读取token,间接往下面接口去跳转。 客服平台刷新token接口当不不便随时去获取新token时,如果怕旧token生效,能够拿旧token调用此接口换取新token 惟一在线客服零碎 https://gofly.v1kf.com 十年开发教训程序员,到职全心守业中,历时三年开发出的产品《惟一客服零碎》

January 5, 2023 · 1 min · jiezi

关于go:网站客服系统源码中实现IP白名单机制基于Golang-Gin框架-网站网页在线客服系统源码

我的客服零碎有一些接口是专门给外部调用的,只容许其余外部零碎来调用,不容许随便拜访,能够应用IP白名单机制 应用 Gin 框架实现 IP 白名单机制能够应用中间件的形式实现。你能够编写一个中间件函数,在每个申请到来时查看它的 IP 地址是否在白名单中,如果不在,则返回错误信息。例如,你能够这样编写中间件函数: func IPWhiteList(whitelist []string) gin.HandlerFunc { return func(c *gin.Context) { // 获取申请的 IP 地址 ip := c.ClientIP() // 查看 IP 地址是否在白名单中 allowed := false for _, value := range whitelist { if value == ip { allowed = true break } } // 如果 IP 地址不在白名单中,则返回错误信息 if !allowed { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "IP address not allowed"}) return } // 容许申请持续拜访后续的处理函数 c.Next() }}而后,你能够将这个中间件函数增加到你的 Gin 路由器中,以便拦挡所有申请并进行 IP 白名单查看。例如,你能够这样应用中间件函数: ...

January 5, 2023 · 1 min · jiezi

关于go:在线客服系统源码编译保护Golang语言下go-build命令构建二进制程序-在线客服源码

我开发了一套在线客服零碎源码,应用了go build进行编译 go build 命令益处在我的在线客服零碎应用 go build 命令的次要益处是,它能够将 Go 程序编译成可执行文件,这样就能够将程序部署到生产环境中。 在生产环境中运行的程序通常是编译后的可执行文件,因为这样能够进步程序的执行效率,并且还能够将源代码暗藏起来,防止被别人查看或篡改。 另外,应用 go build 命令还能够在编译时对程序进行优化,以便在生产环境中进步程序的执行效率。 总之,应用 go build 命令能够使得在线客服零碎的 Go 程序更加高效、牢靠,并且更加适宜在生产环境中应用。 go build 命令解释go build 是一个用于构建 Go 包的命令。它会编译指定包中的 Go 源代码文件及其依赖项,并创立一个可执行二进制文件。go build 命令可用于为各种平台构建 Go 包,包含 Linux、macOS 和 Windows。 例如,如果你的零碎中有一个名为 mypackage 的 Go 包,你能够应用以下命令来构建它: go build mypackage 这将在同一目录中创立一个叫做 mypackage 的可执行二进制文件。你能够运行该二进制文件来执行 Go 程序。 除了构建 Go 包之外,go build 命令也能够用于构建位于当前工作目录中的 Go 程序。例如,如果你在当前目录中有一个名为 main.go 的 Go 文件,你能够应用以下命令来构建它: go build 这将在当前目录中创立一个名为 main 的可执行二进制文件。你能够运行该二进制文件来执行 Go 程序。 在应用 go build 命令时,能够应用 -o 参数来指定输入文件的名称。例如,如果你想要将 Go 包 mypackage 编译成可执行文件,并将其命名为 app,你能够应用以下命令: ...

January 5, 2023 · 1 min · jiezi

关于go:在线客服系统中配置邮箱消息通知提醒功能-在线客服系统源码

为在线客服零碎设置邮件告诉具备以下几个益处: 改善客户体验:邮件告诉能够让客户实时收到新音讯或更新告诉,这有助于进步他们对您的服务的整体体验。提高效率:邮件告诉能够帮忙进步客服团队的效率,因为它们会在新音讯和申请达到时立刻收到告诉,而不用一直查看更新。改善沟通:邮件告诉有助于改善客服团队和客户之间的沟通,因为它容许疾速不便地进行沟通。进步生产率:通过让客服团队在新音讯和申请达到时立刻收到告诉,邮件告诉能够帮忙进步生产率,因为他们可能更快地回复客户征询和申请。易于设置:邮件告诉绝对容易设置,能够轻松集成到大多数在线客服零碎中,无需太大致力。为在线客服系统配置邮件音讯告诉性能,您须要执行以下步骤: 配置邮件服务器或应用第三方邮件服务,如QQ邮箱,新浪邮箱,163邮箱,Gmail或Outlook。您须要有一个无效的电子邮件地址和拜访服务器设置的权限,能力实现这一步。设置在线客服零碎,以在特定事件产生时发送电子邮件告诉,例如收到新音讯或客户的申请已解决。这通常波及编写代码,以连贯到您的电子邮件服务器并发送必要的音讯。测试电子邮件告诉性能,确保它失常工作。您可能须要解决在此过程中呈现的任何问题。设置任何必要的安全措施,以爱护电子邮件通信的隐衷和平安。这可能包含应用安全套接字层(SSL)或传输层平安(TLS)加密,以及设置身份验证办法,如密码保护或双因素身份验证。商家账号设置咱们的惟一客服零碎(gofly.v1kf.com),每个商家都能够设置本人的告诉邮箱,及时获取到用户的音讯告诉 【设置】外面找到上面三个邮箱设置项,而后依据本人的邮箱服务商,去对应的邮箱服务商设置里找到配置信息,填写并保留 管理员设置管理员权限登录后,能够在【零碎设置】【配置参数】找到三个邮箱相干的设置项,这里是设置用户注册时须要发送验证码的邮箱 十年开发教训程序员,到职全心守业中,历时三年开发出的产品《惟一客服零碎》 演示官网 https://gofly.v1kf.com

January 5, 2023 · 1 min · jiezi

关于go:godongle-025-版本发布一个轻量级语义化的-golang-编码解码加密解密库

dongle 是一个轻量级、语义化、对开发者敌对的 Golang 编码解码和加密解密库 Dongle 已被 awesome-go 收录, 如果您感觉不错,请给个 star 吧 github.com/golang-module/dongle gitee.com/golang-module/dongle 更新日志 减少对 rsa 超长明文的私钥加密、公钥解密反对将 split() 更名为 bytesSplit() 并从 rsa.go 挪动到 dongle/rsa.go将 invalidRsaHashError 从 errors.go 挪动到 dongle/rsa.go降级 golang.org/x/crypto 版本到 v0.4.0修复备注谬误性能清单 [x] Hex 编码、解码[x] Base16 编码、解码[x] Base32 编码、解码[x] Base45 编码、解码[x] Base58 编码、解码[x] Base62 编码、解码[x] Base64 编码、解码[x] Base64URL 编码、解码[x] SafeURL 编码、解码[x] Base85 编码、解码[x] Base91 编码、解码[x] Base100 编码、解码[x] Morse(摩斯) 编码、解码[x] Md2 加密[x] Md4 加密[x] Md5 加密[x] Sha1 加密[x] Sha3-224 加密[x] Sha3-256 加密[x] Sha3-384 加密[x] Sha3-512 加密[x] Sha224 加密[x] Sha256 加密[x] Sha384 加密[x] Sha512 加密[x] Sha512-224 加密[x] Sha512-256 加密[x] Shake128 加密[x] Shake256 加密[x] Ripemd160 加密[x] Blake2b-256 加密[x] Blake2b-384 加密[x] Blake2b-512 加密[x] Blake2s-256 加密[x] Hmac-md2 加密[x] Hmac-md4 加密[x] Hmac-md5 加密[x] Hmac-sha1 加密[x] Hmac-sha3-224 加密[x] Hmac-sha3-256 加密[x] Hmac-sha3-384 加密[x] Hmac-sha3-512 加密[x] Hmac-sha224 加密[x] Hmac-sha256 加密[x] Hmac-sha384 加密[x] Hmac-sha512 加密[x] Hmac-sha512-224 加密[x] Hmac-sha512-256 加密[x] Hmac-ripemd160 加密[x] Hmac-sm3 加密[ ] Rc2 加密、解密[x] Rc4 加密、解密[ ] Rc5 加密、解密[ ] Rc6 加密、解密[x] Tea 加密、解密[ ] Xtea 加密、解密[x] Aes 加密、解密[x] Blowfish 加密、解密[x] Des 加密、解密[x] 3Des 加密、解密[x] Rsa 加密、解密[ ] Ecc 加密、解密[ ] Sm2 加密、解密[x] Sm3 加密[ ] Sm4 加密、解密[ ] Sm7 加密、解密[ ] Sm9 加密、解密[x] Bcrypt 签名、验签[x] Ed25519 签名、验签[x] Rsa 签名、验签[ ] Dsa 签名、验签

January 5, 2023 · 1 min · jiezi

关于go:Go实现LRU-Cache

在web程序开发中,个别会应用redis作为数据缓存缓存一些罕用的数据。然而有时候,当访问量特地微小的时候,redis也不肯定能抵御这么大的流量的时候,个别会将罕用的数据放入内存中,避难频繁拜访redis。 因为内存的资源绝对比拟低廉,咱们须要对放入内存中的数据做一些限度以及将一些不罕用的数据清理进来。这个时候就须要用到LRU算法(Least recently used,最近起码应用)。 LSU cache是一种常见的缓存置换算法。会依据缓存拜访的频繁水平,将不罕用的缓存逐步淘汰掉,以开释内存资源。 在go语言中,利用自带的list双向链表能够实现相干算法性能,以下为代码示例 package lru_cacheimport ( "container/list" "sync")type Lrc struct { size int list *list.List cacheMap map[string]*list.Element lock sync.RWMutex}type data struct { key string value interface{}}func NewLrc(size int) *Lrc { return &Lrc{ size: size, list: list.New(), cacheMap: make(map[string]*list.Element), }}// Set 写入缓存func (l *Lrc) Set(key string, value interface{}) { l.lock.Lock() defer l.lock.Unlock() // 判断是否曾经存在 if elem, ok := l.cacheMap[key]; ok { l.list.MoveToFront(elem) elem.Value.(*data).value = value return } item := &data{ key: key, value: value, } elem := l.list.PushFront(item) l.cacheMap[key] = elem // 判断是否超过长度限度 if l.list.Len() > l.size && l.size > 0 { deleteItem := l.list.Back() l.list.Remove(deleteItem) deleteKey := deleteItem.Value.(*data).key delete(l.cacheMap, deleteKey) }}// Get 读取缓存func (l *Lrc) Get(key string) (interface{}, bool) { l.lock.RLock() value, ok := l.cacheMap[key] l.lock.RUnlock() if ok { l.lock.Lock() l.list.MoveToFront(value) l.lock.Unlock() return value.Value.(*data).value, true } else { return nil, false }}// Delete 缓存func (l *Lrc) Delete(key string) { l.lock.RLock() value, ok := l.cacheMap[key] l.lock.RUnlock() if ok { l.lock.Lock() l.list.Remove(value) key := value.Value.(*data).key delete(l.cacheMap, key) l.lock.Unlock() }}github ...

January 4, 2023 · 1 min · jiezi

关于go:unsupported-relations-for-schema

预加载Preload()的参数是构造体的字段名称,而不是表名,如果写成了表名就会报unsupported relations for schema谬误。 type User struct { gorm.Model Username string Orders []Order}type Order struct { gorm.Model UserID uint Price float64}// 查找 user 时预加载相干 Orderdb.Preload("Orders").Find(&users)// SELECT * FROM users;// SELECT * FROM orders WHERE user_id IN (1,2,3,4);

January 4, 2023 · 1 min · jiezi

关于go:2023年了-对Go做一个全网最全的总结

转眼之间,又到了2023,2022仿佛比今年过得更快一些。这一年经验3-6月的上海封城、经验了8月的找工作、经验了公司的一直裁员、经验一直地核酸、经验了疫情的全民放开和经验了你阳了吗等等,这一年大家的生存如同都过得挺蹩脚的。可面对这些,大家又是无能为力,面对各种内卷、面对各种裁员、面对疫情对生存带来的压力。看着眼前蹩脚的环境,咱们惟一能做的就是尽可能的努力学习,晋升本人。 面对这一年的各种窘境,集体也开始明确了本人的职业规划,也开始被动去接触新的常识,去结交新的圈子。在这个过程中,才真正的意识到本人的认知是如许的狭小,感觉本人像一个井底之蛙一样。从工作上,这一年最大的播种就是有了一个属于本人的业务我的项目,并继续为之打磨,尽管在这个过程中很累,但很侥幸本人始终在保持。在生活中,尽管好几年没回家一次,但仍能时刻感触到家里的和煦;同时在这一年中,也遇到了另外一伴。 写这篇文章也不是为了吐槽2022年是如许的蹩脚,也不是为2023年立flag。只能说算是一个简略的总结吧。也心愿2023年可能持续放弃2022年的一种良好的心态,一直地致力、一直地晋升本人。上面的内容就是在2022年之间,集体接触到的一些不错的学习材料,外面有一些视频教程、学习文档、开源软件等等内容,也心愿我的总结能帮忙到你们。好了,开始介绍注释吧。大抵分为如下的提纲。这篇文章次要是分享编程文档和视频。会继续更新其余的内容。本文具体的收录地址 2022年文档在2022年工作上也很忙,同时也始终在做学习总结,根本没写什么文档。这里也汇总一下写过的文章。 思维导图Redis常问面试题汇总 MySQL学习纲要 MySQL150道面试题总结 文章汇总为什么说Go字符串不能批改Golang中的代码分层设计实际与总结实用于疾速开发利用的Golang二次框架MySQL一个200G的大表 该如何优化SQL查问操作MySQL一个200G的大表 该如何优化SQL查问操作分布式日志存储架构设计计划分布式日志存储架构代码实际聊聊Redis热点key缓存问题如何解决如何在Go中操作Redis服务Golang中slice和map并发写入问题解决Redis Stream实现音讯队列中间件齐全弄懂Redis各种业务场景下的应用应用Golang操作Redis的Steam实现高可用MQ服务为什么举荐MySQL不应用join查问熬夜爆肝整顿的elasticsearch中文手册文档Go开发微信小程序SDK举荐Go中struct初始化内存布局状况初学Go 值得深研的7大开源我的项目2022年最适宜编程的 6 种字体Go语言 参数传递到底是值传递还是援用传递Go语言 参数传递到底是值传递还是援用传递Go中的谬误和异样解决最佳实际应用Go设计多缓存驱动Redis大厂面试题总结(2022最新版 附答案)如何剖析Golang依赖包的各项指标能力10分钟学会Go构造体类型20分钟学会数组与切片搭建了一套电子图书零碎 快来看看谷歌都在用的监控软件,到底长什么样实战—Go程序剖析利器pprof一篇文章疾速了解微服务架构Go实现工厂模式微服务下的网关如何抉择如何了解 Go函数是一等公民Go办法 为什么举荐 应用指针类型的接收者有哪些方法能够升高 Redis 的内存应用状况Git-Flow 的工作流程最全面应用总结应用 Go + HTML + CSS + JS 构建丑陋的跨平台桌面利用应用Go开源的一款性能监控软件面试大厂 看这篇MySQL面试题就够了linux、数据库、redis、mongo对立治理操作平台你应该晓得的17个Golang包重新整理一波Go学习材料学习文档往年次要的重心是在Golang这门编程语言上,但也不不足对其余的常识学习。或多或少也会介绍到其余相干的文档。 开发文档Go官网开发文档:所有的编程文档,集体都举荐首看官网文档。如果你学习Go,首推官网教程。根本你把官网教程读一遍,能对Go这门编程语言有一个全面的意识。Go中文网:下面提到的官网文档,可能对于英语差一点的开发者来说,有肯定的难度。那么举荐你应用Go中文网。Go中文网的创建曾经有多年,下面的很多技术帖子都蛮不错的。同时有Go官网包和官网文档的中文版,可能很好的解决你的英语水平。C语言中文网:尽管通过名称,看上去是专门学习C的。实则该网站是专门做文档教程。外面有很多高质量的编程语言教程、例如JavaScript、C、C++、Python、JavaScript等支流的编程语言。如果你没找到好一个文档教程网站,比拟举荐你应用这个网站。不过外面的有些文档须要会员才行,站长如同是全职在负责这个网站的经营,毕竟人家也要生存。地鼠文档:地鼠文档是一个专做Go语言文档教程的网站。外面的文档教程,能够说是蕴含了所有Go支流的教程,珍藏了很多 Go 学习材料。包含网站,书籍,开源库,开源我的项目等。能够作为Go学习的一手材料。Go夜读:这是一个由泛滥资深 Gopher 组织的开源我的项目,次要是对Go源码进行解读。并且保持开源,将相干资源都上传到了GitHub。如果你对Go有所理解之后,这是一个深刻学习Go的站点。小林coding:举荐该博客的次要起因是,博主讲所有一些艰涩、难懂的技术文档都通过图解+文字的形式进行分享,讲素日干燥的技术更加活泼、形象的展现。外面的内容蕴含了计算机网络、操作系统、计算机组成、数据库、编程语言等相干内容。是十分举荐大家学习的一个博客。mojotv 博客:外面很多 Go进阶文章,还有其余方面(docker、rust、Linux)的技术文章。如果你学完Go的根底语法,想进行一些进阶晋升,是十分举荐的一个技术博客。煎鱼博客:置信学Go的开发来说,煎鱼大佬大家曾经不生疏。煎鱼是<<Go 语言设计哲学>>一书的作者,同时他集体也有本人的公众号,不定期的分享一些对于Go的面试题或者一些有价值的问题。如果你想继续学习Go,但也没有太多的工夫去实际一些问题。十分举荐关注。Go语言设计与实现:这个博客乃是左神大佬编写。外面的技术文档不仅仅波及到Go的基础知识,更多的对底层原理、源码等方面的剖析。例如并发编程、编译原理、内存治理等等深度内容的分析。要想进阶Go语言,强烈推荐学习。Go系列教程:如果你在学习Go的过程中,遇到教程文档太过于啰嗦,想找一个疾速入门的教程,十分举荐你看该教程。该教程内容波及到Go入门必会的知识点总结,没有过多的理论知识,间接都是根底语法实操。Go 语言高性能编程:该博客尽管内容不对,但也蕴含了几个Go热门问题的分享总结。想要对Go性能晋升学习的,比拟举荐看看该教程文档。Redis设计与实现:该书全面而残缺地解说了 Redis 的外部运行机制, 对 Redis 的大多数单机性能以及所有多机性能的实现原理进行了介绍, 展现了这些性能的外围数据结构以及要害的算法思维。 通过浏览本书, 读者能够疾速、无效地理解 Redis 的外部结构以及运作机制, 从而学会如何更高效地应用 Redis 。13.Go 程序员面试口试宝典:该书针对国内互联网企业对Go的面试题做了一些汇总,从代码演示、源码剖析等方面剖析Go外部的底层原理。不仅仅能够应酬面试题,也是深刻学习Go的不错书籍。 设计模式:该站点内容是针对编程设计模式的实践与代码实际。其中的代码示例是至今见过最全的书籍,每一个设计模式都有对应的实践+代码编写,同时也反对多语言,有C、C++、JavaScript、PHP、Go、Java、Python等编程语言。如果要学习设计模式,这相对是你的最佳抉择。下面的一些站点,均是集体在2022年内接触过,局部站点也深刻浏览过的教程。十分举荐大家浏览下面的一些教程。对于文档类的教程也给大家总结到这里了,其实有更多的教程还未总结进去,后续也会一直地更新。同时大家有什么好的材料、教程也欢送反馈总结。学习视频随着对编程技术的深刻理解,集体也开始偏差浏览文档类型的教程。对于视频教程就较少的观看。这里还是汇总几个认为不错的资源举荐给大家。 B站最深度的Golang学习到实战:对于通过文档学习Go开发,你会感觉枯燥乏味,举荐你看这个视频教程。该视频教程不仅仅是教Go根底语法常识,还会波及到计算机操作系统,Go底层原理等相干常识,不仅有示例代码还有十分深刻的图形解说。Golang网络编程实战:Go这门编程语言,从根底语法来说,对于有编程教训的开发者来说很简略。但深刻学习之后,你会发现须要把握的基础知识太多了,尤其是操作系统、计算机原理、网络等相干的内容。该视频就是针对网络编程做的一个分享,内容品质也十分地高。特地适宜想对网络编程深刻学的开发者。Golang深刻了解GPM模型:Go语言如此之火,次要是得益于其并发能力,其并发能力的集中体现在协程上。因而很多时候,协程原理成为面试必问,如果你想对协程相干常识的理解,这应该是最值得举荐的一个教程。计算机编译原理:因为在学习Go的过程中,须要波及到一些计算机编译的常识,便找到这样的一个课程。该课程来自哈尔滨理工大学出品,内容视频简略易懂,十分举荐学习。计算机网络:在学习Go的过程中,发现还须要对计算机网络有所理解,便找到了这样的一门课程。该课程是计算机网络编程作者韩立刚老师授课,内容品质必定是相当高的。

January 2, 2023 · 1 min · jiezi

关于go:需要提醒你关于-golang-中-map-使用的几点注意事项

日常的开发工作中,map 这个数据结构置信大家并不生疏,在 golang 外面,当然也有 map 这种类型 对于 map 的应用,还是有蛮多注意事项的,如果不分明,这些事项,要害时候可能会踩坑,咱们一起来演练一下吧 1 应用 map 记得初始化写一个 demo 定义一个 map[int]int 类型的变量 myMap , 不做初始化咱们能够读取 myMap 的值,默认为 零值然而咱们往没有初始化的 myMap 中写入值,程序就会 panic ,这里切记不要踩坑func main(){ var myMap map[int]int fmt.Println("myMap[1] == ",myMap[1])}程序运行成果: # go run main.gomyMap[1] == 0代码中退出写操作: func main(){ var myMap map[int]int fmt.Println("myMap[1] == ",myMap[1]) myMap[1] = 10 fmt.Println("myMap[1] == ",myMap[1])}程序运行成果: # go run main.gomyMap[1] == 0panic: assignment to entry in nil mapgoroutine 1 [running]:main.main() /home/admin/golang_study/later_learning/map_test/main.go:20 +0xf3exit status 2程序果然报 panic 了,咱们理论工作中须要万分小心,对代码要有敬畏之心 ...

January 2, 2023 · 3 min · jiezi

关于go:GoIrisWeb编程一

HTTPHTTP是一种无状态协定(connection-less protocol)通过这种协定发送给服务器的申请对服务器之前解决过的申请无所不知 好的框架通常是疾速构建可扩大且强壮的Web利用的最好办法,但了解暗藏在框架之下的底层概念和基础设施也是十分重要的 对于Go来说,暗藏在框架之下的通常是net/http、html/template两个规范库 HTTP报文是在客户端和服务端之间传递的音讯,分为HTTP申请和HTTP响应 报文构造1.申请行或者响应行2.零个或多个首部3.一个空行4.一个可选的报文主体Request构造 URL字段 用于示意申请行中蕴含的URL,指向url.URL构造的指针 type URL struct { Scheme string Opaque string User *Userinfo Host string Path string RawQuery string Fragment string }URL的个别格局:scheme://[userinfo@]host/path[?query][#Fragment]Header字段Body字段Form字段、PostForm字段和MultipartForm字段net/httpnet/http规范库能够分为客户端与服务端两个局部

December 31, 2022 · 1 min · jiezi

关于go:Go渗透测试编程三TCP扫描器和代理续

通过上述的流程,咱们就能够简略了解示例程序了 func main() { // 在所有接口上绑定TCP端口20080,启动监听服务 listener, err := net.Listen("tcp", ":20080") // 判断监听服务是否启动,否则抛出异样 if err != nil { log.Fatalln("Unable to Bind to port") } // 打印语句,胜利监听 log.Println("Listening on localhost:20080") // 有限循环,期待客户端进行连贯 for { // 期待连贯,创立与返回net.Conn conn, err := listener.Accpet() log.Println("Reveived connection") if err != nil { log.Fatalln("Unable to accept connection") } // 解决连贯,应用goroutine实现并发 go handle(conn) }}代理TCP客户端func handle(src net.Conn) { dst, err := net.Dial("tcp", "targethost:80") if err != nil { log.Fatalln("Unable to connect to host") } defer dst.Close() go func() { // 将源的输入复制到指标 // io.Copy(dst Writer, src Reader) // 将Reader读取到的数据复制到Writer if _, err := io.Copy(dst, src); err != nil { log.Fatalln(err) } }() // 将指标的输入复制回源 if _, err := io.Copy(src, dst); err != nil{ log.Fatalln(err) }}复现Netcat命令执行Netcat,命令行网络工具,用来在两台机器之间建设TCP/UDP连贯,相比Telnet更灵便且能够编写脚本 ...

December 31, 2022 · 1 min · jiezi

关于go:GO语言初始化数据结构的方法你知道吗

xdm 我是阿兵云原生 应用 golang 进行编码过程中,你们都是如何初始化数据结构的呢 GO 外面提供了 2 个关键字来进行初始化数据结构 newmake不过有时候我也会间接应用花括号的形式间接就初始化,例如这样: name := []string{"xiaomotong","bob","marry"}下面这种状况,是初始化的时候曾经明确好了须要填的值,能够应用下面这种做法,不过工作中大多数状况初始化的时候,数据还是未知的,大部分工夫还是会应用上述两种形式 makemake 是 golang 提供的关键字,次要是用于初始化内置的数据结构,不能初始化自定义的数据结构 , make 能够初始化的数据类型有: slice 切片map hash表channel 通道例如咱们初始化的时候就能够这样写 初始化一个切片,填入 len 值, cap 值,切片底层的数据结构除了这俩值以外,还有一个指针,指向的是一个底层数组初始化一个 map,map 的底层是指向一个 hmap 的构造体指针,构造体外面的具体成员感兴趣的 xdm 能够翻看我的历史文章初始化一个通道 ch,这个 ch 是指向一个 hchan 的构造体指针,同样也可翻看我的历史文章看细节strs := make([]string, 0, 10)myMap := make(map[string]string, 10)ch := make(chan struct{}, 10)咱们查看 make 的源码解释能够看到,make 的确反对创立和初始上述 3 种类型 依据解释,咱们晓得,make 的返回值的类型与填入参数的类型保持一致,咱们填入的是切片类型,那么返回值就是切片类型,填入其余类型对应返回值也是咱们冀望的类型,没故障 new那么为什么有了 make 做数据结构的初始化,还须要 new 干啥? 仔细的 胖鱼 能够看进去,后面说到了 make 只实用于初始化 golang 提供的内置数据结构,对于自定义的数据结构,就顾此失彼了 , 这个时候还是须要 new 出马摆平了 ...

December 31, 2022 · 1 min · jiezi

关于go:Go-120要来了看看都有哪些变化第4篇

Go 1.20要来了,看看都有哪些变动-第4篇前言Go官网团队在2022.12.08公布了Go 1.20 rc1(release candidate)版本,Go 1.20的正式release版本预计会在2023年2月份公布。 让咱们先睹为快,看看Go 1.20给咱们带来了哪些变动。 装置办法: $ go install golang.org/dl/go1.20rc1@latest$ go1.20rc1 download这是Go 1.20版本更新内容详解的第4篇,欢送大家关注公众号,及时获取本系列最新更新。 Go 1.20公布清单和Go 1.19相比,改变内容适中,次要波及语言(Language)、可移植性(Ports)、工具链(Go Tools)、运行时(Runtime)、编译器(Compiler)、汇编器(Assembler)、链接器(Linker)和外围库(Core library)等方面的优化。 第1篇次要波及Go 1.20在语言、可移植性方面的优化,原文链接:Go 1.20版本升级内容第1篇。 第2篇次要波及Go命令和工具链方面的优化,原文链接:Go 1.20版本升级内容第2篇。 第3篇次要波及Go在运行时、编译器、汇编器、链接器等方面的优化,原文链接:Go 1.20版本升级内容第3篇。 本文重点介绍Go 1.20在外围库方面的优化。 crypto/ecdhGo 1.20新增了 crypto/ecdh 这个package,ecdh实现了Elliptic Curve Diffie-Hellman这个新的加密算法。 封装多个errorGo 1.20容许一个error变量里封装多个error。 package mainimport ( "errors" "fmt")func main() { err1 := errors.New("err1") err2 := errors.New("err2") err := errors.Join(err1, err2) fmt.Printf("%T, %v\n", err, err) if errors.Is(err, err1) { fmt.Println("err is err1") } if errors.Is(err, err2) { fmt.Println("err is err2") } err3 := fmt.Errorf("error3: %w", err) fmt.Printf("%T, %v\n", err3, errors.Unwrap(err3)) if errors.Is(err3, err1) { fmt.Println("err3 is err1") } if errors.Is(err3, err2) { fmt.Println("err3 is err2") }}这段程序的输入后果为: ...

December 31, 2022 · 2 min · jiezi

关于go:Go-快速入门指南-正则表达式

概述调用 regexp 包即可。 例子是否匹配package mainimport ( "fmt" "regexp")func main() { match, err := regexp.MatchString("h[a-z]+.*d$", "hello world") if err != nil { panic(err) } fmt.Println(match) match, err = regexp.MatchString("h[a-z]+.*d$", "ello world") if err != nil { panic(err) } fmt.Println(match)}// $ go run main.go// 输入如下/** true false*/匹配所有子字符串package mainimport ( "fmt" "regexp")func main() { c, err := regexp.Compile("h[a-z]") if err != nil { panic(err) } res := c.FindAllString("hello world", -1) fmt.Printf("res = %v\n", res) res2 := c.FindAllString("hello world hi ha h1", -1) fmt.Printf("res2 = %v\n", res2)}// $ go run main.go// 输入如下/** res = [he] res2 = [he hi ha]*/替换所有子字符串package mainimport ( "fmt" "regexp")func main() { c, err := regexp.Compile("h[a-z]") if err != nil { panic(err) } res := c.ReplaceAll([]byte("hello world"), []byte("?")) fmt.Printf("res = %s\n", res) res2 := c.ReplaceAll([]byte("hello world hi ha h1"), []byte("?")) fmt.Printf("res2 = %s\n", res2)}// $ go run main.go// 输入如下/** res = ?llo world res2 = ?llo world ? ? h1*/匹配中文package mainimport ( "fmt" "regexp")func main() { match, err := regexp.MatchString("\\x{4e00}-\\x{9fa5}", "hello world") if err != nil { panic(err) } fmt.Println(match) match, err = regexp.MatchString("\\p{Han}+", "hello 世界") if err != nil { panic(err) } fmt.Println(match)}// $ go run main.go// 输入如下/** false true*/分割我 ...

December 30, 2022 · 1 min · jiezi

关于go:Go-快速入门指南-随机数

概述调用 rand 包 即可,重要的一点是每次生成随机数之前,都设置随机数生成种子,否则可能每次生成的随机数都一样。 例子随机生成数字package mainimport ( "fmt" "math/rand" "time")func main() { rand.Seed(time.Now().UnixNano()) // 以以后工夫的纳秒单位为种子 for i := 0; i < 5; i++ { fmt.Println(rand.Int()) }}// $ go run main.go// 输入如下, 你的输入应该和这里的不一样/** 6322308781580164811 8102638055079193560 8689011158917073467 6408490946268327546 2346011052422006168*/随机生成指定区间数字package mainimport ( "fmt" "math/rand" "time")func main() { s := rand.NewSource(time.Now().UnixNano()) // 以以后工夫的纳秒单位为种子 r := rand.New(s) for i := 0; i < 5; i++ { fmt.Println(r.Intn(10)) }}// $ go run main.go// 输入如下, 你的输入应该和这里的不一样/** 5 9 7 1 3*/分割我 ...

December 30, 2022 · 1 min · jiezi

关于go:Go-快速入门指南-日期和时间

概述Go 中和工夫相干的操作全副在 time 包。 语法规定调用 time 包即可,重要的一点是: 不管将工夫格式化为字符串,还是将字符串解析为工夫,用到的工夫参数固定为 2006-01-02 15:04:05 (至于为什么硬编码为这个工夫,感兴趣的读者能够看看扩大浏览上面的文章),而不是随便的工夫参数,比方 2018-08-08 18:28:38。 例子工夫格式化package mainimport ( "fmt" "time")func main() { now := time.Now() fmt.Println(now.Format("2006-01-02 15:04:05")) fmt.Println(now.Format("2006年01月02日 15时04分05秒"))}// $ go run main.go// 输入如下, 你的输入应该和这里的不一样/** 2021-11-03 21:01:04 2021年11月03日 21时01分04秒*/字符串解析为工夫package mainimport ( "fmt" "time")func main() { s := `2021-11-03 21:01:04` t, err := time.Parse("2006-01-02 15:04:05", s) if err != nil { panic(err) } fmt.Println(t.Format("2006-01-02 15:04:05")) fmt.Println(t.Format("2006年01月02日 15时04分05秒"))}// $ go run main.go// 输入如下/** 2021-11-03 21:01:04 2021年11月03日 21时01分04秒*/获取年月日时分秒等属性package mainimport ( "fmt" "time")func main() { now := time.Now() fmt.Println(now.Year()) fmt.Printf("%d\n", now.Month()) fmt.Println(now.Day()) fmt.Println(now.Hour()) fmt.Println(now.Minute()) fmt.Println(now.Second())}// $ go run main.go// 输入如下, 你的输入应该和这里的不一样/** 2021 11 3 21 20 7*/工夫加减package mainimport ( "fmt" "time")func main() { now := time.Now() afterHour := now.Add(time.Hour) // 以后工夫加 1 个小时 fmt.Println(afterHour.Format("2006-01-02 15:04:05")) beforeHour := now.Add(-time.Hour) // 以后工夫减 1 个小时 fmt.Println(beforeHour.Format("2006-01-02 15:04:05"))}// $ go run main.go// 输入如下, 你的输入应该和这里的不一样/** After a hour: 2021-11-03 21:36:17 Before a hour: 2021-11-03 20:36:17 After a year: 2022-11-03 21:40:43 Before a year: 2020-11-03 21:40:43*/工夫比拟package mainimport ( "fmt" "time")func main() { now := time.Now() afterHour := now.Add(time.Hour) // 以后工夫加 1 个小时 fmt.Printf("afterHour after now = %t\n", afterHour.After(now)) beforeHour := now.Add(-time.Hour) // 以后工夫减 1 个小时 fmt.Printf("beforeHour before now = %t\n", beforeHour.After(now))}// $ go run main.go// 输入如下/** afterHour after now = true beforeHour before now = false*/获取/解析 工夫戳package mainimport ( "fmt" "time")func main() { now := time.Now() fmt.Println(now.Unix()) // 单位: 秒 fmt.Println(now.UnixMilli()) // 单位: 毫秒 fmt.Println(now.UnixMicro()) // 单位: 奥妙 fmt.Println(now.UnixNano()) // 单位: 纳秒 var timestamp int64 = 1557433059 t := time.Unix(timestamp, 0) fmt.Println(t.Format("2006-01-02 15:04:05"))}// $ go run main.go// 输入如下,你的输入可能和这里的不一样/** 1667433164 1667433164630 1667433164630949 1667433164630949000 2019-05-10 04:17:39*/扩大浏览https://www.jianshu.com/p/c7f...https://jishuin.proginn.com/p...分割我 ...

December 30, 2022 · 2 min · jiezi

关于go:Go-快速入门指南-XML

概述encoding/xml 蕴含了 XML 相干解决办法。 例子构造体转为 XML 字符串调用 xml.Marshal() 办法实现。 package mainimport ( "encoding/xml" "fmt")type person struct { Name string `xml:"name"` Age int `xml:"age"` addr string `xml:"addr"` // 该属性转 XML 时会被疏忽}func main() { tom := person{ // 应用字面量初始化 Name: "Tom", Age: 6, addr: "???", } tomXml, err := xml.Marshal(tom) if err != nil { panic(err) } fmt.Printf("xml.Marshal(tom) = %s\n", tomXml) // 从输入字符串中能够看到,并没有 addr 属性}// $ go run main.go// 输入如下 /** xml.Marshal(tom) = <person><name>Tom</name><age>6</age></person>*/XML 字符串转为构造体调用 xml.Unmarshal() 办法实现。 ...

December 30, 2022 · 2 min · jiezi

关于go:Go-快速入门指南-JSON

概述encoding/json 蕴含了 JSON 相干解决办法。 例子构造体转为 JSON 字符串调用 json.Marshal() 办法实现。 package mainimport ( "encoding/json" "fmt")type person struct { Name string `json:"name"` Age int `json:"age"` addr string `json:"addr"` // 该属性转 JSON 时会被疏忽}func main() { tom := person{ // 应用字面量初始化 Name: "Tom", Age: 6, addr: "???", } tomJson, err := json.Marshal(tom) if err != nil { panic(err) } fmt.Printf("json.Marshal(tom) = %s\n", tomJson) // 从输入字符串中能够看到,并没有 addr 属性}// $ go run main.go// 输入如下 /** json.Marshal(tom) = {"name":"Tom","age":6}*/JSON 字符串转为构造体调用 json.Unmarshal() 办法实现。 ...

December 30, 2022 · 3 min · jiezi

关于go:Go-快速入门指南-命令行参数

命令行参数个数调用 os 包即可。 获取参数个数, 遍历参数package mainimport ( "fmt" "os")func main() { fmt.Printf("Number of args is %d\n\n", len(os.Args)) for _, arg := range os.Args { fmt.Println(arg) }}// $ go build main.go// $ ./main -a -b --c -d// 输入如下 /** Number of args is 5 ./main -a -b --c -d*/命令行参数解析和设置调用 flag 包即可。 例子设置参数package mainimport ( "flag" "fmt")var ( name = flag.String("name", "Tom", "Please input your name:") // 默认值 Tom age = flag.Int("age", 6, "Please input your age:") // 默认值 6 hasMoney = flag.Bool("hasMoney", true, "Do you have any money?") // 默认值 true)func main() { flag.PrintDefaults() // 打印参数提示信息 flag.Parse() fmt.Printf("name is %s\n", *name) fmt.Printf("name is %d\n", *age) fmt.Printf("name is %t\n", *hasMoney)}// 默认参数// $ go run main.go// 输入如下 /** -age int Please input your age: (default 6) -hasMoney Do you have any money? (default true) -name string Please input your name: (default "Tom") name is Tom name is 6 name is true*/// 设置参数// $ go run main.go -name=Jerry -age=8 -hasMoney=false// 输入如下 /** -age int Please input your age: (default 6) -hasMoney Do you have any money? (default true) -name string Please input your name: (default "Tom") name is Jerry name is 8 name is false*/分割我 ...

December 30, 2022 · 1 min · jiezi

关于go:Go-快速入门指南-进程常用方法

exit调用 os 包,自定义 status code。 例子package mainimport "os"func main() { os.Exit(3) println("exiting ...") // 不会执行到这里}// $ go run main.go// 输入如下 /** exit status 3*/过程 id调用 os 包即可。 例子package mainimport ( "fmt" "os")func main() { fmt.Printf("Process ID = %d\n", os.Getpid()) fmt.Printf("Parent process ID = %d\n", os.Getppid())}// $ go run main.go// 输入如下,你的输入可能和这里的不一样/** Process ID = 13962 Parent process ID = 13860*/信号调用 os/signal 包即可。 例子package mainimport ( "fmt" "os" "os/signal")func main() { c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) fmt.Println("程序执行中... 按 Ctrl + C 终止执行") <-c // 期待信号被触发 fmt.Println("程序执行终止")}// $ go run main.go// 输入如下 /** 程序执行中... 按 Ctrl + C 终止执行 ^C程序执行终止*/限度SIGKILL 信号 和 SIGSTOP 信号无奈被捕捉,这是内核的限度, 目标是为了让操作系统管制过程的生命周期。 ...

December 30, 2022 · 1 min · jiezi

关于go:Go-快速入门指南-常用加解密方法

base64调用 encoding/base64 包即可。 例子package mainimport ( "encoding/base64" "fmt")func main() { s := "hello world" sEncode := base64.StdEncoding.EncodeToString([]byte(s)) fmt.Printf("encode(`hello world`) = %s\n", sEncode) sDecode, err := base64.StdEncoding.DecodeString(sEncode) if err != nil { panic(err) } else { fmt.Printf("decode(`%s`) = %s\n", sEncode, sDecode) }}// $ go run main.go// 输入如下/** encode(`hello world`) = aGVsbG8gd29ybGQ= decode(`aGVsbG8gd29ybGQ=`) = hello world*/sha256调用 crypto/sha256 包即可。 例子package mainimport ( "crypto/sha256" "fmt")func main() { s := "hello world" h := sha256.New() h.Write([]byte(s)) res := h.Sum(nil) fmt.Printf("sha245(`hello world`) = %x\n", res)}// $ go run main.go// 输入如下/** sha256(`hello world`) = b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9*/md5调用 crypto/md5 包即可。 ...

December 30, 2022 · 1 min · jiezi

关于go:Go-快速入门指南-URL

概述调用 net/url 包即可。 例子结构 URLpackage mainimport ( "fmt" "net/url")func main() { u := url.URL{} u.Scheme = "https" u.Host = "go.dev" u.Path = "/learn/doc" values := u.Query() values.Add("hello", "world") u.RawQuery = values.Encode() fmt.Printf("URL = %s\n", u.String())}// $ go run main.go// 输入如下/** URL = https://go.dev/learn/doc?hello=world*/解析 URLpackage mainimport ( "fmt" "net/url")func main() { s := "https://golang.org" u, err := url.Parse(s) if err != nil { panic(err) } fmt.Println(u.Scheme) fmt.Println(u.Host)}// $ go run main.go// 输入如下/** https golang.org*/解析 URL (带参数)package mainimport ( "fmt" "net/url")func main() { s := "https://go.dev/learn/doc?hello=world" u, err := url.Parse(s) if err != nil { panic(err) } fmt.Println(u.Scheme) fmt.Println(u.Host) fmt.Println(u.Path) fmt.Printf("Param hello = %s\n", u.Query().Get("hello"))}// $ go run main.go// 输入如下/** https go.dev /learn/doc Param hello = world*/分割我 ...

December 30, 2022 · 1 min · jiezi

关于go:Go-快速入门指南-HTTP

概述net/http 蕴含了 HTTP 相干办法。 例子package mainimport ( "errors" "fmt" "io" "net/http")func main() { resp, err := http.Get("https://www.baidu.com") if err != nil { panic(err) } defer func() { err = resp.Body.Close() if err != nil { fmt.Printf("resp.Body.Close() %s", err) } }() fmt.Printf("Response status code = %d\n", resp.StatusCode) fmt.Printf("Response content type = %s\n", resp.Header.Get("Content-Type")) fmt.Printf("Response content length = %d\n", resp.ContentLength) body := make([]byte, resp.ContentLength) n, err := resp.Body.Read(body) if err != nil && !errors.Is(err, io.EOF) { panic(err) } fmt.Printf("Response body read = %d\n", n) fmt.Printf("Response body = %s\n", body)}// $ go run main.go// 输入如下/** Response status code = 200 Response content type = text/html Response content length = 227 Response body read = 227 Response body = <html> <head> <script> location.replace(location.href.replace("https://","http://")); </script> </head> <body> <noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript> </body> </html>*/分割我 ...

December 30, 2022 · 1 min · jiezi

关于go:你可能还不知道-golang-的高效编码细节

xdm,咱们都晓得 golang 是天生的高并发,高效的编译型语言 可咱们也都可晓得,工具再好,用法不对,全都徒劳,咱们来举 2 个罕用门路来感受一下 struct 和 map 用谁呢?计算量很小的时候,可能看不出应用 长期 struct 和 map 的耗时差距,然而数量起来了,差距就显著了,且会随着数量越大,差距越发显著 当咱们遇到键和值都能够是固定的时候,咱们抉择 struct 比 抉择 map 的形式 高效多了 咱们模仿循环计算 1 亿 次,看看应用各自的数据结构会耗时多少循环前计算一下以后工夫循环后计算一下以后工夫最初计算两个工夫的差值,此处咱们应用 毫秒为单位func main() { t1 :=time.Now().UnixNano()/1e6 for i := 0; i < 100000000; i++ { var test struct { Name string hobby string } test.Name = "xiaomotong" test.hobby = "program" } t2 :=time.Now().UnixNano()/1e6 fmt.Println("t2 - t1 == ", t2-t1)}程序运行查看成果: # go run main.got1 == 1634377149185t2 == 1634377149221t2 - t1 == 36应用 struct 的形式,耗时 36 ms ,大家感觉这个工夫如何? ...

December 30, 2022 · 3 min · jiezi

关于go:godongle-024-版本发布一个轻量级语义化的-golang-编码解码加密解密库

dongle 是一个轻量级、语义化、对开发者敌对的 Golang 编码解码和加密解密库 Dongle 已被 awesome-go 收录, 如果您感觉不错,请给个 star 吧 github.com/golang-module/dongle gitee.com/golang-module/dongle 更新日志 减少对 base45 编码、解码的反对减少对 blake2b-256, blake2b-384, blake2b-512 哈希算法的反对减少对 blake2s-256 哈希算法的反对减少对超过 117 字节超长明文的 rsa 解密、解密反对性能清单 [x] Hex 编码、解码[x] Base16 编码、解码[x] Base32 编码、解码[x] Base45 编码、解码[x] Base58 编码、解码[x] Base62 编码、解码[x] Base64 编码、解码[x] Base64URL 编码、解码[x] SafeURL 编码、解码[x] Base85 编码、解码[x] Base91 编码、解码[x] Base100 编码、解码[x] Morse(摩斯) 编码、解码[x] Md2 加密[x] Md4 加密[x] Md5 加密[x] Sha1 加密[x] Sha3-224 加密[x] Sha3-256 加密[x] Sha3-384 加密[x] Sha3-512 加密[x] Sha224 加密[x] Sha256 加密[x] Sha384 加密[x] Sha512 加密[x] Sha512-224 加密[x] Sha512-256 加密[x] Shake128 加密[x] Shake256 加密[x] Ripemd160 加密[x] Blake2b-256 加密[x] Blake2b-384 加密[x] Blake2b-512 加密[x] Blake2s-256 加密[x] Hmac-md2 加密[x] Hmac-md4 加密[x] Hmac-md5 加密[x] Hmac-sha1 加密[x] Hmac-sha3-224 加密[x] Hmac-sha3-256 加密[x] Hmac-sha3-384 加密[x] Hmac-sha3-512 加密[x] Hmac-sha224 加密[x] Hmac-sha256 加密[x] Hmac-sha384 加密[x] Hmac-sha512 加密[x] Hmac-sha512-224 加密[x] Hmac-sha512-256 加密[x] Hmac-ripemd160 加密[x] Hmac-sm3 加密[ ] Rc2 加密、解密[x] Rc4 加密、解密[ ] Rc5 加密、解密[ ] Rc6 加密、解密[x] Tea 加密、解密[ ] Xtea 加密、解密[x] Aes 加密、解密[x] Blowfish 加密、解密[x] Des 加密、解密[x] 3Des 加密、解密[x] Rsa 加密、解密[ ] Ecc 加密、解密[ ] Sm2 加密、解密[x] Sm3 加密[ ] Sm4 加密、解密[ ] Sm7 加密、解密[ ] Sm9 加密、解密[x] Bcrypt 签名、验签[x] Ed25519 签名、验签[x] Rsa 签名、验签[ ] Dsa 签名、验签

December 30, 2022 · 1 min · jiezi

关于go:不背锅运维上篇Go并发编程

根本应用package mainimport ( "fmt" "sync")var wg sync.WaitGroupfunc hello() { fmt.Println("hello func...") wg.Done() // 告诉计数器减1}func main() { wg.Add(4) // 计数器,4个并发工作 go hello() go hello() go hello() go hello() fmt.Println("main func!") wg.Wait() // 期待所有工作执行实现}革新一下,开启10000个goroutinepackage mainimport ( "fmt" "sync")var wg sync.WaitGroupfunc hello(i int) { fmt.Println("hello func...", i) wg.Done()}func main() { // wg.Add(10000) for i := 0; i < 10000; i++ {  wg.Add(1)  go hello(i) } fmt.Println("main func!") wg.Wait()}将上一个例子革新成匿名函数package mainimport ( "fmt" "sync")var wg sync.WaitGroupfunc main() { // wg.Add(10000) for i := 0; i < 10000; i++ {  go func(i int) {   fmt.Println("hello...", i)  }(i) } fmt.Println("main func!") wg.Wait()}指定占用CPU外围数package mainimport ( "fmt" "runtime" "sync")var wg sync.WaitGroupfunc test1() { for i := 0; i < 10; i++ {  fmt.Println("func test1...", i) }}func test2() { for i := 0; i < 10; i++ {  fmt.Println("func test2...", i) }}func main() { runtime.GOMAXPROCS(1) // 只占用1个CPU外围 wg.Add(2) go test1() go test2() wg.Wait()}带缓冲区的通道,相似于异步的操作package mainimport "fmt"func main() { ch1 := make(chan int, 1) // 只能寄存1个值的缓冲区通道 ch1 <- 10  // 发送 x := <-ch1 // 接管 fmt.Println(x) close(ch1)}无缓冲区的通道,又称为同步通道package mainimport "fmt"func main() { ch1 := make(chan int) // 无缓冲区通道,又称为同步通道, ch1 <- 10             // 此时这里会处于阻塞的状态,除非有另外一个goroutine去取值,它才会发送 x := <-ch1 fmt.Println(x) close(ch1)}获取通道的容量和通道里的元素数量package mainimport "fmt"func main() { ch1 := make(chan int, 10) ch1 <- 89 ch1 <- 70 fmt.Println(len(ch1)) // 获取通道中元素的数量 fmt.Println(cap(ch1)) // 获取通道的容量 close(ch1)}通道和goroutine的小栗子package mainimport ( "fmt" "sync")type myinterface interface{}var ch1 = make(chan myinterface, 1)var wg sync.WaitGroupfunc sendData(i myinterface) { fmt.Printf("向通道发送 %v 胜利\n", i) ch1 <- i wg.Done()}func readData() { v := <-ch1 fmt.Println("从通道获取的值:", v) wg.Done()}func main() { nameArray := []string{"ttr", "tantianran"} wg.Add(2) go sendData(nameArray) go readData() wg.Wait()}通道+goroutine,实现协同干活例子2package mainimport "fmt"func producer(ch chan int) { for i := 0; i < 10; i++ {  ch <- i } close(ch)}func consumer(ch1 chan int, ch2 chan int) { for {  v, ok := <-ch1  if !ok {   break  }  ch2 <- v * 2 } close(ch2)}func main() { ch1 := make(chan int, 100) ch2 := make(chan int, 200) go producer(ch1) go consumer(ch1, ch2) for i := range ch2 {  fmt.Println(i) }}本文转载于(喜爱的盆友关注咱们哦):https://mp.weixin.qq.com/s/_X...

December 30, 2022 · 1 min · jiezi

关于go:Go基础篇之数组

数组相必大家都很相熟,各大语言也都有数组的身影。Go 语言也提供了数组类型的数据结构。 1. Array(数组)数组是同一种数据类型的固定长度的元素汇合。在 Go 语言中,数组申明后长度就不能扭转了,能够批改数组的元素,用法: // eg: 定义一个长度为 10 的 int 数组var a [10]int2. 申明数组Go 语言数组申明时须要指定元素类型及元素的个数,语法格局如下: var variable_name [SIZE] variable_type3. 数组初始化Go 语言中初始化数组有很多形式。 3.1 形式一咱们也能够通过字面量在申明数组的同时疾速初始化数组: balance := [5]float32{3.14, 13.0, 33.4, 15.0, 20.0}3.2 形式二如果数组长度不确定,能够应用 ...代替数组的长度,编译器会依据元素个数自行推断数组的长度: balance := [...]float32{3.14, 13.0, 33.4, 15.0, 20.0}3.3 形式三如果设置了数组的长度,咱们还能够通过指定下标来初始化元素: // 将索引下标为 1 和 3 的元素初始化balance := [5]float32{1:2.0,3:7.0}3.4 多维数组package mainimport ( "fmt")var array1 [5][3]intvar array2 [2][3]int = [...][3]int{{10, 20, 30}, {4, 5, 6}}func main() { arr1 := [2][3]int{{10, 11, 12}, {20, 21, 22}} arr2 := [...][2]int{{10, 11}, {20, 21}, {30, 31}} fmt.Println(array1, array2) fmt.Println(arr1, arr2)}留神: Go 语言多维数组中,只有第一层能够用 ...其余维度不能用 ... ...

December 30, 2022 · 2 min · jiezi

关于go:godongle-023-版本发布一个轻量级语义化的-golang-编码解码加密解密库

dongle 是一个轻量级、语义化、对开发者敌对的 Golang 编码解码和加密解密库 Dongle 已被 awesome-go 收录, 如果您感觉不错,请给个 star 吧 github.com/golang-module/dongle gitee.com/golang-module/dongle 更新日志 减少对 shake128 哈希算法的反对减少对 shake256 哈希算法的反对性能清单 [x] Hex 编码、解码[x] Base16 编码、解码[x] Base32 编码、解码[x] Base58 编码、解码[x] Base62 编码、解码[x] Base64 编码、解码[x] Base64URL 编码、解码[x] SafeURL 编码、解码[x] Base85 编码、解码[x] Base91 编码、解码[x] Base100 编码、解码[x] Morse(摩斯) 编码、解码[x] Md2 加密[x] Md4 加密[x] Md5 加密[x] Sha1 加密[x] Sha3-224 加密[x] Sha3-256 加密[x] Sha3-384 加密[x] Sha3-512 加密[x] Sha224 加密[x] Sha256 加密[x] Sha384 加密[x] Sha512 加密[x] Sha512-224 加密[x] Sha512-256 加密[x] Shake128 加密[x] Shake256 加密[x] Ripemd160 加密[x] Hmac-md2 加密[x] Hmac-md4 加密[x] Hmac-md5 加密[x] Hmac-sha1 加密[x] Hmac-sha3-224 加密[x] Hmac-sha3-256 加密[x] Hmac-sha3-384 加密[x] Hmac-sha3-512 加密[x] Hmac-sha224 加密[x] Hmac-sha256 加密[x] Hmac-sha384 加密[x] Hmac-sha512 加密[x] Hmac-sha512-224 加密[x] Hmac-sha512-256 加密[x] Hmac-ripemd160 加密[x] Hmac-sm3 加密[ ] Rc2 加密、解密[x] Rc4 加密、解密[ ] Rc5 加密、解密[ ] Rc6 加密、解密[x] Tea 加密、解密[ ] Xtea 加密、解密[x] Aes 加密、解密[x] Blowfish 加密、解密[x] Des 加密、解密[x] 3Des 加密、解密[x] Rsa 加密、解密[ ] Ecc 加密、解密[ ] Sm2 加密、解密[x] Sm3 加密[ ] Sm4 加密、解密[ ] Sm7 加密、解密[ ] Sm9 加密、解密[x] Bcrypt 签名、验签[x] Ed25519 签名、验签[x] Rsa 签名、验签[ ] Dsa 签名、验签

December 28, 2022 · 1 min · jiezi

关于go:不背锅运维GoPromethus-Eexporter开发一篇带你玩妥它

本篇内容有点长,代码有点多。有趣味的能够保持看上来,并入手实际,没趣味的能够划走。本文分两大块,一是搞清楚prometheus四种类型的指标Counter,Gauge,Histogram,Summary用golang语言如何结构这4种类型对应的指标,二是搞清楚批改指标值的场景和形式。指标类型类别形容可利用场景Counter计数类应用在累计指标枯燥递增或递加状况下,只能在指标重启后主动归零服务申请解决数量、已实现工作数量、谬误数量Guage测量类应用可增可减的的数据状况下以后内存/CPU应用状况、并发申请数量Histogram直方图类应用统计指标信息在不同区间内的统计数量延迟时间、响应大小。例如:0-1秒内的延迟时间、、0-5秒内的延迟时间、例如0-1kb之内的响应大小、0-5kb之内的响应大小Summary摘要类相似于直方图,在客户端对百分位进行统计延迟时间、响应大小。例如:超过百分之多少的人要满足需要的话,须要多长时间实现。1. Gauge指标类型1.1 不带label的根本例子package mainimport ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")func main() { // 定义指标 cpuUsage := prometheus.NewGauge(prometheus.GaugeOpts{  Name: "cpu_usage",                      // 指标名称  Help: "this is test metrics cpu usage", // 帮忙信息 }) // 给指标设置值 cpuUsage.Set(89.56) // 注册指标 prometheus.MustRegister(cpuUsage) // 裸露指标 http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}1.2 带有固定label指标的例子package mainimport ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")func main() { // 定义指标 cpuUsage := prometheus.NewGauge(prometheus.GaugeOpts{  Name:        "cpu_usage",                      // 指标名称  Help:        "this is test metrics cpu usage", // 帮忙信息  ConstLabels: prometheus.Labels{"MachineType": "host"}, // label }) // 给指标设置值 cpuUsage.Set(89.56) // 注册指标 prometheus.MustRegister(cpuUsage) // 裸露指标 http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}1.3 带有非固定label指标的例子package mainimport ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")func main() { //定义带有不固定label的指标 mtu := prometheus.NewGaugeVec(prometheus.GaugeOpts{  Name: "interface_mtu",  Help: "网卡接口MTU", }, []string{"interface", "Machinetype"}) // 给指标设置值 mtu.WithLabelValues("lo", "host").Set(1500) mtu.WithLabelValues("ens32", "host").Set(1500) mtu.WithLabelValues("eth0", "host").Set(1500) // 注册指标 prometheus.MustRegister(mtu) // 裸露指标 http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}2. Counter指标类型2.1 不带label的根本例子package mainimport ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")func main() { // 定义指标 reqTotal := prometheus.NewCounter(prometheus.CounterOpts{  Name: "current_request_total",  Help: "以后申请总数", }) // 注册指标 prometheus.MustRegister(reqTotal) // 设置值 reqTotal.Add(10) // 裸露指标 http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}2.2 带有固定label指标的例子package mainimport ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")func main() { // 定义指标 suceReqTotal := prometheus.NewCounter(prometheus.CounterOpts{  Name:        "sucess_request_total",  Help:        "申请胜利的总数",  ConstLabels: prometheus.Labels{"StatusCode": "200"}, }) // 注册指标 prometheus.MustRegister(suceReqTotal) // 设置值 suceReqTotal.Add(5675) // 裸露指标 http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}2.3 带有非固定label指标的例子package mainimport ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")func main() { // 定义指标 pathReqTotal := prometheus.NewCounterVec(prometheus.CounterOpts{  Name: "path_request_total",  Help: "path申请总数", }, []string{"path"}) // 注册指标 prometheus.MustRegister(pathReqTotal) // 设置值 pathReqTotal.WithLabelValues("/token").Add(37) pathReqTotal.WithLabelValues("/auth").Add(23) pathReqTotal.WithLabelValues("/user").Add(90) pathReqTotal.WithLabelValues("/api").Add(67) // 裸露指标 http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}3. Histogram指标类型3.1 不带label的根本例子package mainimport ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")func main() { // 定义指标 reqDelay := prometheus.NewHistogram(prometheus.HistogramOpts{  Name:    "request_delay",  Help:    "申请提早,单位秒",  Buckets: prometheus.LinearBuckets(0, 3, 6), // 调用LinearBuckets生成区间,从0开始,宽度3,共6个Bucket }) // 注册指标 prometheus.MustRegister(reqDelay) // 设置值 reqDelay.Observe(6) // 裸露指标 http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}3.2 带固定label的例子package mainimport ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")func main() { // 定义指标 reqDelay := prometheus.NewHistogram(prometheus.HistogramOpts{  Name:        "request_delay",  Help:        "申请提早,单位秒",  Buckets:     prometheus.LinearBuckets(0, 3, 6), // 调用LinearBuckets生成区间,从0开始,宽度3,共6个Bucket  ConstLabels: prometheus.Labels{"path": "/api"}, }) // 注册指标 prometheus.MustRegister(reqDelay) // 设置值 reqDelay.Observe(6) // 裸露指标 http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}3.3 带有非固定label的例子package mainimport ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")func main() { // 定义指标 reqDelay := prometheus.NewHistogramVec(prometheus.HistogramOpts{  Name:    "request_delay",  Help:    "申请提早,单位秒",  Buckets: prometheus.LinearBuckets(0, 3, 6), // 调用LinearBuckets生成区间,从0开始,宽度3,共6个Bucket }, []string{"path"}) // 注册指标 prometheus.MustRegister(reqDelay) // 设置值 reqDelay.WithLabelValues("/api").Observe(6) reqDelay.WithLabelValues("/user").Observe(3) reqDelay.WithLabelValues("/delete").Observe(2) reqDelay.WithLabelValues("/get_token").Observe(13) // 裸露指标 http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}4. Summary指标类型4.1 不带label的例子package mainimport ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")func main() { // 定义指标 reqDelay := prometheus.NewSummary(prometheus.SummaryOpts{  Name:       "request_delay",  Help:       "申请提早",  Objectives: map[float64]float64{0.5: 0.05, 0.90: 0.01, 0.99: 0.001}, // 百分比:精度 }) // 注册指标 prometheus.MustRegister(reqDelay) // 设置值 reqDelay.Observe(4) // 裸露指标 http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}4.2 带有固定label的例子package mainimport ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")func main() { // 定义指标 reqDelay := prometheus.NewSummary(prometheus.SummaryOpts{  Name:        "request_delay",  Help:        "申请提早",  Objectives:  map[float64]float64{0.5: 0.05, 0.90: 0.01, 0.99: 0.001}, // 百分比:精度  ConstLabels: prometheus.Labels{"path": "/api"}, }) // 注册指标 prometheus.MustRegister(reqDelay) // 设置值 reqDelay.Observe(4) // 裸露指标 http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}4.3 带有非固定label的例子package mainimport ( "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")func main() { // 定义指标 reqDelay := prometheus.NewSummaryVec(prometheus.SummaryOpts{  Name:       "request_delay",  Help:       "申请提早",  Objectives: map[float64]float64{0.5: 0.05, 0.90: 0.01, 0.99: 0.001}, // 百分比:精度 }, []string{"path"}) // 注册指标 prometheus.MustRegister(reqDelay) // 设置值 reqDelay.WithLabelValues("/api").Observe(4) reqDelay.WithLabelValues("/token").Observe(2) reqDelay.WithLabelValues("/user").Observe(3) // 裸露指标 http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}5. 值的批改5.1 基于事件的触发来批改值,比方每拜访1次/api就增1基于事件的触发对指标的值进行批改,通常大多数是来自业务方面的指标需要,如自研的利用须要裸露相干指标给promethus进行监控、展现,那么指标采集的代码(指标定义、设置值)就要嵌入到自研利用代码里了。package mainimport ( "fmt" "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")func main() { urlRequestTotal := prometheus.NewCounterVec(prometheus.CounterOpts{  Name: "urlRequestTotal",  Help: "PATH申请累计 单位 次", }, []string{"path"}) http.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {  urlRequestTotal.WithLabelValues(r.URL.Path).Inc() // 应用Inc函数进行增1  fmt.Fprintf(w, "Welcome to the api") }) prometheus.MustRegister(urlRequestTotal) http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}5.2 基于工夫周期的触发来批改值,比方上面的示例中,是每距离1秒获取cpu负载指标基于工夫周期的触发,能够是多少秒、分、时、日、月、周。package mainimport ( "net/http" "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/shirou/gopsutil/load")func main() { cpuUsage := prometheus.NewGaugeVec(prometheus.GaugeOpts{  Name: "CpuLoad",  Help: "CPU负载", }, []string{"time"}) // 开启一个子协程执行该匿名函数内的逻辑来给指标设置值,且每秒获取一次 go func() {  for range time.Tick(time.Second) {   info, _ := load.Avg()   cpuUsage.WithLabelValues("Load1").Set(float64(info.Load1))   cpuUsage.WithLabelValues("Load5").Set(float64(info.Load5))   cpuUsage.WithLabelValues("Load15").Set(float64(info.Load15))  } }() prometheus.MustRegister(cpuUsage) http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}5.3 基于每拜访一次获取指标的URI才批改值,比方每次拜访/metrics才去批改某些指标的值上面的这个示例是,每拜访一次/metrics就获取一次内存总容量package mainimport ( "fmt" "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/shirou/gopsutil/mem")func main() { MemTotal := prometheus.NewGaugeFunc(prometheus.GaugeOpts{  Name: "MemTotal",  Help: "内存总容量 单位 GB", }, func() float64 {  fmt.Println("call MemTotal ...")  info, _ := mem.VirtualMemory()  return float64(info.Total / 1024 / 1024 / 1024) }) prometheus.MustRegister(MemTotal) http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":9900", nil)}目前只有Gauge和Counter的指标类型有对应的函数,别离是NewGaugeFunc和NewCounterFunc,而且是固定的label。本文转载于(喜爱的盆友关注咱们):https://mp.weixin.qq.com/s/zb...

December 28, 2022 · 1 min · jiezi

关于go:万万没想到go的数据库操作也能像php一样溜了

Hi,各位go的小伙伴。 很多人都是从php转过来的吧,不晓得你们有没有发现,go界的orm并没有像php的orm一样好用。这篇文章里,咱们认真的探讨下这个问题,并且会在前面提出解决方案。 php的不便比方你想实现一个关联查问,在php里,你只须要一直的应用箭头函数就能够了。 $users = DB::table('users')->whereIn('id', [1, 2, 3])->orderBy('name', 'desc')->get();以上代码,很简略实现了对一个表的查问操作,并且将查问后果以name做倒序排列,很简略 然而做同样的工作,在go外面就比拟麻烦了 go的麻烦如果你应用go的原生查问的话,你须要写如下的代码 rows, err := db.Query("select * from users where id in (?,?,?) order by name desc", 1, 2, 3)基本上说,你须要手写一个残缺的sql语句,全手动 什么!手写sql语句,不是咱不会写,要害是没必要手写啊,是吧。 全手写可能带来两个问题 某些同学对于sql语法可能不相熟,容易有语法错误某些同学可能写sql不认真,容易有拼写错误,尤其是条件多,占位符多的时候如果你应用gorm之类的orm工具,可能会这样写 db.Where("id in (?)", []int{1,2,3}).Order("create_time desc").Find(&users)很显然比照原生的来说,好一些,不必手写select 等关键字了,然而外围问题还是没解决,还须要手写 id in (?)之类的。相当于之前是全手工,当初是半手工半自动了。 我这个例子里,条件就一个,在理论业务中,查问条件会有很多,并且数量还不肯定,这种半自动的办法还是不太好的。 解决方案既然有问题,那就有解决方案。很显著,最现实的计划就是放弃与php的统一。那么go能做到这样吗? 答案是毫无疑问的,能够的。 这里举荐一个新的数据库操作库,能够很不便的实现这样的工作 tangpanqing/aorm: Operate Database So Easy For GoLang Developer (github.com) 它有一些显著的个性  代码简洁,高性能 反对 MySQL,MsSQL,Postgres,Sqlite3 数据库 反对 空值查问 反对 主动迁徙 反对 SQL 拼接咱们来看具体应用,就方才的操作 aorm.Use(db).Table("users").WhereIn("id", []int{1,2,3}).OrderBy("name","desc").GetMany(&users)比照php的写法 $users = DB::table('users')->whereIn('id', [1, 2, 3])->orderBy('name', 'desc')->get();不能说截然不同吧,那几乎是截然不同是不是? 咱们再来看看如果是查问条件不确定怎么办? 这是列表查问常常遇到的问题,前端传过来的数据数量是不肯定的,咱们须要依据不同的数据,来减少或者缩小不同的条件,进而产生不同的sql,查问不同的后果 var listByWhere []Person var where1 []builder.WhereItem where1 = append(where1, builder.WhereItem{Field: "type", Opt: builder.Eq, Val: 0}) where1 = append(where1, builder.WhereItem{Field: "age", Opt: builder.In, Val: []int{18, 20}}) where1 = append(where1, builder.WhereItem{Field: "money", Opt: builder.Between, Val: []float64{100.1, 200.9}}) where1 = append(where1, builder.WhereItem{Field: "money", Opt: builder.Eq, Val: 100.15}) where1 = append(where1, builder.WhereItem{Field: "name", Opt: builder.Like, Val: []string{"%", "li", "%"}}) aorm.Use(db).Debug(true).Table("person").WhereArr(where1).GetMany(&listByWhere) for i := 0; i < len(listByWhere); i++ { fmt.Println(listByWhere[i]) }如上,你能够定义一个builder.WhereItem的切片(数组),而后依据前端传过来的信息,来减少和缩小这个数组里的项,最初将这个查问数组,传递给aorm进行最初查问,最终失去后果。 ...

December 27, 2022 · 1 min · jiezi

关于go:你确定没有滥用-goroutine-吗

写在后面学习 golang ,路还很长呢,犹记得刚开始学习 golang 的时候,写起来的确非常简单,有很多包和工具应用,不须要反复造轮子,然而要真的学好一门语言作为工具,对于其原理是十分有必要学懂的 并发谬误golang 天生高并发,编码的时候,就会呈现滥用 goroutine 的状况,咱们来看看都是如何滥用的 func main() { for i := 0; i < 10; i++ { go func() { fmt.Println(" the num is ", i) }() } time.Sleep(time.Second) fmt.Println(" program over !! ")}xdm 看看下面这个简略的程序运行 go run main.go 输入会是什么呢? 是会输入 0 到 9 吗?,咱们来理论看看成果 # go run main.go the num is 10 the num is 10 the num is 10 the num is 10 the num is 10 the num is 10 the num is 10 the num is 10 the num is 10 the num is 10 program over !!哦豁,这是为啥,明明循环了 10 次,应该每一次递增 1 的打印出后果才对呀 ...

December 26, 2022 · 3 min · jiezi

关于go:Aorm又进步了目前已支持MySQLMSSQLPostgresSqlite3并且支持子查询

hi,各位golang的敌人,我很快乐的通知你们,Aorm又提高了。 Aorm是什么Aorm是一个基于go语言的数据库操作库,能够帮忙你更不便的进行数据库操作。 它最大的特点是反对空值查问和更新,以及反对sql的链式操作,特地相似于php相干的orm操作 这里是之前发过的一个文档想早点上班?试试Aorm库吧,更不便的进行Go数据库操作 - 掘金 (juejin.cn) 这是具体的我的项目地址 tangpanqing/aorm: Operate Database So Easy For GoLang Developer (github.com) 在最近的一个星期左右,我将它进行了降级。 之前只反对MySQL,目前曾经反对MySQL, MSSQL, Postgres, Sqlite3等四大数据库 之前不反对子查问,目前曾经反对 示例个别状况下的写入如果你应用MySQL,Sqlite3 数据库,能够间接应用如下的代码,来进行一次插入 id, errInsert := aorm.Use(db).Debug(true).Insert(&Person{ Name: null.StringFrom("Alice"), Sex: null.BoolFrom(false), Age: null.IntFrom(18), Type: null.IntFrom(0), CreateTime: null.TimeFrom(time.Now()), Money: null.FloatFrom(100.15), Test: null.FloatFrom(200.15987654321987654321),})if errInsert != nil { fmt.Println(errInsert)}fmt.Println(id)它产生的sql如下 INSERT INTO person (name,sex,age,type,create_time,money,test) VALUES (?,?,?,?,?,?,?)Alice false 18 0 2022-12-07 10:10:26.1450773 +0800 CST m=+0.031808801 100.15 200.15987654321987MSSQL与Postgres的特殊性如果你应用MSSQL,Postgres 数据库,须要减少一个Driver操作,以明确的通知Aorm,这里是MSSQL或者Postgres,Aorm会对sql做一些批改,例如 id, errInsert := aorm.Use(db).Debug(true).Driver("mssql").Insert(&Person{ ....})它产生的sql如下 ...

December 26, 2022 · 2 min · jiezi

关于go:Go-快速入门指南-日志

概述调用 log 包即可,包外面的办法输入日志时会主动加上日期工夫前缀字符。 例子输入到终端package mainimport ( "log" "os")func main() { log.SetOutput(os.Stdout) log.Println("[4.426ms] [rows:1] SELECT * FROM `users` WHERE `id` = 1024") log.Printf("[GET] %d %s %s", 200, "OK", "/api/v1/users")}// $ go run main.go// 输入如下,你的输入可能和这里的不一样/** 2021/01/03 15:18:55 [4.426ms] [rows:1] SELECT * FROM `users` WHERE `id` = 1024 2021/01/03 15:18:55 [GET] 200 OK /api/v1/users*/输入到文件倡议先浏览 创立, 删除文件。 package mainimport ( "log" "os")func main() { logFile := "/tmp/test_main_go_server.log" file, err := os.Create(logFile) if err != nil { panic(err) } defer func() { err = file.Close() if err != nil { panic(err) } }() log.SetOutput(file) log.Println("[4.426ms] [rows:1] SELECT * FROM `users` WHERE `id` = 1024") log.Printf("[GET] %d %s %s", 200, "OK", "/api/v1/users")}// $ go run main.go// $ cat /tmp/test_main_go_server.log// 输入如下,你的输入可能和这里的不一样/** 2021/01/03 15:25:23 [4.426ms] [rows:1] SELECT * FROM `users` WHERE `id` = 1024 2021/01/03 15:25:23 [GET] 200 OK /api/v1/users*/分割我 ...

December 25, 2022 · 1 min · jiezi

关于go:Go-快速入门指南-遍历目录

概述调用 path/filepath 包即可。filepath.Walk() 办法十分弱小,无需递归,以非常简单的形式实现了整个目录遍历。 倡议先浏览 创立, 删除目录。 例子package mainimport ( "fmt" "io/fs" "os" "path/filepath")func main() { dir := "/tmp/test_main_go_dir" // 创立一些测试目录和文件 if _, err := os.Stat(dir); os.IsNotExist(err) { subDir := filepath.Join(dir, "1", "2", "3") err = os.MkdirAll(subDir, 0755) // 创立多级目录 if err != nil { panic(err) } // 退出时删除目录 defer func() { err = os.RemoveAll(dir) if err != nil { panic(err) } }() // 在目录上面新建 2 个文件 _, err := os.Create(filepath.Join(subDir, "4.log")) if err != nil { panic(err) } _, err = os.Create(filepath.Join(subDir, "5.log")) if err != nil { panic(err) } } err := filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { var typ string if info.IsDir() { typ = "Dir" } else { typ = "File" } fmt.Printf("[%s] %s\n", typ, path) return nil }) if err != nil { panic(err) }}// $ go run main.go// 输入如下/** [Dir] /tmp/test_main_go_dir [Dir] /tmp/test_main_go_dir/1 [Dir] /tmp/test_main_go_dir/1/2 [Dir] /tmp/test_main_go_dir/1/2/3 [File] /tmp/test_main_go_dir/1/2/3/4.log [File] /tmp/test_main_go_dir/1/2/3/5.log*/分割我 ...

December 25, 2022 · 1 min · jiezi

关于go:Go-快速入门指南-创建-删除目录

概述调用 os 包即可。 例子目录创立package mainimport ( "fmt" "os")func main() { err := os.Mkdir("/tmp/test_go_main_dir", 0755) // 创立 1 级目录 if err != nil { panic(err) } else { fmt.Println("/tmp/test_go_main_dir has been created") } err = os.MkdirAll("/tmp/test_go_main_dir/1/2/3", 0755) // 创立多级目录 if err != nil { panic(err) } else { fmt.Println("/tmp/test_go_main_dir/1/2/3 has been created") }}// $ go run main.go// 输入如下/** /tmp/test_go_main_dir has been created /tmp/test_go_main_dir/1/2/3 has been created*/目录删除package mainimport ( "fmt" "os")func main() { err := os.RemoveAll("/tmp/test_go_main_dir") if err != nil { panic(err) } else { fmt.Println("/tmp/test_go_main_dir has been deleted") }}// $ go run main.go// 输入如下/** /tmp/test_go_main_dir/1/2/3 has been deleted*/分割我 ...

December 25, 2022 · 1 min · jiezi

关于go:Go-快速入门指南-文件判断

概述调用 os 包即可。 例子检测文件是否存在package mainimport ( "fmt" "os")func main() { if _, err := os.Stat("/tmp/not_found_main.go"); os.IsNotExist(err) { fmt.Printf("%s\n", err) }}// $ go run main.go/** stat /tmp/not_found_main.go: no such file or directory*/检测是否领有文件权限package mainimport ( "fmt" "os")func main() { _, err := os.ReadFile("/root/passwd") if err != nil && os.IsPermission(err) { fmt.Printf("%s\n", err) }}// $ go run main.go// 输入如下 /** open /root/passwd: permission denied*/分割我

December 25, 2022 · 1 min · jiezi

关于go:Go-快速入门指南-文件路径-扩展名

概述调用 path/filepath 包即可。 例子package mainimport ( "fmt" "path/filepath")func main() { path, err := filepath.Abs("./main.go") if err != nil { panic(err) } fmt.Printf("file abs path = %s\n", path) // 获取文件的绝对路径 fmt.Printf("file name = %s\n", filepath.Base("./main.go")) // 获取文件名称 fmt.Printf("file ext = %s\n", filepath.Ext("./main.go")) // 获取文件扩展名 path2 := filepath.Join("/tmp", "code", "test", "main.go") fmt.Printf("build file path = %s\n", path2) // 获取构建的文件门路}// $ go run main.go// 输入如下,你的输入可能和这里的不一样/** file abs path = /home/codes/Go-examples-for-beginners/main.go file name = main.go file ext = .go build file path = /tmp/code/test/main.go*/分割我 ...

December 25, 2022 · 1 min · jiezi

关于go:Go-快速入门指南-读文件

概述调用 os 包即可。倡议先浏览 创立文件 和 写文件。 例子间接读取package mainimport ( "fmt" "os")func main() { code, err := os.ReadFile("/tmp/test_main.go") if err != nil { panic(err) } fmt.Printf("%s\n", code)}// $ go run main.go// 输入如下 /** package main func main() { println("hello world") }*/先获取文件句柄,而后读取package mainimport ( "fmt" "os")func main() { file, err := os.OpenFile("/tmp/test_main.go", os.O_RDONLY, 0755) if err != nil { panic(err) } // 记得敞开文件句柄 defer func() { err = file.Close() if err != nil { panic(err) } }() code := make([]byte, 1024) // 留神: 切片的长度决定了读取内容的长度 n, err := file.Read(code) if err != nil { panic(err) } fmt.Printf("%d characters were successfully read\n", n) fmt.Printf("%s\n", code)}// $ go run main.go// 输入如下 /** 55 characters were successfully read package main func main() { println("hello world") }*/分割我 ...

December 25, 2022 · 1 min · jiezi