关于golang:gofs使用教程基于golang的开源跨平台文件同步工具

概述gofs是基于golang开发的一款开箱即用的跨平台文件同步工具,开源地址如下:https://github.com/no-src/gofs,欢送点个Star或者提交Issue和PR,共同进步! 装置首先须要确保曾经装置了Go (版本必须是1.18+),而后你就能够应用上面的命令来装置gofs了 如果你不须要自行从源码编译装置,也能够间接下载最新公布的二进制文件 Release go install github.com/no-src/gofs/...@latest在Docker中运行如果你想要在docker中运行,请在装置或者编译的时候应用-tags netgo命令行参数或者设置环境变量CGO_ENABLED=0,否则当你运行docker容器时可能会报找不到gofs的谬误 go install -tags netgo github.com/no-src/gofs/...@latest后盾运行在windows零碎中,你能够应用上面的命令构建一个在后盾运行的不带命令行界面的程序 go install -ldflags="-H windowsgui" github.com/no-src/gofs/...@latest移除Web文件服务器如果你不须要一个Web文件服务器,能够应用上面命令构建一个体积更小的不带Web文件服务器的程序 go install -tags "no_server" github.com/no-src/gofs/...@latest疾速开始先决条件请确保文件同步的源目录和目标目录都曾经存在,如果目录不存在,则用你理论的目录替换上面的门路进行提前创立 $ mkdir source dest生成仅用于测试的证书和密钥文件,生产中请替换为正式的证书 TLS证书和密钥文件仅用于与Web文件服务器和近程磁盘服务端进行平安通信 $ go run $GOROOT/src/crypto/tls/generate_cert.go --host 127.0.0.12021/12/30 17:21:54 wrote cert.pem2021/12/30 17:21:54 wrote key.pem查看你的工作目录 $ lscert.pem key.pem source dest本地磁盘监控本地源目录将变更同步到目标目录 你能够应用logically_delete命令行参数来启用逻辑删除,从而防止误删数据 $ gofs -source=./source -dest=./dest全量同步执行一次全量同步,间接将整个源目录同步到目标目录 $ gofs -source=./source -dest=./dest -sync_once定时同步定时执行全量同步,将整个源目录同步到目标目录 # 每30秒钟将源目录全量同步到目标目录$ gofs -source=./source -dest=./dest -sync_cron="*/30 * * * * *"守护过程模式启动守护过程来创立一个工作过程解决理论的工作,并将相干过程的pid信息记录到pid文件中 $ gofs -source=./source -dest=./dest -daemon -daemon_pidWeb文件服务器启动一个Web文件服务器用于拜访近程的源目录和目标目录 ...

March 30, 2022 · 1 min · jiezi

关于golang:Golang力扣Leetcode-27-移除元素

题目:给你一个数组 nums 和一个值 val,你须要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要应用额定的数组空间,你必须仅应用 O(1) 额定空间并 原地 批改输出数组。 元素的程序能够扭转。你不须要思考数组中超出新长度前面的元素。 链接: 力扣Leetcode - 27. 移除元素. 示例 1: 输出:nums = [3,2,2,3], val = 3输入:2, nums = [2,2]解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不须要思考数组中超出新长度前面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。示例 2: 输出:nums = [0,1,2,2,3,0,4,2], val = 2输入:5, nums = [0,1,4,0,3]解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。留神这五个元素可为任意程序。你不须要思考数组中超出新长度前面的元素。思路:遍历数组,如果数不等于给定的数,增加到数组中,如果不等就不增加 Go代码: package mainimport "fmt"func removeElement(nums []int, val int) int { if len(nums) == 0 { return 0 } a := 0 for i, _ := range nums { if nums[i] != val { nums[a] = nums[i] a++ } } return a}func main() { a := []int{3, 2, 2, 3} fmt.Println(removeElement(a, 3))}提交截图: ...

March 29, 2022 · 1 min · jiezi

关于golang:Go-语言之父介绍泛型增添三个新的主要内容

近日,Go 官网博客基于 2021 年 GopherCon 大会发表了一篇介绍新个性“泛型”的文章,作者为 Robert Griesemer 和 Ian Lance Taylor。 据介绍,Go 1.18 版本减少了对泛型的反对,泛型是自 Go 开源以来的最大扭转。泛型是一种编写范式,它独立于所应用的特定类型,泛型容许在函数和类型的实现中应用某个类型汇合中的任何一种类型。 泛型为 Go 增加了三个新的重要内容: 面向函数和类型的“类型参数” (type parameters)将接口类型定义为类型汇合,包含没有办法的接口类型类型推断:在许多状况下,在调用泛型函数时可省略类型参数(type arguments)类型推断这是 Go 中最简单的变更,包含: 函数参数类型推断 (Function argument type inference)束缚类型推断 (Constraint type inference)尽管类型推断的工作原理细节很简单,但应用它并不简单:类型推断要么胜利,要么失败。如果胜利,能够省略类型参数,调用泛型函数看起来与调用一般函数没有什么不同。如果类型推断失败,编译器将给出谬误音讯,在这种状况下,只需提供必要的类型参数。 type arguments当初函数和类型都具备类型参数,类型参数列表看起来像一个一般的参数列表,除了它应用方括号而不是圆括号。 先从浮点值的根本非泛型 Min 函数开始: func Min(x, y float64) float64 {    if x < y {        return x    }    return y}通过增加类型参数列表来使这个函数泛型化——使其实用于不同的类型。在此示例中,增加了一个带有单个类型参数 T 的类型参数列表,并将float64替换为T。 import "golang.org/x/exp/constraints"func GMin[T constraints.Ordered](x, y T) T {    if x < y {        return x    }    return y}当初就能够应用类型参数调用此函数 x := GMin[int](2, 3)向 GMin 提供类型参数,在这种状况下 int 称为实例化。实例化分两步进行。首先,编译器在泛型函数或泛型类型中用所有类型参数替换它们各自的类型参数。 其次,编译器验证每个类型参数是否满足各自的束缚。如果第二步失败,实例化就会失败,程序就会有效。胜利实例化后,即可产生非泛型函数,它能够像任何其余函数一样被调用。例如: fmin := GMin[float64]m := fmin(2.71, 3.14)实例化 GMin\[float64\] 产生了一个与 Min 函数等效的函数,能够在函数调用中应用它。类型参数也能够与类型一起应用。 type Tree[T interface{}] struct {    left, right *Tree[T]    value       T}func (t *Tree[T]) Lookup(x T) *Tree[T] { ... }var stringTree Tree[string]这里泛型类型 Tree 存储了类型参数T的值。泛型类型也能够有办法,如本例中的 Lookup。为了应用泛型类型,它必须被实例化; Tree\[string\] 是应用类型参数 string 来实例化 Tree 的示例。 泛型是 Go 1.18 中一个重要的新语言个性,Robert Griesemer 和 Ian Lance Taylor 示意,这个性能实现得很好并且品质很高,但在生产环境中部署泛型代码时,还是须要审慎行事。 ...

March 29, 2022 · 1 min · jiezi

关于golang:gozero源码阅读代码结构第一期

go-zero 作为一个微服务框架,不仅给咱们提供了很好的参考,而且外围代码量不多,咱们能够在空闲工夫读读他的外围代码,来多多学习充电。 rest 局部代码构造rest├── handler // 自带中间件│   ├── authhandler.go // 权限│   ├── breakerhandler.go // 断路器│   ├── contentsecurityhandler.go // 平安验证│   ├── cryptionhandler.go // 加密解密│   ├── gunziphandler.go // zip 压缩│   ├── loghandler.go // 日志│   ├── maxbyteshandler.go // 最大申请数据限度│   ├── maxconnshandler.go // 最大申请连接数限度│   ├── metrichandler.go // 申请指标统计│   ├── prometheushandler.go // prometheus 上报│   ├── recoverhandler.go // 谬误捕捉│   ├── sheddinghandler.go // 过载爱护│   ├── timeouthandler.go // 超时管制│   └── tracinghandler.go // 链路追踪├── httpx│   ├── requests.go│   ├── responses.go│   ├── router.go│   ├── util.go│   └── vars.go├── internal│   ├── cors // 跨域解决│   │   └── handlers.go│   ├── response│   │   ├── headeronceresponsewriter.go│   │   └── withcoderesponsewriter.go│   ├── security // 加密解决│   │   └── contentsecurity.go│   ├── log.go│   └── starter.go├── pathvar // path 参数解析│   └── params.go├── router│   └── patrouter.go├── token│   └── tokenparser.go├── config.go // 配置├── engine.go // 引擎├── server.go└── types.go服务启动流程咱们以 go-zero-example 我的项目 http/demo/main.go 代码来剖析 ...

March 29, 2022 · 3 min · jiezi

关于golang:Golang力扣Leetcode-9回文数数学

题目:给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数是斧正序(从左向右)和倒序(从右向左)读都是一样的整数。 例如,121 是回文,而 123 不是。链接: 力扣Leetcode - 9.回文数. 示例 1: 输出:x = 121输入:true示例 2: 输出:x = -121输入:false解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因而它不是一个回文数。示例 3: 输出:x = 10输入:false解释:从右向左读, 为 01 。因而它不是一个回文数。思路:这里用比较简单的方法,在数学上如果为回文数,颠倒后的数肯定和原来相等 如果是正数则肯定不是回文数,间接返回 false如果是负数,则将其倒序数值计算出来,而后比拟和原数值是否相等如果是回文数则相等返回 true,如果不是则不相等 falseGo代码: package mainimport ( "fmt")func isPalindrome(x int) bool { var sum int first := x if x < 0 { return false } else { for x != 0 { a := x % 10 x = x / 10 sum = sum*10 + a } } return sum == first}func main() { fmt.Println(isPalindrome(121))}提交截图: ...

March 29, 2022 · 1 min · jiezi

关于golang:Golang力扣Leetcode-2两数相加

题目:给你两个 非空 的链表,示意两个非负的整数。它们每位数字都是依照 逆序 的形式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以雷同模式返回一个示意和的链表。 你能够假如除了数字 0 之外,这两个数都不会以 0 结尾。 链接: 力扣Leetcode - 2、两数相加. 示例 1: 输出:l1 = [2,4,3], l2 = [5,6,4]输入:[7,0,8]解释:342 + 465 = 807.示例 2: 输出:l1 = [0], l2 = [0]输入:[0]示例 3: 输出:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]输入:[8,9,9,9,0,0,0,1]思路:因为两个链表都是逆序存储数字的位数的,因而两个链表中同一地位的数字能够间接相加。两个链表处相应地位的数字相加,可能就会有进位的状况产生,所以咱们设进位值为 carry 。则它们的和为 n1+n2+carry;其中,答案链表处相应地位的数字为 (n1+n2+carry)mod10,而新的进位值为 (n1+n2+carry)/10 。 Go代码: /** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */func addTwoNumbers(l1, l2 *ListNode) (head *ListNode) { var tail *ListNode carry := 0 for l1 != nil || l2 != nil { n1, n2 := 0, 0 if l1 != nil { n1 = l1.Val l1 = l1.Next } if l2 != nil { n2 = l2.Val l2 = l2.Next } sum := n1 + n2 + carry sum, carry = sum%10, sum/10 if head == nil { head = &ListNode{Val: sum} tail = head } else { tail.Next = &ListNode{Val: sum} tail = tail.Next } } if carry > 0 { tail.Next = &ListNode{Val: carry} } return}提交截图: ...

March 28, 2022 · 1 min · jiezi

关于golang:Go语言中一个fallthrough的使用问题

置信学习Go语言的小伙伴对fallthrough这个关键词并不生疏,与Java、PHP等语言不同,Go语言的switch case语句不须要在每个case前面增加break语句,默认在执行完case之后,会主动break,从switch语句中本义进去。 而咱们想要使程序能程序透传到下个case中,这时咱们就须要手动增加上fallthrough关键词,例如: package mainimport ( "fmt" "time")func main() { switch num := time.Now().Month(); { case num <= 3: fmt.Println("以后是第一季度") case num > 6: fmt.Println("以后是下半年") default: fmt.Println("未知月份") }}执行后后果当然会输入:以后是第一季度 而不会继续执行,输入“以后是下半年”或是“未知年份”的提醒。 这时我能够应用fallthrough关键词来强制执行上面的case语句的内容。 package mainimport ( "fmt" "time")func main() { switch num := time.Now().Month(); { case num <= 3: fmt.Println("以后是第一季度") fallthrough case num > 6: fmt.Println("以后是下半年") default: fmt.Println("未知月份") }}这时执行代码后,会输入 以后是第一季度 以后是下半年 这里咱们须要留神一下,fallthrough的透传会间接传递给下一个case,而不会去判断下一个case的条件。 但有一种状况是无奈应用fallthrough来进行透传的,示例如下: package mainimport ( "fmt")func main() { var num interface{} var num1 int = 1 num = num1 switch num.(type) { case int: fmt.Printf("以后num类型是:%T\n", num) fallthrough case float64: fmt.Printf("以后num类型是:%T\n", num) default: fmt.Printf("以后num类型是:%T\n", num) }}这时候,如果你应用vscode来开发,会提醒一个红色的波浪线,如图: ...

March 28, 2022 · 1 min · jiezi

关于golang:一篇文章搞懂Golang的error处理

Golang中的errorGolang中的 error 就是一个简略的接口类型。只有实现了这个接口,就能够将其视为一种 error type error interface { Error() string} error的几种玩法翻看Golang源码,能看到许多相似于上面的这两种error类型 哨兵谬误var EOF = errors.New("EOF")var ErrUnexpectedEOF = errors.New("unexpected EOF")var ErrNoProgress = errors.New("multiple Read calls return no data or error")毛病:1.让 error 具备二义性 error != nil不再意味着肯定产生了谬误比方io.Reader返回io.EOF来告知调用者没有更多数据了,然而这又不是一个谬误2.在两个包之间创立了依赖 如果你应用了io.EOF来查看是否read完所有的数据,那么代码里肯定会导入io包 自定义谬误类型一个不错的例子是os.PathError,它的长处是能够附带更多的上下文信息 type PathError struct { Op string Path string Err error} Wrap error到这里咱们能够发现,Golang 的 error 非常简单,然而简略也意味着有时候是不够用的Golang的error始终有两个问题:1.error没有附带file:line信息(也就是没有堆栈信息)比方这种error,鬼晓得代码哪一行报了错,Debug时几乎要命 SERVICE ERROR 2022-03-25T16:32:10.687+0800!!! Error 1406: Data too long for column 'content' at row 12.下层error想附带更多日志信息时,往往会应用fmt.Errorf(),fmt.Errorf()会创立一个新的error,底层的error类型就被“吞”掉了 var errNoRows = errors.New("no rows")// 模拟sql库返回一个errNoRowsfunc sqlExec() error { return errNoRows}func serviceNoErrWrap() error { err := sqlExec() if err != nil { return fmt.Errorf("sqlExec failed.Err:%v", err) } return nil}func TestErrWrap(t *testing.T) { // 应用fmt.Errorf创立了一个新的err,失落了底层err err := serviceNoErrWrap() if err != errNoRows { log.Println("===== errType don't equal errNoRows =====") }}-------------------------------代码运行后果----------------------------------=== RUN TestErrWrap2022/03/26 17:19:43 ===== errType don't equal errNoRows =====为了解决这个问题,咱们能够应用github.com/pkg/error包,应用errors.withStack()办法将err保存到withStack对象 ...

March 28, 2022 · 6 min · jiezi

关于golang:使用Go语言ORM库worm的SQL预处理功能

会话worm提供了Session办法用于创立带配置的会话。应用会话能够共用一组配置,例如:开启SQL预编译,或者是SQL日志输入配置。会话该当只用于一个go routine中, 通常在一个HTTP处理器中创立并应用会话。例如: func AddOrder(c *wego.WebContext) { session := worm.NewSession() session.ShowLog(true) var order dao.Order order.Create_time = time.Now().Unix() //..... var err error order.Id, err = dbs.Model(&order).Insert() if err != nil { log.Error(err) c.AbortWithText(510, err.Error()) return } c.WriteTextF(200, "%d", order.Id)}应用SQL语句预编译worm反对SQL语句的预编译,应用SQL语句预编译能够晋升数据库拜访的效率。在worm中能够通过三种形式开启SQL语句预编译:全局开启、会话中开启、语句中开启。 开启全局预编译 func main2() { dbcnn, err := initMySql("account:pwd@tcp(127.0.0.1:3306)/db?charset=utf8&parseTime=True") if err != nil { log.Error(err) } defer dbcnn.Close() err = worm.InitMysql(dbcnn) if err != nil { log.Error(err) return } worm.ShowSqlLog(true) //开启SQL语句预编译 worm.UsePrepare(true) //设置预编译stmt缓存的最大数量 worm.SetMaxStmtCacheNum(1000)}会话中开启预编译 ...

March 27, 2022 · 1 min · jiezi

关于golang:面试官来说一说Go语言的函数调用惯例

原文链接:面试官:来说一说Go语言的函数调用常规 前言哈喽,大家好,我是asong。良久没有更新了,最近因工作须要忙着写python,Go语言我都有些陌生了,然而我不能放弃Go语言,该学习还是要学习的,明天与大家聊一聊Go语言的函数调用常规,调用常规是调用方和被调用方对于参数和返回值传递的约定,Go语言的调用常规在1.17版本进行了优化,本文咱们就看一下两个版本的调用常规是什么样的吧~。1.17版本前栈传递在Go1.17版本之前,Go语言函数调用是通过栈来传递的,咱们应用Go1.12版本写个例子来看一下: package mainfunc Test(a, b int) (int, int) { return a + b, a - b}func main() { Test(10, 20)}执行go tool compile -S -N -l main.go能够看到其汇编指令,咱们分两局部来看,先看main函数局部: "".main STEXT size=68 args=0x0 locals=0x28 0x0000 00000 (main.go:7) TEXT "".main(SB), ABIInternal, $40-0 0x0000 00000 (main.go:7) MOVQ (TLS), CX 0x0009 00009 (main.go:7) CMPQ SP, 16(CX) 0x000d 00013 (main.go:7) JLS 61 0x000f 00015 (main.go:7) SUBQ $40, SP // 调配40字节栈空间 0x0013 00019 (main.go:7) MOVQ BP, 32(SP) // 基址指针存储到栈上 0x0018 00024 (main.go:7) LEAQ 32(SP), BP 0x001d 00029 (main.go:7) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB) 0x001d 00029 (main.go:7) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB) 0x001d 00029 (main.go:7) FUNCDATA $3, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB) 0x001d 00029 (main.go:8) PCDATA $2, $0 0x001d 00029 (main.go:8) PCDATA $0, $0 0x001d 00029 (main.go:8) MOVQ $10, (SP) // 第一个参数压栈 0x0025 00037 (main.go:8) MOVQ $20, 8(SP) // 第二个参数压栈 0x002e 00046 (main.go:8) CALL "".Test(SB) // 调用函数Test 0x0033 00051 (main.go:9) MOVQ 32(SP), BP // Test函数返回后复原栈基址指针 0x0038 00056 (main.go:9) ADDQ $40, SP // 销毁40字节栈内存 0x003c 00060 (main.go:9) RET // 返回 0x003d 00061 (main.go:9) NOP 0x003d 00061 (main.go:7) PCDATA $0, $-1 0x003d 00061 (main.go:7) PCDATA $2, $-1 0x003d 00061 (main.go:7) CALL runtime.morestack_noctxt(SB) 0x0042 00066 (main.go:7) JMP 0 0x0000 65 48 8b 0c 25 00 00 00 00 48 3b 61 10 76 2e 48 eH..%....H;a.v.H 0x0010 83 ec 28 48 89 6c 24 20 48 8d 6c 24 20 48 c7 04 ..(H.l$ H.l$ H.. 0x0020 24 0a 00 00 00 48 c7 44 24 08 14 00 00 00 e8 00 $....H.D$....... 0x0030 00 00 00 48 8b 6c 24 20 48 83 c4 28 c3 e8 00 00 ...H.l$ H..(.... 0x0040 00 00 eb bc .... rel 5+4 t=16 TLS+0 rel 47+4 t=8 "".Test+0 rel 62+4 t=8 runtime.morestack_noctxt+0通过下面的汇编指令咱们能够剖析出,参数10、20依照从右向左进行压栈,所以第一个参数在栈顶的地位SP~SP+8,第二个参数存储在SP+8 ~ SP+16,参数筹备结束后就去调用TEST函数,对应的汇编指令:CALL "".Test(SB),对应的汇编指令如下: ...

March 27, 2022 · 4 min · jiezi

关于golang:Golang-设计模式装饰模式

简略装璜器咱们通过一个简略的例子来看一下装璜器的简略利用,首先编写一个 hello 函数: package mainimport "fmt"func hello() { fmt.Println("Hello World!")}func main() { hello()}实现下面代码后,执行会输入“Hello World!”。接下来通过以下形式,在打印“Hello World!”前后各加一行日志: package mainimport "fmt"func hello() { fmt.Println("before") fmt.Println("Hello World!") fmt.Println("after")}func main() { hello()}代码执行后输入: `beforeHello World!after`当然咱们能够抉择一个更好的实现形式,即独自编写一个专门用来打印日志的 logger 函数,示例如下: package mainimport "fmt"func logger(f func()) func() { return func() { fmt.Println("before") f() fmt.Println("after") }}func hello() { fmt.Println("Hello World!")}func main() { hello := logger(hello) hello()}能够看到 logger 函数接管并返回了一个函数,且参数和返回值的函数签名同 hello 一样。而后咱们在原来调用 hello() 的地位进行如下批改: `hello := logger(hello)hello()`这样咱们通过 logger 函数对 hello 函数的包装,更加优雅的实现了给 hello 函数减少日志的性能。执行后的打印后果仍为: ...

March 27, 2022 · 1 min · jiezi

关于golang:行之有效的Golang编码规范

编码标准相熟编码标准能够帮忙咱们写出可读性高,可测试性高的代码同时编码标准也是小型重构的利器,当初咱们从命名,变量,循环,正文,函数等方面,谈谈如何从编码角度晋升整体我的项目品质。 命名1.命名的首要要求是精确直观地表白用意,主要要求是简短。 除了一些大家比拟熟知的缩写外,不举荐应用缩写。比方:sec 示意 second、str 示意 string、num 示意 number、doc 示意 document。2.命名的技巧是:动词➕宾语,也就是"谁干了什么事"比方:AddTopicDynamic => 增加主题动静 动词-Add 宾语-TopicDynamic3.用意义明确的常量代替魔法数字 有一次遇到一个if判断,心里曾经MMP了,鬼晓得这个 count*5 代表什么意思if (groupCount < count*5) { // 业务代码}4.分组命名常量比方:redis的key Dynamics = "xxx" // hashGlobalDynamic = "xxx" // 全局动静DynamicPushed = "xxx" // 用于标记动静是否已推送-------------------------------------------------// 应用前缀Key将常量分组,可读性更强KeyDynamics = "xxx" // hashKeyGlobalDynamic = "xxx" // 全局动静KeyDynamicPushed = "xxx" // 用于标记动静是否已推送变量1.要控制变量的作用域,应该private的变量绝不public。 2.要控制变量的存活工夫,变量的存活工夫越短,代码越易读,重构起来越简略。比方:在变量行将被应用时再初始化 // 优化前func Demo() { paramA := "A" // 业务代码1 // 业务代码2 paramA = "B"}---------------------------------------// 在变量行将被应用时再初始化,缩短变量生命周期func Demo() { // 业务代码1 // 业务代码2 paramA := "A" paramA = "B"}3.用布尔变量优化布尔判断 ...

March 26, 2022 · 2 min · jiezi

关于golang:高性能Go语言日志模块dlog使用说明

介绍dlog是用GO语言实现的一个简略高效、反对文件轮换以及日志分级的日志SDK。其特色如下: 采纳文件日志类型采纳了内存缓存,满足高性能输入日志。反对日志分级,具体分级如下: fatal (log.LOG_FATAL)error (log.LOG_ERROR)warn (log.LOG_WARN)info (log.LOG_INFO)debug (log.LOG_DEBUG)反对终端日志类型以及可依照工夫进行轮换的文件日志类型。文件日志类型反对依照天或小时进行轮换输入。装置阐明go get github.com/haming123/wego/dlog 应用文档请点击:具体文档 输入日志到终端dlog的缺省日志类型为:TermLogger(终端日志类型),应用TermLogger时不须要初始化,可间接应用日志输入函数输入日志。 package mainimport log "dlog"func main() { log.Debug("This is a Debug Message") log.Info("This is a Info Message")}//执行后的输入后果为://2021/11/30 07:20:06 [D] main.go:31 This is a Debug Message//2021/11/30 07:20:06 [I] main.go:32 This is a Debug Info日志级别dlog反对5个日志级别,别离是:fatal、error、warn、info、debug。 package mainimport log "dlog"func main() { log.Debug("This is Debug Message") log.Info("This is Info Message") log.Warn("This is Warn Message") log.Error("This is Error Message") log.Fatal("This is Fatal Message")}输入格局dlog反对为每个级别的日志提供了一个xxxf、xxxJSON、xxxXML的函数,用于输入不同格局日志: ...

March 26, 2022 · 2 min · jiezi

关于golang:Go-Timer-详解以及-Reset-和-Stop-的正确用法

time.TimerTimer 是 go 中 time 包里的一种一次性计时器,它的作用是定时触发事件,在触发之后这个 Timer 就会生效,须要调用 Reset() 来让这个 Timer 从新失效。 type Timer struct { C <-chan Time // contains filtered or unexported fields}这个是 Timer 类型的构造体,其中只有一个 channel 可供内部拜访,这个 channel 的作用就是在定时完结完结之后,会发送以后工夫到这个 channel 外面,所以在 channel 收到值的时候,就等于计时器超时了,能够执行定时的事件了。所以个别是和 select 语句搭配应用。 Timer 的底层原理在一个程序中,其中的所有计时器都是由一个运行着 timerproc() 函数的 goroutine 来保护。它采纳了工夫堆的算法来保护所有的 Timer,其底层的数据结构是基于数组的小根堆,堆顶的元素是间隔超时最近的 Timer,这个 goroutine 会定期 wake up,读取堆顶的 Timer,执行对应的 f 函数或者 send time,而后将其从堆顶移除。 time.NewTimer() 创立 Timerfunc NewTimer(d Duration) *Timertime.NewTimer() 是创立 Timer 的其中一种形式,通过传入一个定时工夫 d,time.NewTimer() 就会返回创立的 Timer 的指针,这个 Timer 会在通过 d 这么长的工夫工夫之后,向 Timer 中的 channel 发送以后工夫。 ...

March 26, 2022 · 2 min · jiezi

关于golang:使用Go语言web框架wego实现用户登录功能

介绍本文通过一个简略的例子阐明如何应用wego框架来实现用户登录性能。次要性能如下: 用户拜访须要进行登录验证的页面时,首先会查看session的登录账号,若没有登录账号,则跳转到登录页面。用户提交登录页面后,验证是否是非法的用户,若通过验证,则保留用户账号到session,并跳转到index页面。阐明:本例子采纳基于cookie引擎的session 我的项目的构造demo├── controller - 控制器目录│ └── base.go - 控制器根底struct│ └── home.go - home控制器│ └── login.go - 登录相干的处理器├── models - 模型目录├── logs - 日志文件目录├── static - 动态资源目录│ ├── css│ ├── img│ └── js├── view - 视图模板目录│ └── login.html│ └── index.html├── app.conf - 利用配置文件└── main.go - 入口文件配置文件的内容#利用名称app_name = demo[server]#http监听端口http_port = 8080[session]#session 是否开启session_on = true#session类型session_store=cookie#客户端的cookie的名称cookie_name = "wego"#session 过期工夫, 单位秒life_time = 3600#session数据的hash字符串hash_key = 123456重点阐明: http_port = 8080<< 服务将监听8080端口[session]<< 用于设置是否开启session,并设置session对应的缓存引擎,本例子中采纳基于cookie的sessionmain文件package mainimport ( "demo/controller" "github.com/haming123/wego" log "github.com/haming123/wego/dlog")func main() { web, err := wego.InitWeb() if err != nil{ log.Error(err) return } web.GET ("/show_login", controller.HandlerShowLogin) web.POST("/login_post", controller.HandlerLoginPost) web.GET ("/index", (*controller.HomeController).ShowHome) err = web.Run() if err != nil { log.Error(err) }}登录逻辑用户拜访须要进行登录验证的页面时,首先会查看session的登录账号,若没有登录账号,则跳转到登录页面, 登录页面的路由注册代码为: ...

March 26, 2022 · 2 min · jiezi

关于golang:使用Go语言ORM库worm访问mysql数据库

介绍worm是一款不便易用的Go语言ORM库,worm具备应用简略,运行性能高,功能强大的特点。具体特色如下: 通过Struct的Tag与数据库字段进行映射,让您免于常常拼写SQL的麻烦。反对Struct映射、原生SQL以及SQL builder三种模式来操作数据库,并且Struct映射、原生SQL以及SQL builder可混合应用。Struct映射、SQL builder反对链式API,可应用Where, And, Or, ID, In, Limit, GroupBy, OrderBy, Having等函数结构查问条件。可通过Join、LeftJoin、RightJoin来进行数据库表之间的关联查问。反对事务反对,可在会话中开启事务,在事务中能够混用Struct映射、原生SQL以及SQL builder来操作数据库。反对预编译模式拜访数据库,会话开启预编译模式后,任何SQL都会应用缓存的Statement,能够晋升数据库拜访效率。反对应用数据库的读写拆散模式来拜访一组数据库。反对在Insert,Update,Delete,Get, Find操作中应用钩子办法。反对SQL日志的输入,并且可通过日志钩子自定义SQL日志的输入,日志钩子反对Context。可依据数据库主动生成库表对应的Model构造体。目前worm反对的数据库有:mysql、postgres、sqlite、sqlserver。 装置go get github.com/haming123/wego/worm 应用文档请点击:具体文档 疾速开始创立实体类//建表语句CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(30) DEFAULT NULL, `age` int(11) DEFAULT NULL, `passwd` varchar(32) DEFAULT NULL, `created` datetime DEFAULT NULL, `updated` datetime DEFAULT NULL, PRIMARY KEY (`id`));数据库表user对应的实体类的定义如下: type User struct { Id int64 `db:"id;autoincr"` Name string `db:"name"` Age int64 `db:"age"` Passwd string `db:"passwd"` Created time.Time `db:"created;n_update"`}func (ent *User) TableName() string { return "user"}worm应用名称为"db"的Tag映射数据库字段,"db"前面是字段的名称,autoincr用于阐明该字段是自增ID,n_update用于阐明该字段不可用于update语句中。 ...

March 25, 2022 · 4 min · jiezi

关于golang:Go语言Web框架wego使用说明

简介wego是一个Go语言编写的高性能的Web框架,能够用来疾速开发RESTful服务以及后端服务等各种利用。wego框架是一个残缺的MVC框架,包含路由模块、数据库ORM模块、view模板解决以及Session模块。wego具备性能高、不便易用,兼容性好,扩展性强等特点,具体特色如下: 基于Radix树开发的路由模块,路由查问性能高。反对路由组。为路由参数、Query参数、Form参数的拜访提供率不便易于应用的API,并能够将参数映射到Struct。为JSON、XML和HTML渲染提供了易于应用的API。反对过滤器中间件,不便您对Web框架进行扩大。反对BeforeRoute、BeforeExec、AfterExec拦截器,不便您进行身份验证、日志输入。内置Crash解决机制,wego能够recover一个HTTP申请中的panic,这样可确保您的服务器始终可用。内置Config模块,不便对利用的参数进行治理。内置Session模块,您能够抉择cookie、redis、memcache、memory缓存引擎存储Session数据。内置ORM模块(开发中)。内置log模块,用于生成利用日志。采纳缓存来治理HTML的Template,既不便输入Html页面,又能够应用缓存晋升零碎性能。良好的兼容性,wego反对go原生的func(http.ResponseWriter, *http.Request)路由处理函数,这样您的代码大量批改就能够应用wego了。wego兼容两种编码习惯,能够应用一般函数作为路由处理函数,也能够应用strcut的成员函数作为路由处理函数。装置go get github.com/haming123/wego 应用文档请点击:具体文档 简略http server创立一个main.go文件,代码如下: package mainimport ( "github.com/haming123/wego" log "github.com/haming123/wego/dlog")func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.GET("/hello", func(c *wego.WebContext) { c.WriteText(200, "world") }) err = web.Run(":8080") if err != nil { log.Error(err) }}而后运行它,关上浏览器,输出http://localhost:8080/hello, 就能够看到如下内容: world我的项目构造wego框没有对我的项目构造做出限度,这里给出一个MVC框架我的项目的倡议构造: demo├── app │ └── router.go - 路由配置文件│ └── templfun.go - 模板函数文件├── controllers - 控制器目录,必要的时候能够持续划分子目录│ └── controller_xxx.go├── models - 模型目录│ └── model_xxx.go├── logs - 日志文件目录,次要保留我的项目运行过程中产生的日志│ └── applog_20211203.log├── static - 动态资源目录│ ├── css│ ├── img│ └── js├── utils - 公共代码目录│ └── util_xxx.go├── views - 视图模板目录│ └── html_xxx.html├── app.conf - 利用配置文件└── main.go - 入口文件注册参数路由func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.PATH("/user/:id", func(c *wego.WebContext) { c.WriteTextF(200, "param id=%s", c.RouteParam.GetString("id").Value) }) err = web.Run(":8080") if err != nil { log.Error(err) }}注册含糊匹配路由func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.PATH("/files/*name", func(c *wego.WebContext) { c.WriteTextF(200, "param name=%s", c.RouteParam.GetString("name").Value) }) err = web.Run(":8080") if err != nil { log.Error(err) }}注册RESTful路由func main() { web, err := wego.NewWeb() if err != nil{ log.Error(err) return } web.GET("/users/:id", func(c *wego.WebContext) { //查问一个用户 }) web.POST("/users/:id", func(c *wego.WebContext) { //创立一个用户 }) web.PUT("/users/:id", func(c *wego.WebContext) { //更新用户信息 }) web.PATCH("/users/:id", func(c *wego.WebContext) { //更新用户的局部信息 }) web.DELETE("/users/:id", func(c *wego.WebContext) { //删除用户 }) err = web.Run(":8080") if err != nil { log.Error(err) }}获取参数在wego中通过c.Param.GetXXX函数来获取申请参数: ...

March 25, 2022 · 4 min · jiezi

关于golang:作为-Gopher你知道-Go-的注释即文档应该怎么写吗

刚入门 Go 开发时,在开源我的项目的主页上咱们常常能够看到这样的一个徽章: 点击徽章,就能够关上 https://pkg.go.dev/ 的网页,网页中给出了这个开源我的项目所对应的 Go 文档。在刚接触 Go 的时候,我一度认为,pkg.go.dev 下面的文档是须要开发者上传并审核的——要不然那些文档咋都显得那么业余呢。 然而当我写本人的轮子时,缓缓的我就发现并非如此。划重点:在 pkg.go.dev 上的文档,都是 Go 主动从开源我的项目的工程代码中爬取、格式化后展示进去的。换句话说,每个人都能够写本人的 GoDoc 并且展现在 pkg.go.dev 上,只须要听从 GoDoc 的格局规范即可,也不须要任何审核动作。 本文章的目标是通过例子,简要阐明 GoDoc 的格局,让读者也能够本人写一段高大上的 godoc。以下内容以我本人的 jsonvalue 包为例子。其对应的 GoDoc 在这里。读者能够点开,并与代码中的内容做参考比照。 什么是 GoDoc顾名思义,GoDoc 就是 Go 语言的文档。在理论利用中,godoc 可能能够指以下含意: 在 2019.11 月之前,示意 https://godoc.org 中的内容当初 godoc.org 曾经下线,会重定向到 pkg.go.dev,并且其性能也都从新迁徙到这下面——下文以 “pkg.go.dev” 指代这个含意Go 开发工具的一个命令,就叫做 godoc——下文间接以 “godoc” 指代这个工具pkg.go.dev 的相干命令,被叫做 pkgsite,代码托管在 GitHub 上——下文以 “pkgsite” 指代这个工具Go 工具包的文档以及生成该文档所相干的格局——下文以 “GoDoc” 指代这个含意目前的 godoc 和 pkgsite 有两个作用,一个是用来本地调试本人的 GoDoc 显示成果;另一个是在无奈迷信上网的时候,用来本地搭建 GoDoc 服务器之用。 godoc 命令咱们从工具命令开始讲起吧。在 2019 年之前,Go 应用的是 godoc 这个工具来格式化和展现 Go 代码中自带的文档。当初这个命令曾经不再蕴含于 Go 工具链中,而须要额定装置: ...

March 24, 2022 · 3 min · jiezi

关于golang:开源服务lalserver支持多种鉴权防盗链方式

lalserver是纯Golang开发的流媒体服务器。目前已反对RTMP, RTSP(RTP/RTCP), HLS, HTTP[S]/WebSocket[S]-FLV/TS协定。 目前已反对多种鉴权防盗链的形式。 lal github地址: https://github.com/q191201771... ▌ 形式一. 固定值的鉴权参数首先,批改配置文件,如下: "conf_version": "v0.2.6",..."simple_auth": { "key": "q191201771", // 公有key,计算鉴权参数时应用 "dangerous_lal_secret": "pengrl", // 后门鉴权参数,所有的流可通过该参数值鉴权 "pub_rtmp_enable": true, // rtmp推流是否开启鉴权,true为开启鉴权,false为不开启鉴权 "sub_rtmp_enable": true, // rtmp拉流是否开启鉴权 "sub_httpflv_enable": true, // httpflv拉流是否开启鉴权 "sub_httpts_enable": true, // httpts拉流是否开启鉴权 "pub_rtsp_enable": true, // rtsp推流是否开启鉴权 "sub_rtsp_enable": true, // rtsp拉流是否开启鉴权 "hls_m3u8_enable": true // m3u8拉流是否开启鉴权}...形式一和形式二的配置都在配置项simple_auth下治理: pub和sub结尾的字段决定了各协定是否开启鉴权dangerous_lal_secret为鉴权参数的值key在上面形式二中应用,这里临时不关怀举例,没开启鉴权性能时,推rtmp流的url是rtmp://127.0.0.1:8080/live/test110开启后,业务方推流url是变为rtmp://127.0.0.1:8080/live/test110?lal_secret=pengrl其中lal_secret就是鉴权签名参数,名字是固定的,值也是固定的,对应配置文件中dangerous_lal_secret的值。 该鉴权形式,所有流都应用同一个鉴权参数值。 ▌ 形式二. MD5签名的鉴权参数首先,仍然是批改配置文件(参见下面形式一中的形容): pub和sub等结尾的字段决定了各协定是否开启鉴权key用来做MD5签名举例,没开启鉴权性能时,推rtmp流的url是rtmp://127.0.0.1:8080/live/test110开启后,业务方推流url是变为rtmp://127.0.0.1:8080/live/test110?lal_secret=700997e1595a06c9ffa60ebef79105b0 其中lal_secret就是鉴权签名参数,名字是固定的,值的计算公式是md5(配置文件中的simple_auth::key + 流名称) 下面的例子对应的计算形式是md5("q191201771test110") Go、c++代码以及命令行、网页工具如何计算MD5见:应用工具或代码生成MD5 - 仁亮笔记 该鉴权模式下,不同的流名称对应不同的鉴权参数。 留神,形式一和形式二可同时应用。lal_secret的值满足任意一种计算形式即可鉴权通过。 ▌ 形式三. 与业务方服务交互,自在定制鉴权形式大体的逻辑是,lalserver在接管到推流或者拉流申请时,应用http回调的形式告诉业务方的服务。业务方的服务依据本身的逻辑,断定这个推流或者拉流申请是否非法。如果不非法,应用lalserver提供的http api接口将该申请踢掉。 ...

March 22, 2022 · 1 min · jiezi

关于golang:Go进阶基础特性定时器

在理论的利用中,咱们常常会须要在特定的提早后,或者定时去做某件事情。这时就须要用到定时器了,Go 语言提供了一次性定时器 time.Timer 和周期型定时器 time.Ticker。 如何应用Timer 是一次性的定时器,通过指定的工夫后触发一个事件,这个事件通过其自身提供的 channel 进行告诉。与之相干的次要办法如下: // 创立 Timerfunc NewTimer(d Duration) *Timer// 进行 Timerfunc (t *Timer) Stop() bool// 重置 Timerfunc (t *Timer) Reset(d Duration) bool// 创立 Timer,返回它的 channelfunc After(d Duration) <-chan Time// 创立一个提早执行 f 函数的 Timerfunc AfterFunc(d Duration, f func()) *TimerTimer 的次要应用场景有: 设定超时工夫;提早执行某个办法。Ticker 是周期型定时器,即周期性的触发一个事件,通过 Ticker 提供的管道将事件传递进来。次要办法有: // 创立 Tickerfunc NewTicker(d Duration) *Ticker// 进行 Ticker,Ticker 在应用完后务必要开释,否则会产生资源泄露func (t *Ticker) Stop()// 启动一个匿名的 Ticker(无奈进行)func Tick(d Duration) <-chan TimeTicker 的应用场景都和定时工作无关,例如定时进行聚合等批量解决。 实现原理咱们先来看看 Timer 和 Ticker 的数据结构: ...

March 22, 2022 · 4 min · jiezi

关于golang:GO-语言-JSON-与-Cache-库-调研与选型

JSON基本上从以下两种角度进行剖析 性能方面,如是否应用反射;是否反对 Unmarshal 到 map 或 struct,未波及灵活性与扩展性方面,上面报告中只思考最简略的反序列化,不会提及每个库的灵活性,如提供的一些定制化抽取的 API;相干库GO 1.14 规范库 JSON 大量应用反射获取值,首先 go 的反射自身性能较差,其次频繁调配对象,也会带来内存调配和 GC 的开销; valyala/fastjson star: 1.4k 通过遍历 json 字符串找到 key 所对应的 value,返回其值 []byte,由业务方自行处理。同时能够返回一个 parse 对象用于屡次解析;只提供了简略的 get 接口,不提供 Unmarshal 到构造体或 map 的接口;tidwall/gjson star: 9.5k 原理与 fastjson 相似,但不会像 fastjson 一样将解析的内容保留在一个 parse 对象中,后续能够重复的利用,所以当调用 GetMany 想要返回多个值的时候,须要遍历 JSON 串屡次,因而效率会比拟低;提供了 get 接口和 Unmarshal 到 map 的接口,但没有提供 Unmarshal 到 struct 的接口;buger/jsonparser star: 4.4k 原理与 gjson 相似,有一些更灵便的 api;只提供了简略的 get 接口,不提供 Unmarshal 到构造体或 map 的接口;json-iterator star: 10.3k ...

March 22, 2022 · 2 min · jiezi

关于golang:Golang力扣Leetcode剑指Offer字符串58-I-翻转单词顺序库函数

题目:输出一个英文句子,翻转句子中单词的程序,但单词内字符的程序不变。为简略起见,标点符号和一般字母一样解决。例如输出字符串"I am a student. ",则输入"student. a am I"。 链接: 力扣Leetcode—剑指Offer—字符串—58 - I. 翻转单词程序. 示例 1: 输出: "the sky is blue"输入: "blue is sky the"示例 2: 输出: " hello world! "输入: "world! hello"解释: 输出字符串能够在后面或者前面蕴含多余的空格,然而反转后的字符不能包含。示例 3: 输出: "a good example"输入: "example good a"解释: 如果两个单词间有多余的空格,将反转后单词间的空格缩小到只含一个。思路:法一:用库函数 用 strings.TrimSpace(s) 去除字符串前后的空格用 strings.Split 宰割字符串存为一个 []string “b”将 b 中的字符串翻转遍历翻转后的字符串,将不为 "" 的字符串退出 res 字符串切片中将 res 字符串切片连贯为一个字符串,之间用 " " 来分隔。法二:最死板的办法 先去掉空格再反转字符串最初反转单词法一Go代码: package mainimport ( "fmt" "strings")func reverseWords(s string) string { var res []string a := strings.TrimSpace(s) // 去除字符串前后的空格 b := strings.Split(a, " ") // 宰割字符串存为一个[]string //字符串翻转 for i := 0; i < len(b)>>1; i++ { b[i], b[len(b)-1-i] = b[len(b)-1-i], b[i] } //解决字符串两头的空格,遍历翻转后的字符串,将不为""的字符串退出 res 字符串切片中 for i, _ := range b { if b[i] != "" { res = append(res, b[i]) } } //将字符串切片连贯为一个字符串,之间用 " " 来分隔。 return strings.Join(res, " ")}func main() { fmt.Println(reverseWords("the sky is blue."))}提交截图: ...

March 22, 2022 · 2 min · jiezi

关于golang:GO-语言插件设计调研报告

典型场景-微内核架构可浏览去哪儿网的落地实际分享。 从上到下隔离级别逐步递增,灵活性逐步增高,性能逐步降落,因而在选型时须要思考插件是否是高频调用,耗时要求如何; Go 语言落地实现如上述可知,去哪儿网采纳了 Spring 生态下提供的运行时插件设计,是基于 java 语言的实现,以下给出几种基于 Go 语言的实现计划; 编译时插件 - 代码级别的隔离应用引包的形式,进行依赖注入,相似于 go 规范库中的 database/sql; 运行时插件plugin原理可见:GO 语言设计与实现 8.1 插件零碎,利用了操作系统的动静库链接能力实现模块化的设计,go/plugin -> cgo -> c -> 操作系统对于具体内容可见 一文搞懂Go语言的plugin,在此做摘要介绍:问题有如下问题,因而并未被宽泛应用 官网只明确说反对 Linux、FreeBSD 和 macOS,因而其余零碎是否反对不能确定,且即便能够应用,会不会有潜藏危险无从得悉;当一个插件第一次被open时,plugin中所有不属于主程序的包的init函数将被调用,但一个插件只被初始化一次,而且不能被敞开;若主程序和插件包依赖同一第三方库,则该独特依赖包的版本必须统一;若主程序或插件库任一一方采纳 vendor 构建,则主程序和插件包必须基于同一个 vendor 目录构建;主程序和插件库应用的编译器的版本必须统一;应用插件库的主程序只能应用动静链接,不能应用动态链接;对于插件的版本,若插件名雷同,内容也雷同,主程序屡次 load 不会呈现问题;但若插件名雷同,但内容不同,主程序运行时屡次 load 会导致无奈复原的 panic。因而插件版本治理须要留神。解法依据下面看到的种种束缚,如果要利用go plugin,必须要做到: 构建环境统一对第三方包的版本统一。因而,业内在应用go plugin时多利用builder container(用来构建程序的容器)来保障主程序和plugin应用雷同的构建环境。在go plugin为数不多的用户中,有三个比拟出名的开源我的项目值得后续认真钻研: gosh: https://github.com/vladimirvi...tyk api gateway: https://github.com/TykTechnol...tidb : https://github.com/pingcap/tidb,并给出了其插件零碎应用go plugin的残缺设计方案:https://github.com/pingcap/ti...远端插件 - 过程级别隔离hashicorp/go-pluginhttps://github.com/hashicorp/... 小结实例间无差别部署,通过回环地址或 unix 域套接字实现本地插件拜访,每个机器上内部署雷同的插件,归为远端插件,理论仍是本地插件计划; 问题 reattach (服务重启从新加载插件)须要业务代码本人记录下插件的pid和addr,能力实现;只实现了单个插件的加载,没有实现多个插件的治理,如果要治理多个插件的话,还是须要业务代码里自行去组织;并不是一套残缺的本地插件解决方案,只实现了根本的 server 与插件的交互逻辑,在插件的管控上依然须要自行设计、治理。其余计划另有一种未开源计划,基于 ZK 进行插件的中心化管控,不同的机器上部署有不同的插件,实现插件的有差异部署。业务服务从 ZK 中取到插件 IP、Port 信息通过 grpc 协定进行拜访,是真正的网络插件。 ...

March 22, 2022 · 1 min · jiezi

关于golang:GO-语言内存泄漏排查两例

例1:Goroutine 透露景象NumGoroutine 指标继续上涨,且低峰期未降落,判断呈现了 Goroutine 透露景象。 排查通过拜访线上服务 pprof 裸露进去的 HTTP 接口,拿到以后所有协程的堆栈信息;curl http://「ip:port」/debug/pprof/goroutine?debug\=2发现存在大量存活工夫超过上千分钟的 Goroutine,察看堆栈疑似是 http 连贯未开释导致,通过对下图 net.sockets.tcp.inuse(正在应用的tcp socket数量)指标的察看进行了进一步的确认;论断http上面以本次 case http 服务为例,做简略介绍: 上游服务作为客户端应用了 http1.1 并且将连贯设置为 keepalive;本服务作为服务端未设置 idletimeout 与 readtimeout;当这两种状况同时产生时,如果上游持有对本服务的连贯不进行开释,那么服务端会始终维持这个连贯的存在,不进行回收,进而导致协程透露; client上游客户端可能为 GO、Java 等,以下为 GO 语言 http 客户端的闲暇连贯超时设置;server解决倡议启动 http server 尽量用后者,前者尽管简略,然而服务不够强壮; thriftserver Tips须要留神的一点是,这个 Goroutine 透露问题不止在 http 下会产生,在 thrift、grpc 中也是同样的情理,如果服务端不对连贯设置 timeout,某些状况下就会被上游拖死。 Referencehttps://zhuanlan.zhihu.com/p/... 例2:内存居高不下景象内存使用量(mem.rss)居高不下,且低峰期未降落,狐疑产生了内存透露景象; 排查刚开始狐疑时内存透露,然而抓取 pprof heap 图察看后,未发现泄露问题,且内存调配合乎预期;发现内存应用尽管居高不下,但未呈上涨趋势,因而批改关键字为“go 内存占用居高不下”,发现有雷同问题;论断问题来自于 GO 在将内存归还给操作系统时的内存开释策略,详情见官网 issues,以下做简略介绍。 GO 内存开释策略(此节内容整顿自 压测后go服务内存暴涨) 不同策略的开释机制 MADV_DONTNEED:内核将会在适合的机会去开释内存,但过程的 RSS(常驻内存)将会立刻缩小。如果再次申请内存,内核会重新分配一块新的空间。MADV_FREE:只能在 linux 内核版本 4.5 以上能力应用,此操作实践上只是打了一个标记位,只有在内核感觉到内存压力的时候才会将这些打标记的内存回收掉,调配给其余过程应用。这个策略下过程的 RSS 不会立刻缩小。不同策略的理论差异 ...

March 22, 2022 · 1 min · jiezi

关于golang:带你十天轻松搞定-Go-微服务系列三

序言咱们通过一个系列文章跟大家具体展现一个 go-zero 微服务示例,整个系列分十篇文章,目录构造如下: 环境搭建服务拆分用户服务(本文)产品服务订单服务领取服务RPC 服务 Auth 验证服务监控链路追踪分布式事务冀望通过本系列带你在本机利用 Docker 环境利用 go-zero 疾速开发一个商城零碎,让你疾速上手微服务。 残缺示例代码:https://github.com/nivin-studio/go-zero-mall 首先,咱们来更新一下上篇文章中的服务拆分图片,因为微信公众号手机和电脑端不同步,导致丑化的图片没有跟大家见面,特此补上,如图: 3 用户服务(user)进入服务工作区$ cd mall/service/user3.1 生成 user model 模型创立 sql 文件$ vim model/user.sql编写 sql 文件CREATE TABLE `user` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL DEFAULT '' COMMENT '用户姓名', `gender` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '用户性别', `mobile` varchar(255) NOT NULL DEFAULT '' COMMENT '用户电话', `password` varchar(255) NOT NULL DEFAULT '' COMMENT '用户明码', `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `idx_mobile_unique` (`mobile`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;运行模板生成命令$ goctl model mysql ddl -src ./model/user.sql -dir ./model -c3.2 生成 user api 服务创立 api 文件$ vim api/user.api编写 api 文件type ( // 用户登录 LoginRequest { Mobile string `json:"mobile"` Password string `json:"password"` } LoginResponse { AccessToken string `json:"accessToken"` AccessExpire int64 `json:"accessExpire"` } // 用户登录 // 用户注册 RegisterRequest { Name string `json:"name"` Gender int64 `json:"gender"` Mobile string `json:"mobile"` Password string `json:"password"` } RegisterResponse { Id int64 `json:"id"` Name string `json:"name"` Gender int64 `json:"gender"` Mobile string `json:"mobile"` } // 用户注册 // 用户信息 UserInfoResponse { Id int64 `json:"id"` Name string `json:"name"` Gender int64 `json:"gender"` Mobile string `json:"mobile"` } // 用户信息)service User { @handler Login post /api/user/login(LoginRequest) returns (LoginResponse) @handler Register post /api/user/register(RegisterRequest) returns (RegisterResponse)}@server( jwt: Auth)service User { @handler UserInfo post /api/user/userinfo() returns (UserInfoResponse)}运行模板生成命令$ goctl api go -api ./api/user.api -dir ./api3.3 生成 user rpc 服务创立 proto 文件$ vim rpc/user.proto编写 proto 文件syntax = "proto3";package userclient;option go_package = "user";// 用户登录message LoginRequest { string Mobile = 1; string Password = 2;}message LoginResponse { int64 Id = 1; string Name = 2; int64 Gender = 3; string Mobile = 4;}// 用户登录// 用户注册message RegisterRequest { string Name = 1; int64 Gender = 2; string Mobile = 3; string Password = 4;}message RegisterResponse { int64 Id = 1; string Name = 2; int64 Gender = 3; string Mobile = 4;}// 用户注册// 用户信息message UserInfoRequest { int64 Id = 1;}message UserInfoResponse { int64 Id = 1; string Name = 2; int64 Gender = 3; string Mobile = 4;}// 用户信息service User { rpc Login(LoginRequest) returns(LoginResponse); rpc Register(RegisterRequest) returns(RegisterResponse); rpc UserInfo(UserInfoRequest) returns(UserInfoResponse);}运行模板生成命令$ goctl rpc proto -src ./rpc/user.proto -dir ./rpc增加下载依赖包 ...

March 22, 2022 · 6 min · jiezi

关于golang:golang-开发框架文档集

istio我的项目简介:Istio是由Google、IBM和Lyft开源的微服务治理、爱护和监控框架。应用istio能够很简略的创立具备负载平衡、服务间认证、监控等性能的服务网络,而不须要对服务的代码进行任何批改。 仓库地址:https://github.com/istio/istio 官网文档地址:https://istio.io/latest/docs/ Go-kit我的项目简介:Go-kit 是一个 Go 语言的分布式开发包,用于开发微服务。 仓库地址:https://github.com/go-kit/kit/ 官网文档地址:https://gokit.io/ Go-kratos我的项目简介:哔哩哔哩开源的一套Go微服务框架,蕴含大量微服务相干框架及工具。 仓库地址:https://github.com/go-kratos/... 官网文档地址:https://go-kratos.dev/docs/ Go-micro我的项目简介:Micro是一个专一于简化分布式系统开发的微服务生态系统。可插拔的插件化设计,提供弱小的可插拔的架构来保障根底组件能够被灵便替换。 仓库地址:https://github.com/micro/micro 官网文档地址:https://micro.mu/ Go-zero我的项目简介:go-zero 是一个集成了各种工程实际的 web 和 rpc 框架。 仓库地址:https://github.com/tal-tech/g... Goa我的项目简介:Goa 是一款用 Go 用于构建微服务的框架,采纳独特的设计优先的办法 仓库地址:https://github.com/goadesign/goa 官网文档地址:https://goa.design/ gizmo我的项目简介:gizmo是纽约时报开源的go微服务工具,提供如下个性:标准化配置和日志;可配置策略的状态监测端点;用于治理 pprof 端点和日志级别的配置;结构化日志,提供根本申请信息;端点的有用度量;优雅的进行服务; 定义期待和词汇的根本接口。 仓库地址:https://github.com/nytimes/gizmo Dubbo-go我的项目简介:阿里系,由Apache 软件基金会官网公布Go 语言退出 Dubbo 生态,架构是基于dubbo的extension模块和分层的代码设计,次要解决 Go 我的项目与 Java & Dubbo 我的项目的互通问题,同时也为 Go 我的项目提供了一种 RPC 与微服务 仓库地址:https://github.com/apache/dub... 官网文档地址:https://dubbogo.github.io/dub... Jupiter我的项目简介:斗鱼开源的一套微服务治理框架,提供丰盛的后盾性能,治理利用的资源、配置,利用的性能、配置等可视化。 仓库地址:https://github.com/douyu/jupiter 官网文档地址:http://jupiter.douyu.com/ Tars-go我的项目简介:腾讯系,Tarsgo是基于Golang编程语言应用Tars协定的高性能RPC框架 仓库地址:https://github.com/TarsCloud/... 官网文档地址:https://tarscloud.github.io/T...

March 22, 2022 · 1 min · jiezi

关于golang:Go进阶基础特性反射

定义反射是什么?来自维基百科的定义是:在计算机学中,反射是指计算机程序在运行时能够拜访、检测和批改它自身状态或行为的一种能力。用比喻来说,反射就是程序在运行的时候可能 “察看” 并且批改本人的行为。《Go 程序设计语言》中则是这样定义的:Go 语言提供了一种机制在运行时更新变量和查看它们的值、调用它们的办法,然而在编译时并不知道这些变量的具体类型,这称为反射机制。 应用场景和毛病应用反射的常见场景有两种: 函数的参数类型不能确定,须要在运行时解决任意对象。不能确定调用哪个函数,须要依据传入的参数在运行时决定。反射机制能带给咱们很大的灵活性,不过绝大多数状况下还是不举荐应用,次要理由有: 与反射相干的代码个别可读性都比拟差。反射相干的代码通常在运行时才会裸露谬误,这时常常是间接 panic,可能会造成重大的结果。反射对性能影响比拟大,比失常代码运行速度慢一到两个数量级。所以这是一把双刃剑,因而要想应用好,必须得明确其中的基本原理。 实现原理reflect.TypeOf 和 reflect.ValueOf 是进入反射世界仅有的两扇“大门”。顾名思义,这两个函数返回的别离是接口变量的类型信息和值信息,首先来看一下这两个函数。 reflect.TypeOffunc TypeOf(i interface{}) Type { eface := *(*emptyInterface)(unsafe.Pointer(&i)) return toType(eface.typ)}type emptyInterface struct { typ *rtype word unsafe.Pointer}func toType(t *rtype) Type { if t == nil { return nil } return t}注:传入反射函数如 TypeOf 等的参数(interface 类型)是在编译阶段进行类型转换的。 emptyInterface 和上一篇文章中提到的空接口类型 eface 是一样的,只是属性名不同而已,typ 是接口变量的动静类型,word 是动静值的指针。那么这个函数的逻辑就很明确了:应用 unsafe.Pointer 办法获取接口变量的指针值,将之强制转换为 emptyInterface 类型,并返回它的动静类型。 返回值 Type 实际上是一个接口,定义了很多办法,用来获取类型相干的各种信息,而 *rtype 实现了 Type 接口。Type 定义了很多无关类型的办法,倡议都大抵过一遍。 type Type interface { // 所有的类型都能够调用上面这些函数 // 此类型的变量对齐后所占用的字节数 Align() int // 如果是 struct 的字段,对齐后占用的字节数 FieldAlign() int // 返回类型办法集里的第 `i` (传入的参数)个办法 Method(int) Method // 通过名称获取办法 MethodByName(string) (Method, bool) // 获取类型办法集里导出的办法个数 NumMethod() int // 类型名称 Name() string // 返回类型所在的门路,如:encoding/base64 PkgPath() string // 返回类型的大小,和 unsafe.Sizeof 性能相似 Size() uintptr // 返回类型的字符串示意模式 String() string // 返回类型的类型值 Kind() Kind // 类型是否实现了接口 u Implements(u Type) bool // 是否能够赋值给 u AssignableTo(u Type) bool // 是否能够类型转换成 u ConvertibleTo(u Type) bool // 类型是否能够比拟 Comparable() bool // 上面这些函数只有特定类型能够调用 // 如:Key, Elem 两个办法就只能是 Map 类型能力调用 // 类型所占据的位数 Bits() int // 返回通道的方向,只能是 chan 类型调用 ChanDir() ChanDir // 返回类型是否是可变参数,只能是 func 类型调用 // 比方 t 是类型 func(x int, y ... float64) // 那么 t.IsVariadic() == true IsVariadic() bool // 返回外部子元素类型,只能由类型 Array, Chan, Map, Ptr, or Slice 调用 Elem() Type // 返回构造体类型的第 i 个字段,只能是构造体类型调用 // 如果 i 超过了总字段数,就会 panic Field(i int) StructField // 返回嵌套的构造体的字段 FieldByIndex(index []int) StructField // 通过字段名称获取字段 FieldByName(name string) (StructField, bool) // FieldByNameFunc returns the struct field with a name // 返回名称合乎 func 函数的字段 FieldByNameFunc(match func(string) bool) (StructField, bool) // 获取函数类型的第 i 个参数的类型 In(i int) Type // 返回 map 的 key 类型,只能由类型 map 调用 Key() Type // 返回 Array 的长度,只能由类型 Array 调用 Len() int // 返回类型字段的数量,只能由类型 Struct 调用 NumField() int // 返回函数类型的输出参数个数 NumIn() int // 返回函数类型的返回值个数 NumOut() int // 返回函数类型的第 i 个值的类型 Out(i int) Type // 返回类型构造体的雷同局部 common() *rtype // 返回类型构造体的不同局部 uncommon() *uncommonType}reflect.ValueOftype Value struct { typ *rtype ptr unsafe.Pointer flag}func ValueOf(i interface{}) Value { if i == nil { return Value{} } escapes(i) return unpackEface(i)}func unpackEface(i interface{}) Value { e := (*emptyInterface)(unsafe.Pointer(&i)) t := e.typ if t == nil { return Value{} } f := flag(t.Kind()) if ifaceIndir(t) { f |= flagIndir } return Value{t, e.word, f}}ValueOf 的逻辑也比较简单:首先调用 escapes 让变量 i 逃逸到堆上,而后将变量 i 强制转换为 emptyInterface 类型,最初将所需的信息组装成 reflect.Value 类型后返回。reflect.Value 的构造和 emptyInterface 也很像,只是多个示意元数据的 flag 字段。 ...

March 21, 2022 · 3 min · jiezi

关于golang:Golang力扣Leetcode剑指Offer字符串58-II-左旋转字符串

题目:字符串的左旋转操作是把字符串后面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的性能。比方,输出字符串"abcdefg"和数字2,该函数将返回左旋转两位失去的后果"cdefgab"。 链接: 力扣Leetcode—剑指Offer—字符串—58 - II. 左旋转字符串. 示例 1: 输出: s = "abcdefg", k = 2输入: "cdefgab"示例 2: 输出: s = "lrloseumgh", k = 6输入: "umghlrlose"思路:在编程的时候,全面地思考问题是很重要的,n 可能是一个远大于字符串长度的整数,循环右移不难发现,右移 n 位之后的情景,跟右移 n % len(s) 位之后的情景一样,再进行字符串拼接 res := s[n:number] + s[0:n] 就是答案了。 Go代码: package mainimport "fmt"func reverseLeftWords(s string, n int) string { number := len(s) if s == "" || number == 0 { return s } n = n % number // 取余,旋转的位数可能大于字符串的长度,旋转一周字符串等于没变 res := s[n:number] + s[0:n] return res}func main() { fmt.Println(reverseLeftWords("lrloseumgh", 6))}提交截图: ...

March 21, 2022 · 1 min · jiezi

关于golang:用-Go-语言造了一个全新的-kv-存储引擎

经验了大略 4 个月的打磨,LotusDB 的第一个 release 版本终于公布了,我看了下,有 200 屡次 commit(靠近 rosedb 一年多的 commit 次数了)。 我的项目地址:https://github.com/flower-cor... 有了 rosedb 在 bitcask 模型上的实际之后,以及本人在存储这方面的一些教训积攒,去年底的时候,在下班路上忽然想到的一个 idea,让我有了做一个新的 kv 存储引擎的想法。 有了想法之后便是验证,因为其实心里还是没谱,我又在 Github 上翻了翻,并没有同类型的实现。起初又找一些大佬沟通了下,证实我的想法是可行的。 这期间还发现了 Usenix Fast 上的一篇对于优化 LSM 的论文,发现论文的内容跟我的 idea 十分相似,这算是又多了一个理论依据,于是便决定开干了。 感兴趣的能够参考下论文,叫做 SLM-DB,地址:https://www.usenix.org/confer...家喻户晓,数据存储引擎,目前最支流的两种模型是 B+ 树和 LSM 树,B+ 树在关系型数据库例如 Mysql 中利用比拟宽泛,而 LSM 的典型代表 rocksdb 也是大多数分布式系统数据落盘的首选。 B+ 树读性能稳固,而 LSM 写吞吐高,LotusDB 在这根底上做了一个微小的改变,就是齐全舍弃掉 LSM 中的 SST 文件,改由 B+ 树来存储索引,而 value 寄存则参考了 Wisckey 和 bitcask 模型的设计,存储到独自的 value log 文件中。 LotusDB 是对 LSM 和 B+ 树的劣势联合,目前并没有同类型的实现,咱们应该是第一个吃螃蟹的人。 ...

March 21, 2022 · 2 min · jiezi

关于golang:Go-118-新特性多模块工作区教程让多模块开发变得简单

导读随着 2020 年 3 月 15 日 go 1.18 正式公布,新版本除了对性能的晋升之外,还引入了很多新性能,其中就有 go 期盼已久的性能泛型(Generics),同时还引入的多模块工作区(Workspaces)和含糊测试(Fuzzing)。对于泛型网上曾经有很多介绍的教程了,这里我介绍一个实用的性能,多模块工作区的应用办法和教程。Go 多模块工作区可能使开发者可能更容易地同时解决多个模块的工作,如: 不便进行依赖的代码调试(打断点、批改代码)、排查依赖代码 bug 不便同时进行多个仓库/模块并行开发调试目录多模块工作区开发流程演示总结参考文献多模块工作区阐明go 应用的是多模块工作区,能够让开发者更容易同时解决多个模块的开发。在 Go 1.17 之前,只能应用 go.mod replace 指令来实现,如果你正巧是同时进行多个模块的开发,应用它可能是很苦楚的。每次当你想要提交代码的时候,都不得不删除掉 go.mod 中的 replace 能力使模块稳固的公布版本。在应用 go 1.18 多模块工作区性能的时候,就应用这项工作变得简略容易解决。上面我来介绍怎么应用这一性能。Go 多模块工作区文档、代码示例获取地址 https://github.com/link1st/li...应用条件首先 咱们须要 go 1.18 或更高版本 go 装置# 查看 go 版本> go versiongo version go1.18 darwin/amd64go work 反对命令通常状况下,倡议不要提交 go.work 文件到 git 上,因为它次要用于本地代码开发。举荐在: $GOPATH 门路下执行,生成 go.work 文件go work init 初始化工作区文件,用于生成 go.work 工作区文件 初始化并写入一个新的 go.work 到以后门路下,能够指定须要增加的代码模块 示例: go work init ./hello 将本地仓库 hello 增加到工作区 hello 仓库必须是 go mod 依赖治理的仓库(./hello/go.mod 文件必须存在)go work use 增加新的模块到工作区 ...

March 21, 2022 · 3 min · jiezi

关于golang:Golang-基础之函数使用-二

大家好,明天将梳理出的 Go语言函数用法内容,分享给大家。 请多多指教,谢谢。 本次《Go语言函数应用》内容共分为三个章节,本文为第二章节。 Golang 根底之函数应用 (一)Golang 根底之函数应用 (二)Golang 根底之函数应用 (三)本章节内容匿名函数闭包递归函数提早调用 (defer)匿名函数介绍在Go语言中,函数能够像一般变量一样被传递或应用,反对随时在代码里定义匿名函数。 匿名函数由一个不带函数名的函数申明和函数体组成。匿名函数的优越性在于能够间接应用函数内的变量,不用申明。 匿名函数有动态创建的个性,该个性使得匿名函数不必通过参数传递的形式,就能够间接援用内部的变量。 应用第一种用法:将匿名函数赋给变量,在通过变量调用匿名函数 sum := func(a, b int) int { return a + b}fmt.Println(sum(1, 2)) // 输入 3第二种用法:在定义匿名函数的时候间接应用,这种形式只能应用一次传参 sum := func(a, b int) int { return a + b}(1,2) // 传入参数fmt.Println(sum) // 输入 3第三种用法:将匿名函数赋给一个全局变量,匿名函数在以后程序中都能够应用 package mainimport "fmt"var ( // 全局变量必须首字母大写 Sum = func(a, b int) int { return a + b })func main() { sum := Sum(1, 2) fmt.Println("sum=", sum) // 输入 sum= 3}闭包介绍所谓“闭包”,指的是一个领有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因此这些变量也是该表达式的一部分。 ...

March 20, 2022 · 3 min · jiezi

关于golang:golang-读取文件的几种方式

// ReadOne 读取到file中,再利用ioutil将file间接读取到[]byte中func ReadOne() string { file, err := os.Open("file/test") if err != nil { fmt.Println("read file fail", err) return "" } defer file.Close() content, err := ioutil.ReadAll(file) if err != nil { fmt.Println("read to fd fail", err) return "" } return string(content)}// WriteOne 应用 bufio.NewWriter 写文件func WriteOne() { fileName := "file/test3" file, err3 := os.Create(fileName) //创立文件 defer file.Close() if err3 != nil { fmt.Println("create file fail") } writer := bufio.NewWriter(file) //创立新的 Writer 对象 _, err := writer.WriteString("bufferedn") if err != nil { fmt.Println("write fail") } writer.Flush()}// ReadTwo 利用ioutil.ReadFile间接从文件读取到[]byte中func ReadTwo() string { f, err := ioutil.ReadFile("file/test") if err != nil { fmt.Println("read fail", err) } return string(f)}// WriteTwo 应用 ioutil.WriteFile 写文件func WriteTwo() { fileName := "file/test2" strTest := "测试测试" var d = []byte(strTest) err := ioutil.WriteFile(fileName, d, 0666) if err != nil { fmt.Println("write fail") } fmt.Println("write success")}图一、io.Reader/Writer之间的关系 ...

March 20, 2022 · 1 min · jiezi

关于golang:golang-写入文件的四种方法

go中写入数据到文件中有以下四种办法1.bufio.NewWriter2.io.WriteString3.ioutil.WriteFile4.File(Write,WriteString) package mainimport ( "bufio" //缓存IO "fmt" "io" "io/ioutil" //io 工具包 "os")func main() { var wireteString = "测试n" var filename = "./output1.txt" var f *os.File var err1 error /***************************** 第一种形式: 应用 io.WriteString 写入文件 ***********************************************/ if checkFileIsExist(filename) { //如果文件存在 f, err1 = os.OpenFile(filename, os.O_APPEND, 0666) //关上文件 fmt.Println("文件存在") } else { f, err1 = os.Create(filename) //创立文件 fmt.Println("文件不存在") } check(err1) n, err1 := io.WriteString(f, wireteString) //写入文件(字符串) check(err1) fmt.Printf("写入 %d 个字节n", n) /***************************** 第二种形式: 应用 ioutil.WriteFile 写入文件 ***********************************************/ var d1 = []byte(wireteString) err2 := ioutil.WriteFile("./output2.txt", d1, 0666) //写入文件(字节数组) check(err2) /***************************** 第三种形式: 应用 File(Write,WriteString) 写入文件 ***********************************************/ f, err3 := os.Create("./output3.txt") //创立文件 check(err3) defer f.Close() n2, err3 := f.Write(d1) //写入文件(字节数组) check(err3) fmt.Printf("写入 %d 个字节n", n2) n3, err3 := f.WriteString("writesn") //写入文件(字节数组) fmt.Printf("写入 %d 个字节n", n3) f.Sync() /***************************** 第四种形式: 应用 bufio.NewWriter 写入文件 ***********************************************/ w := bufio.NewWriter(f) //创立新的 Writer 对象 n4, err3 := w.WriteString("bufferedn") fmt.Printf("写入 %d 个字节n", n4) w.Flush() f.Close()}func check(e error) { if e != nil { panic(e) }}/** * 判断文件是否存在 存在返回 true 不存在返回false */func checkFileIsExist(filename string) bool { var exist = true if _, err := os.Stat(filename); os.IsNotExist(err) { exist = false } return exist}

March 20, 2022 · 1 min · jiezi

关于golang:golang-中接口-指针类型和值类型方法区别

类型 T 的可调用办法集蕴含接受者为 T 或 T 的所有办法集这条规定说的是如果咱们用来调用特定接口办法的接口变量是一个指针类型,那么办法的接受者能够是值类型也能够是指针类型. 类型 T 的可调用办法集蕴含接受者为 T 的所有办法** package mainimport "fmt"func main() { //能够调用 *T T类型的办法 var te1 myPerson //接口类型 te1 = &Person{ Name: "小马", Age: 10, } te1.setName() te1.setPerAge() fmt.Println(te1) //只能调用 T 类型的办法 var people myPeople people = Person{ Name: "小河", Age: 5, } people.setAge() fmt.Println(people)}// Person 定义构造体type Person struct { Name string Age int}//定义接口type myPerson interface { setName() setPerAge()}//定义接口type myPeople interface { setAge() //setPeopleName()}func (p *Person) setName() { p.Name = "小呼"}func (p Person) setPerAge() { fmt.Println("输入年龄:", p.Age)}func (p Person) setAge() { p.Age = 18}//func (p *Person) setPeopleName() {// p.Name = "测试"//}参考:https://blog.csdn.net/suiban7... ...

March 20, 2022 · 1 min · jiezi

关于golang:goalng-中结构体方法的区别使用

package mainimport "fmt"//不论调用模式如何(调用者是值类型还是援用类型),真正决定是值拷贝还是地址拷贝的,要看办法的接收者是什么类型;//如: (p Person) 则进行的是值拷贝,(p *Person) 是地址拷贝;// 申明的变量, 不论是值类型,指针类型, 都能够调用setAge办法,setName 办法func main() { //var p Person //var p = new(Person) //var p3 = &Person{} var p4 = Person{ Name: "小明", Age: 12, } p4.setName() p4.setAge() fmt.Println(p4) var p5 = Person{ Name: "小笨", Age: 8, } p5.setName() p5.setAge() fmt.Println(p5)}type Person struct { Name string Age int}// 接收者为实例变量的正本,在办法内更改值不会影响原来的值func (p Person) setAge() { p.Age = 16}//接收者为实例变量地址的正本,在办法内更改值会扭转原来的值func (p *Person) setName() { p.Name = "小江"}

March 20, 2022 · 1 min · jiezi

关于golang:Golang中空接口的使用

Go语言中的空接口是接口类型的一种非凡的模式,即是一个没有任何办法的接口。因为,空接口没有任何办法,因而,咱们能够说 Golang 中的任何 数据类型 都实现了空接口。空接口是任何类型的父接口。 应用空接口保留一个数据的过程会比间接用数据对应类型的变量保留稍慢。因而在开发中,应在须要的中央应用空接口,而不是在所有中央应用空接口。 任何变量都能够赋值给interface{}类型的变量。 空接口的定义形式: type emptyInt interface {}// 申明一个空接口实例var i interface{}//再比方函数应用空接口类型参数:func myfunc(i interface{})通过空接口类型,Go也能像其它动静语言一样,在数据结构中存储任意类型的数据。 构造体与接口的区别: 构造体:由不同类型的元素组合而成。1、struct构造体中的类型能够是任意类型; 接口:接口是一组办法的签名的汇合。接口定义办法名,Golang中的接口,不须要显示的实现。Interface类型能够定义一组办法,然而这些不须要实现。并且interface不能蕴含任何变量。 只有一个变量,含有接口类型中的所有办法,那么这个变量就实现这个接口. 空构造体示意一个占位符,空接口示意一个类型 参考: https://blog.csdn.net/whhcs/a...

March 20, 2022 · 1 min · jiezi

关于golang:golang-中-字符串转int-float转-string-总结

总共会用 strconv.Atoi strconv.Itoa strconv.ParseInt strconv.FormatFloat这些函数。 str:="5555" //string到int int,err:=strconv.Atoi(str) //string到int64 int64, err := strconv.ParseInt(str, 10, 64) //int到string string:=strconv.Itoa(int) //int64到string string:=strconv.FormatInt(int64,10) //string到float32(float64) float,err := strconv.ParseFloat(string,32/64) //float到string string := strconv.FormatFloat(float32, 'E', -1, 32) string := strconv.FormatFloat(float64, 'E', -1, 64) cc:=strconv.FormatFloat(startTime, 'f', 0, 32), // 'b' (-ddddp±ddd,二进制指数) // 'e' (-d.dddde±dd,十进制指数) // 'E' (-d.ddddE±dd,十进制指数) // 'f' (-ddd.dddd,没有指数) // 'g' ('e':大指数,'f':其它状况) // 'G' ('E':大指数,'f':其它状况)

March 20, 2022 · 1 min · jiezi

关于golang:Goalng中-空结构体的使用

空构造体指的是不蕴含任何字段或元素的构造体,size 为 0 为什么要用空构造体:空构造体 struct{ } 为什么会存在的外围理由就是为了节俭内存。当你须要一个构造体,然而却丝毫不关系外面的内容,那么就能够思考空构造体。golang 外围的几个复合构造 map ,chan ,slice 都能联合 struct{} 应用。 做管制而非数据信息: chan struct{}实现set: map[string]struct{} 应用的场景次要分为三块:1.实现办法接收者2.实现汇合类型3.实现空通道 1、实现办法接收者在业务场景下,咱们须要将办法组合起来,代表其是一个 ”分组“ 的,便于后续拓展和保护。然而如果咱们应用:type T struct{} type T string func (s *T) Call()又仿佛有点不大敌对,因为作为一个字符串类型,其自身会占据定的空间。这种时候咱们会采纳空构造体的形式,这样也便于将来针对该类型进行公共字段等的减少。如下: type T struct{} func (s *T) Call() { fmt.Println("脑子进煎鱼了") } func main() { var s T s.Call() }在该场景下,应用空构造体从多维度来考量是最合适的,易拓展,省空间,最结构化。另外你会发现,其实你在日常开发中下意识就曾经这么做了,你能够了解为设计模式和日常生活相结合的另类案例。 2、实现汇合类型在 Go 语言的规范库中并没有提供汇合(Set)的相干实现,因而个别在代码中咱们图不便,会间接用 map 来代替。但有个问题,就是汇合类型的应用,只须要用到 key(键),不须要 value(值)。type Set map[string]struct{} type Set map[string]struct{} func (s Set) Append(k string) { s[k] = struct{}{} } func (s Set) Remove(k string) { delete(s, k) } func (s Set) Exist(k string) bool { _, ok := s[k] return ok } func main() { set := Set{} set.Append("大鱼") set.Append("小鱼") set.Append("咸鱼") set.Remove("咸鱼") fmt.Println(set.Exist("死鱼")) }3、 实现空通道在 Go channel 的应用场景中,经常会遇到告诉型 channel,其不须要发送任何数据,只是用于协调 Goroutine 的运行,用于流转各类状态或是管制并发状况。如下:ch := make(chan struct{}) ...

March 20, 2022 · 1 min · jiezi

关于golang:goroutine-顺序执行的技巧

当敞开一个channel时,会使得这个channel变得可读。通过这个个性,能够实现一个goroutine执行程序的技巧。B依赖A, C依赖B package mainimport ( "fmt" "sync" "time")var wg sync.WaitGroup//要使 A->B->C 程序执行func main() { A := make(chan struct{}) B := make(chan struct{}) C := make(chan struct{}) wg.Add(3) go func() { defer wg.Done() testA(A, B) }() go func() { defer wg.Done() testB(B, C) }() go func() { defer wg.Done() testC(C) }() close(A) wg.Wait() time.Sleep(10 * time.Second)}func testA(A chan struct{}, B chan struct{}) { <-A fmt.Println(1) close(B)}func testB(B chan struct{}, C chan struct{}) { <-B fmt.Println(2) close(C)}func testC(C chan struct{}) { <-C fmt.Println(3)}

March 20, 2022 · 1 min · jiezi

关于golang:golang-求两个数组的交集-差集-去重等方法

// Find Find获取一个切片并在其中查找元素。如果找到它,它将返回它的密钥,否则它将返回-1和一个谬误的bool。func Find(slice []string, val string) (int, bool) { for i, item := range slice { if item == val { return i, true } } return -1, false}// IntersectArray 求两个切片的交加func IntersectArray(a []string, b []string) []string { var inter []string mp := make(map[string]bool) for _, s := range a { if _, ok := mp[s]; !ok { mp[s] = true } } for _, s := range b { if _, ok := mp[s]; ok { inter = append(inter, s) } } return inter}// DiffArray 求两个切片的差集func DiffArray(a []int, b []int) []int { var diffArray []int temp := map[int]struct{}{} for _, val := range b { if _, ok := temp[val]; !ok { temp[val] = struct{}{} } } for _, val := range a { if _, ok := temp[val]; !ok { diffArray = append(diffArray, val) } } return diffArray}// RemoveRepeatedElement 切片去重实现func RemoveRepeatedElement(arr []string) (newArr []string) { newArr = make([]string, 0) for i := 0; i < len(arr); i++ { repeat := false for j := i + 1; j < len(arr); j++ { if arr[i] == arr[j] { repeat = true break } } if !repeat { newArr = append(newArr, arr[i]) } } return}//切片去重实现func arrayUnique(arr []string) []string { result := make([]string, 0, len(arr)) temp := map[string]struct{}{} for i := 0; i < len(arr); i++ { if _, ok := temp[arr[i]]; ok != true { temp[arr[i]] = struct{}{} result = append(result, arr[i]) } } return result}

March 20, 2022 · 2 min · jiezi

关于golang:Golang-基础之函数使用-一

大家好,明天将梳理出的 Go语言函数用法内容,分享给大家。 请多多指教,谢谢。 本次《Go语言函数应用》内容共分为三个章节,本文为第一章节。 Golang 根底之函数应用 (一)Golang 根底之函数应用 (二)Golang 根底之函数应用 (三)本章节内容函数介绍函数特点函数申明传参形式不定参数传值任意参数类型的不定参数返回值函数介绍为了实现某一性能的程序指令(语句)的汇合,称为函数。 Go 语言的函数能够分为:自定义函数和零碎函数。Go 语言函数与其余语言函数最大的不同是,Go 语言的函数能够反对返回任意多个值,而其余语言的函数个别只反对返回一个值。 比方C语言函数返回值只能是一种类型。Go 语言的函数也反对一般函数、匿名函数和闭包三种模式。 函数特点无需申明原型反对不定变参反对多返回值反对命名返回参数反对匿名函数和闭包 (变向的高阶函数)函数也是一种类型,一个函数能够赋值给变量不反对嵌套 (nested) 一个包不能有两个名字一样的函数不反对重载 (overload)不反对默认参数 (default parameter)函数申明函数申明包含函数名、形式参数列表、返回值列表(可省略)以及函数体。 func name(parameter-list) (result-list) { // 申明函数名 // 函数体}如果函数返回一个无名变量或者没有返回值,返回值列表的括号是能够省略的。如果一个函数申明不包含返回值列表,那么函数体执行结束后,不会返回任何值。 传参形式值传递指在调用函数时将理论参数复制一份传递到函数中,这样在函数中如果对参数进行批改,将不会影响到理论参数。 func num(x, y int) int { // 解决逻辑}援用传递是指在调用函数时将理论参数的地址传递到函数中,那么在函数中对参数所进行的批改,将影响到理论参数。 func swap(x, y *int) { var temp int temp = *x /* 保留 x 的值 */ *x = *y /* 将 y 值赋给 x */ *y = temp /* 将 temp 值赋给 y*/}无论是值传递,还是援用传递,传递给函数的都是变量的正本,不过,值传递是值的拷贝。 ...

March 19, 2022 · 1 min · jiezi

关于golang:golang-基本知识点

// 5.Runtime.mp4小对象构造体合并bytes Buffer sice、map预创立长调用栈防止频繁创立长期对象字符串拼接 strings.Builder不必要的memory copy剖析内存逃逸// 这种申明形式 p 是一个 nil 值var p *Point// 改为var p *Point = new(Point)// 或者var p *Point = &Point{}为什么这么改就能够呢,咱们看看定义,大抵意思是,new函数会分配内存,返回的值是一个指向该类型零值的地址。 //第一种申明 var language map[string]string language = make(map[string]string, 10) //在应用map前,须要先make,make的作用就是给map调配数据空间 language["1"] = "C#" language["2"] = "go" language["3"] = "python" fmt.Println(language) //map[1:C# 2:go 3:python] //第二种申明 相比下面的第一种,少了 var申明 language2 := make(map[string]string) language2["1"] = "C#" language2["2"] = "go" language2["3"] = "python" fmt.Println(language2) //map[1:C# 2:go 3:python] //第三种申明 间接初始化 language3 := map[string]string{ "1": "C#", "2": "go", "3": "python", } fmt.Println(language3) //map[1:C# 2:go 3:python]

March 19, 2022 · 1 min · jiezi

关于golang:go-new-和-make-的区别

看起来二者没有什么区别,都在堆上分配内存,然而它们的行为不同,实用于不同的类型。 new(T) 为每个新的类型T调配一片内存,初始化为 0 并且返回类型为*T的内存地址:这种办法 返回一个指向类型为 T,值为 0 的地址的指针,它实用于值类型如数组和构造体;它相当于 &T{}。 make(T) 返回一个类型为 T 的初始值,它只实用于3种内建的援用类型:切片、map 和 channel new只分配内存, make用于slice,map,和channel的初始化.下图给出了区别:

March 19, 2022 · 1 min · jiezi

关于golang:学习笔记带你十天轻松搞定-Go-微服务系列大结局十-分布式事务

1、学习课程带你十天轻松搞定 Go 微服务系列(十)- 分布式事务 明天是学习 go 微服务的最初一天,明天是学习分布式事务 2、go-zero 应用 DTM2.1 增加 DTM 服务配置参见 第一章 环境搭建,批改 dtm->config.yml 配置文件。咱们只有批改 MicroService 中的 Target,EndPoint 配置即可,将 dtm 注册到 etcd 中。 # ......# 微服务MicroService: Driver: 'dtm-driver-gozero' # 要解决注册/发现的驱动程序的名称 Target: 'etcd://etcd:2379/dtmservice' # 注册 dtm 服务的 etcd 地址 EndPoint: 'dtm:36790'# ......2.2 增加 dtm_barrier 数据表应用 DTM 提供的子事务屏障技术则须要在业务数据库中创立子事务屏障相干的表,建表语句如下: create database if not exists dtm_barrier/*!40100 DEFAULT CHARACTER SET utf8mb4 */;drop table if exists dtm_barrier.barrier;create table if not exists dtm_barrier.barrier( id bigint(22) PRIMARY KEY AUTO_INCREMENT, trans_type varchar(45) default '', gid varchar(128) default '', branch_id varchar(128) default '', op varchar(45) default '', barrier_id varchar(45) default '', reason varchar(45) default '' comment 'the branch type who insert this record', create_time datetime DEFAULT now(), update_time datetime DEFAULT now(), key(create_time), key(update_time), UNIQUE key(gid, branch_id, op, barrier_id));留神:库名和表名请勿批改,如果您自定义了表名,请在应用前调用 dtmcli.SetBarrierTableName。 ...

March 18, 2022 · 7 min · jiezi

关于golang:Golang-基础之知识普及

大家好,明天将梳理出的 Go语言常识遍及内容,分享给大家。 请多多指教,谢谢。 后面已将根底语法、数据类型、函数应用内容介绍实现,置信大家曾经有了Go根底。此篇内容次要谈一下对Go这门语言的背景和个性内容,还有一些编程标准和大家分享一下。 本章节内容Go语言的介绍编程标准Go语言的介绍Go语言是由谷歌公司在2007年开发的一门语言,目标是能在多外围时代高效编写网络应用程序。 Go语言的创始人 Robert Griesemer、Rob Pike 和 Ken Thompson都是在计算机倒退过程中作出过重要奉献的人。 自从2009年11月正式公开公布后,Go语言迅速席卷了整个互联网后端开发畛域,其社区里不断涌现出相似vitess、Docker、etcd、Consul等重量级的开源我的项目。 Go语言开发团队花了很长时间来解决当今软件开发人员面对的问题。 开发人员在为项目选择语言时,不得不在疾速开发和性能之间作出抉择。 C和C++这类语言提供了很快的执行速度,而Ruby和Python这类语言则善于疾速开发。 Go语言在这两者间架起了桥梁,不仅提供了高性能的语言,同时也让开发更疾速。 个性语法简洁到只有几个关键字编译器速度十分快能显著缩小期待我的项目构建的工夫内置并发机制自带垃圾回收器1. 开发速度 编译一个大型的C或者C++我的项目所破费的工夫甚至比去喝杯咖啡的工夫还长。 Go语言应用了更加智能的编译器,并简化了解决依赖的算法,最终提供了更快的编译速度。 编译Go程序时,编译器只会关注哪些间接被援用的库,而不是像Java、C和C++那样,要遍历依赖链中所有依赖的库。因而,很多Go程序能够在1秒内编译完。 在古代硬件上,编译整个Go语言源码树只须要20秒。 2. Runtime Golang Runtime是go语言运行所须要的基础设施,次要作用: 携程调度,内存调配,GC;操作系统及CPU相干的操作的封装(信号处理,零碎调用,寄存器操作,原子操作等),CGO;pprof,trace,race检测的反对;Map,channel,string等内置类型及反射的实现 阐明: 与Java,Python不同,Go并没有虚拟机的概念,Runtime也间接被编译成 native code;Go的Runtime与用户代码一起打包在一个可执行文件中;用户代码与Runtime代码在执行的时候并没有显著的界线,都是函数调用;go对系统调用的指令进行了封装,不依赖于glibc;一些Go的关键字被编译成runtime包下的函数此局部内容参考 腾讯技术工程公布的Runtime文章 https://zhuanlan.zhihu.com/p/... 3. 内存治理 不当的内存治理会导致程序解体或者内存透露,甚至让整个操作系统解体。 Go语言领有现代化的垃圾回收机制,能够无效的解决这个难题。外围的目标是把无趣的内存治理交给业余的编译器去做,而让程序员更专一与更乏味的事件。 实用的畛域服务器编程,以前你如果应用C或者C++做的那些事件,用Go来做很适合,例如解决日志、数据打包、虚拟机解决、文件系统等。分布式系统,数据库代理器等。网络编程,这一块目前利用最广,包含Web利用、API利用、下载利用。内存数据库,前一段时间google开发的groupcache,couchbase的局部组建。云平台,目前国外很多云平台在采纳Go开发,CloudFoundy的局部组建,前VMare的技术总监本人进去搞的apcera云平台。游戏服务端的开发。总体来说,所面临的业务要求高并发、性能要求强、解决麻利等个性,都能够首先思考用Go来做。编程标准命名标准包命名 放弃package的名字和目录保持一致,尽量采取有意义的包名,简短,有意义,尽量和规范库不要抵触。包名应该为小写单词,不要应用下划线或者混合大小写。 文件命名 尽量采取有意义的文件名,简短,有意义,应该为小写单词,应用下划线分隔各个单词。非单元测试文件不要以_test结尾,go编译器默认 x_test.go 为单元测试文件,不会进行编译。变量命名 采纳驼峰法,通过首字母大小写来管制是否包外可见。非凡名词的首字母缩写须要依照标准来,例如 URLProxy 或者 urlProxy 不要命名为 UrlProxy。接口命名 单个函数的接口名以"er"作为后缀,例如 type Reader interface {…}两个函数的接口名综合两个函数名,例如 type WriteFlusher interface {…}三个以上函数的接口名,相似于构造体名,例如 type Car interface {…}代码格式化举荐应用gofmt, goimports 正文多写要害函数的正文,活用 //TODO,//FIXME 包援用包引入了三种类型的包:规范库包、程序外部包、第三方包,请按这种程序每局部预留一行空行,较为清晰。在我的项目中不要应用相对路径引入包,应用绝对路径引入包不要应用 . 来省略包名援用其余标准receiver命名最多2个字母,不能应用 me 或者 self 或者 this,例如 func (c *Client) GetUserName() string每行代码长度最好不超过80个字符,如果超过倡议换行函数返回值采纳返回"指针"类型而不是返回"值"类型 (举荐)没十分必要不能panic,过程开始的处理函数能够panic任何一个goroutine都应该有recover来爱护程序不会因为panic而crash,因为任何一个goroutine如果抛panic但没有recover整个程序会crash技术文章继续更新,请大家多多关注呀~~ ...

March 18, 2022 · 1 min · jiezi

关于golang:基于-Go-的泛型快速实现一个功能完备的路由

Go 语言的路由库有很多,性能上都大同小异,最大的差别应该是路由函数的签名,官网采纳了 http.Handler 接口,而大部分非官方路由都将 http.ResponseWriter 和 http.Request 合并成了一个对象。本文介绍的库 https://github.com/issue9/mux 利用 go1.18 对泛型的反对,实现了用户自定义该性能的需要,仅须要几步即可实现一个欠缺的路由,实用于疾速开发一个 web 框架。 如何应用以实现一个兼容 http.Handler 接口的路由为例,仅需以下几个步骤即可。 定义路由解决类型能够是接口,也能够是函数,咱们以 http.Handler 为例,那么该类型就是 http.Handler 接口,此步能够省略。 定义泛型对应的类型以 http.Handler 为参数实例化泛型类型: package custom_routerimport "github.com/issue9/mux/v6"type ( Router = mux.RouterOf[http.Handler] Prefix = mux.PrefixOf[http.Handler] Resource = mux.ResourceOf[http.Handler] Options = mux.OptionsOf[http.Handler] Middleware = mux.MiddlewareOf[http.Handler])定义 New 函数咱们须要一个 CallOf 函数,用于将给定的参数转换成调用 http.Handler 的办法。其原型如下: CallOf[T any] func(http.ResponseWriter, *http.Request, Params, T)New 能够间接调用 NewRouterOf 办法,给出 CallOf 的实例化办法即可。 package custom_routerimport "github.com/issue9/mux/v6"func call(w http.ResponseWriter, r *http.Request, ps Params, h http.Handler) { h.ServeHTTP(w, WithValue(r, ps))}func New(name string, o *Options) *Router { return NewRouterOf[http.Handler](name, call, o)}辅助函数而后定义一些辅助函数,比方将参数写入到 http.Request 和从 http.Request 中获取参数。 ...

March 18, 2022 · 2 min · jiezi

关于golang:第四十三期社招面经后端开发-蚂蚁

面试前蚂蚁的面试挺独特,每轮面试都没有 HR 约工夫,个别是早晨 8 点左右面试官来一个电话,问是否能面试,能的话开始面,不能就约一个其它工夫。 全程 6 面,前五面技术面,电话面试,最初一面是 HR 面,现场面。 一面介绍一下本人问我的项目经验, 聊"数据同步"接着聊上了 K8S 的我的项目有没有什么钻研得比拟深得技术?(我:kubernetes, golang, prometheus, java)kubernetes 的架构是怎么样的?这个问题很大,拆成 apiserver、controller、kubelet、scheduler 讲了一下golang 与 java 的比拟这个问题又很大,过后次要比照了 vm、协程反对、面向对象和泛型的区别、以及本人对各自应用场景的一些了解 golang 的 gc 算法晓得是三色标记,不过细节说不上来 从有限的字符流中, 随机选出 10 个字符没见过也没想进去,查了一下是蓄水池采样算法,经典面试题,没刷题吃亏了 怎么扩大 kubernetes scheduler, 让它能 handle 大规模的节点调度单节点提速:优选阶段随机取局部节点进行优选;程度扩大 scheduler 节点,pod 做一致性 hash 来决定由哪个 scheduler 调度 你有什么想问我的?一面其实有点僵,我本人齐全没放开,面试官对我的答复没有什么反馈和深刻,都是"哦好的"而后就过了。所以我过后面完感觉本人其实曾经挂了(我本人要是对*不感兴趣,有时候也就问完问题走个过场溜了),起初收到二面电话着实吃惊了一下。 二面先聊了聊我的项目给 Prometheus 做了哪些改变?自研配置核心, 具体做了哪些内容?有用过 MySQL 的什么高级个性吗?这里不太了解,我问什么算高级个性,面试官就切换到了下一个问题配置核心的外围数据表是怎么设计的?为什么在业务里用 Redis, Redis 有什么长处?单线程:并发平安;高性能;原语与数据结构丰盛;采纳宽泛,踩坑成本低对 Redis 里数据结构的实现相熟吗?说了一个 zset 跳表用过 Redis 的哪些数据结构, 别离用在什么场景? Java 初始化一个线程池有哪些参数能够配置, 别离是什么作用?本人写的 Java 利用调优过哪些 JVM 参数, 为什么这么调优? ...

March 18, 2022 · 2 min · jiezi

关于golang:gosearch-golang的包搜索工具

gosearchgosearch 是golang的包搜索器,不须要记住包的全路劲即可安装包 如:装置 gin: gosearch gin装置 logrus: gosearch logrus 装置多个包: gosearch mysql pq beego 我的项目地址: https://github.com/clearcodec... 装置形式: go get github.com/clearcodecn/gosearch应用形式: ✗ gosearch pq? select a package pq github.com/lib/pq Package pq is a pure Go Postgres driver for the database/sql package. go get github.com/lib/pqgo: downloading github.com/lib/pq v1.10.4go get: added github.com/lib/pq v1.10.4 done

March 17, 2022 · 1 min · jiezi

关于golang:Golang力扣Leetcode剑指Offer字符串05-替换空格

题目:请实现一个函数,把字符串 s 中的每个空格替换成"%20"。 链接: 力扣Leetcode—剑指Offer—字符串—05. 替换空格. 示例 1: 输出:s = "We are happy."输入:"We%20are%20happy."思路: 一个办法是建设一个新的字符串,用 for range 遍历原字符串,应用 Switch 对 value 值进行抉择,case 空格则加上%20,默认状况则是间接加上value,留神要转为 string 就解决了。另一种办法就是间接调用现有的库。法一Go代码: package mainimport "fmt"func replaceSpace(s string) string { var res string for _, v := range s { switch v { case ' ': //遇到空格则加上%20 res += "%20" default: //默认加上v值,然而要转为string res += string(v) } } return res}func main() { a := "We are happy." fmt.Println(replaceSpace(a))}提交截图: ...

March 17, 2022 · 1 min · jiezi

关于golang:Go-笔记-小练习之获取命令行参数的三种方法

代码性能:实现一个简略的命令行工具:将输出的命令行参数打印进去 代码如下(三种办法):第一种办法:应用 for 循环 package mainimport ( "fmt" "os")func main() { // r 是最终要输入的后果,sep 代表分隔符 var r, sep string // 应用 os.Args 获取命令行参数 for i := 1; i < len(os.Args); i++ { r += sep + os.Args[i] // 第一次循环的时候 sep 就是个空字符串。则 r 第一次循环的后果就是 os.Args[1] sep = " " // 将分隔符定义为空格。第二次循环的后果就是 os.Args[1] + 空格 + os.Args[2] } fmt.Println("您输出的参数为:", r)}第二种办法:应用 range package mainimport ( "fmt" "os")func main() { // r 是最终要输入的后果,sep 代表分隔符 var r, sep string // 应用 os.Args 获取命令行参数 for _, arg := range os.Args[1:] { // os.Args[1:] 从 1 开始是因为 0 是这个工具名自身,相当于 shell 的 $0 r += sep + arg sep = " " } fmt.Println("您输出的参数为:", r)}第三种办法(最简略,举荐!):应用 strings.Join() 函数 ...

March 16, 2022 · 1 min · jiezi

关于golang:Go-笔记-Beego-之-orm-表结构操作

代码:package mainimport ( "github.com/beego/beego/v2/client/orm" _ "github.com/go-sql-driver/mysql" "log" "time")/* 标签的应用:1、用 beego orm 显示设置主键2、ID 属性须要设置 int64 或者显示指定 pk3、设置标签名应用:orm。多个标签应用分号分隔。4、设置主键:pk(个别主动设置,主动找第一个 int64 类型设置为主键)5、设置主动增长:auto(个别主动设置,主动找第一个 int64 类型设置为主动增长)6、设置列名:column(name)7、设置字符串类型:默认 varchar(255),设置长度应用 size(length)。其余字符串类型:type(text)8、是否容许为 null:默认不容许。容许为 null,应用:null9、默认值:default()10、正文:description()11、惟一索引:unique12、设置索引:index13、struct 字段的首字母必须大写,否则无奈映射到数据库表(不创立对应的 column)14、auto_now // 每次更新的时候主动设置属性为以后工夫。不体现在 sql 中,是在 orm 代码执行过程中实现15、auto_now_add // 当数据创立时设置为以后工夫。不体现在 sql 中,是在 orm 代码执行过程中实现16、工夫:type(date)17、默认引擎:InnoDB*/type Account struct { ID int64 `orm:"pk;auto;column(id)"` // Id string `orm:"pk"` // 强制设置为主键 // Name string `orm:"size(64);unique"` Name string `orm:"size(64)"` Password string `orm:"size(1024)"` Birthday *time.Time Telephone string Email string Addr string `orm:"default(中国北京)"` Status int8 `orm:"default(1);description(状态)"` RoleId int64 DepartmentId int64 CreatedAt *time.Time `orm:"auto_now_add;"` UpdatedAt *time.Time `orm:"auto_now;"` DeletedAt *time.Time `orm:"null;"` Description string `orm:"type(text)"` Sex bool Height float64 `orm:"digits(10);decimals(2)"` // 总共位数 10 位,小数位数 2 位 Weight float64 //height float64 //weight float64 //A string //B string //B int64}/* 关联表的办法: 1、默认会依据 struct 名称生成对应的表。例如 type Account struct 则生成表 account 。 2、应用该办法后,则依据 return 返回的名称生成或者关联到表。例如 return "act" 首次执行则生成表 act 。后续执行则将变更更新到表 act 。*/func (account *Account) TableName() string { return "act"}// 创立索引func (account *Account) TableIndex() [][]string { return [][]string{ // 给 name 创立索引,并给 telephone 和 email 创立联结索引 {"name"}, {"telephone", "email"}, }}func main() { // 驱动名 driverName := "mysql" // databaseName := "default" dsn := "golang:123456@tcp(192.168.100.20:33060)/cmdb?charset=utf8mb4&parseTime=true" // 注册数据库驱动到 orm // 参数:自定义的数据库类型名,驱动类型(orm 中提供的) orm.RegisterDriver(driverName, orm.DRMySQL) // 参数:beego 必须指定默认的数据库名称,应用的驱动名称(orm 驱动类型名),数据库的配置信息,数据库(连接池),连贯(池)名称 err := orm.RegisterDataBase(databaseName, driverName, dsn) if err != nil { log.Fatal(err) } // 定义构造 // 注册模型 orm.RegisterModel(new(Account)) // 依据定义的构造体生成表(只同步表构造,不同步库。须要提前创立库) // 第二个参数 force:如果为 true,则每次编译时都会从新生成表,即如果表已存在就删除并重建。如果为 false,则只更新列的变更 // 第三个参数 verbose:打印执行的 sql 语句 // orm.RunSyncdb(databaseName,false,true) orm.RunSyncdb(databaseName, true, true)}sql 执行后果:drop table `act` DROP TABLE IF EXISTS `act`create table `act` -- -------------------------------------------------- -- Table Structure for `main.Account` -- -------------------------------------------------- CREATE TABLE IF NOT EXISTS `act` ( `id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(64) NOT NULL DEFAULT '' , `password` varchar(1024) NOT NULL DEFAULT '' , `birthday` datetime NOT NULL, `telephone` varchar(255) NOT NULL DEFAULT '' , `email` varchar(255) NOT NULL DEFAULT '' , `addr` varchar(255) NOT NULL DEFAULT '中国北京' , `status` tinyint NOT NULL DEFAULT 1 COMMENT '状态', `role_id` bigint NOT NULL DEFAULT 0 , `department_id` bigint NOT NULL DEFAULT 0 , `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, `deleted_at` datetime, `description` longtext NOT NULL, `sex` bool NOT NULL DEFAULT FALSE , `height` numeric(10, 2) NOT NULL DEFAULT 0 , `weight` double precision NOT NULL DEFAULT 0 ) ENGINE=InnoDB; CREATE INDEX `act_name` ON `act` (`name`); CREATE INDEX `act_telephone_email` ON `act` (`telephone`, `email`);Process finished with exit code 0生成的表:MariaDB root@localhost:cmdb> desc act;+---------------+---------------+------+-----+----------+----------------+| Field | Type | Null | Key | Default | Extra |+---------------+---------------+------+-----+----------+----------------+| id | bigint(20) | NO | PRI | <null> | auto_increment || name | varchar(64) | NO | MUL | | || password | varchar(1024) | NO | | | || birthday | datetime | NO | | <null> | || telephone | varchar(255) | NO | MUL | | || email | varchar(255) | NO | | | || addr | varchar(255) | NO | | 中国北京 | || status | tinyint(4) | NO | | 1 | || role_id | bigint(20) | NO | | 0 | || department_id | bigint(20) | NO | | 0 | || created_at | datetime | NO | | <null> | || updated_at | datetime | NO | | <null> | || deleted_at | datetime | YES | | <null> | || description | longtext | NO | | <null> | || sex | tinyint(1) | NO | | 0 | || height | decimal(10,2) | NO | | 0.00 | || weight | double | NO | | 0 | |+---------------+---------------+------+-----+----------+----------------+17 rows in setTime: 0.008s

March 16, 2022 · 3 min · jiezi

关于golang:Golang-基础之数据类型梳理

大家好,将梳理出的 Go语言数据类型内容,分享给大家。 请多多指教,谢谢。 类型汇总Go 语言中,次要分为值类型次要分为三局部: 整型、浮点型和其余类型。 // 整型int int8 int16 int32 int64uint uint8 uint16 uint32 uint64 uintptr// 浮点型、复数float32 float64 complex128 complex64// 其余类型bool byte rune string error整型Go语言同时提供了有符号和无符号类型的整数运算。 int int8 int16 int32 有合乎和无符号类型这里有int8、int16、int32和int64四种截然不同大小的有符号整数类型,别离对应8、16、32、64bit大小的有符号整数,与此对应的是uint8、uint16、uint32和uint64四种无符号整数类型。 这里还有两种个别对应特定CPU平台机器字大小的有符号和无符号整数int和uint;其中int是利用最宽泛的数值类型。这两种类型都有同样的大小,32或64bit,然而咱们不能对此做任何的假如;因为不同的编译器即便在雷同的硬件平台上可能产生不同的大小。 uintptr 类型uintptr 是一种无符号的整数类型 ,没有指定具体的bit大小然而足以包容指针。uintptr 类型只有在底层编程时才须要,特地是Go语言和C语言函数库或操作系统接口相交互的中央。 不论它们的具体大小,int、uint 和 uintptr 是不同类型的兄弟类型。其中int和int32也是不同的类型,即便int的大小也是32bit,在须要将int当作int32类型的中央须要一个显式的类型转换操作,反之亦然。 类型值范畴类型名称大小形容int8 字节int的大小是和操作系统位数相干的,如果是32位操作系统,int类型的大小是4字节;如果是64位操作系统,int类型的大小就是8个字节int81 字节无符号整数的所有bit位都用于示意非正数,值域是0到$2^n-1$。例如,int8类型整数的值域是从-128到127,而uint8类型整数的值域是从0到255。int162 字节有符号int16类型整数值域是从 -32768 ~ 32767,而无符号uint16类型整数值域是从 0 ~ 65535int324 字节有符号int32类型整数值域是从 -2147483648 ~ 2147483647,而无符号uint32类型整数值域是从 0 ~ 4294967295int648 字节有符号int64类型整数值域是从 -9223372036854775808 ~ 9223372036854775807,而无符号uint64类型整数值域是从 0 ~ 18446744073709551615uintptr长度4或8字节存储指针的uint32 或 uint64整数取值范畴示例package mainimport ( "fmt" "math" "unsafe")func main() { fmt.Println("各int类型的大小: ") var i1 int = 1 var i2 int8 = 2 var i3 int16 = 3 var i4 int32 = 4 var i5 int64 = 5 var i6 uint64 = 6 fmt.Printf("int : %v\n", unsafe.Sizeof(i1)) fmt.Printf("int8 : %v\n", unsafe.Sizeof(i2)) fmt.Printf("int16 : %v\n", unsafe.Sizeof(i3)) fmt.Printf("int32 : %v\n", unsafe.Sizeof(i4)) fmt.Printf("int64 : %v\n", unsafe.Sizeof(i5)) fmt.Printf("uint64: %v\n", unsafe.Sizeof(i6)) // 输入各int类型的取值范畴 fmt.Println("int8:", math.MinInt8, "~", math.MaxInt8) fmt.Println("int16:", math.MinInt16, "~", math.MaxInt16) fmt.Println("int32:", math.MinInt32, "~", math.MaxInt32) fmt.Println("int64:", math.MinInt64, "~", math.MaxInt64) fmt.Println() // n是主动推导类型 n := 1234567890 fmt.Printf("n := 1234567890 的默认类型为: %T\n", n) fmt.Printf("int类型的字节数为: %v\n\n", unsafe.Sizeof(n)) // 初始化一个32位整型值 var a int32 = 987654321 fmt.Println("var a int32 = 987654321") // 输入变量的十六进制模式和十进制 fmt.Printf("int32: 十六进制为0x%x, 十进制为%d\n", a, a) // 将a转换为int8类型, 产生数值截断 b := int8(a) fmt.Printf("int8: 十六进制0x%x, 十进制为%d\n", b, b) // 将a转换为int16类型, 产生数值截断 c := int16(a) fmt.Printf("int16: 十六进制为0x%x, 十进制%d\n", c, c) // 将a转换为int64类型 d := int64(a) fmt.Printf("int64: 十六进制为0x%x, 十进制%d\n", d, d)}浮点型浮点数类型的取值范畴能够从很渺小到很微小。浮点数的范畴极限值能够在math包找到。常量math.MaxFloat32示意float32能示意的最大数值,大概是 3.4e38;对应的 math.MaxFloat64 常量大概是1.8e308。它们别离能示意的最小值近似为1.4e-45和4.9e-324。 ...

March 16, 2022 · 2 min · jiezi

关于golang:go118泛型的简单尝试

明天golang终于公布了1.18版本,这个版本最大的一个扭转就是退出了泛型。尽管没有在beta版本的时候尝试泛型,然而因为在其余语言的泛型教训,动手泛型不是件难事~ 官网示例Tutorial: Getting started with generics - The Go Programming Language 依据官网示例能够看出,在go中泛型申明应用中括号,大体用法也与其余语言差不多。上面就官网示例中呈现的几个点做记录。 comparable在泛型的束缚中有 comparable 关键字,咱们进到源码中看到解释: // comparable is an interface that is implemented by all comparable types// (booleans, numbers, strings, pointers, channels, arrays of comparable types,// structs whose fields are all comparable types).// The comparable interface may only be used as a type parameter constraint,// not as the type of a variable.type comparable interface{ comparable }看得出来这是官网定义的一个可比拟的类型的一个泛型束缚,它也只能存在于类型参数束缚的时候。 一些扭转咱们尝试批改官网示例,体验一下其余的关键词及相干用法。 ~ 波浪号咱们会在一些泛型示例中看到这样的申明: ...

March 16, 2022 · 1 min · jiezi

关于golang:为什么说想搞懂云原生必须会-Go-语言

云原生技术作为一个新赛道,近几年倒退十分迅速。 随着利用上云成为不可逆转的趋势,很多公司都抉择将基础架构/业务架构云化,甚至所有技术都围绕云来构建。这也造成了市场对 Go 工程师的需要,无论是数量还是薪资,都一劳永逸。 这是因为在云原生技术栈语言组成中,有 63% 的云原生我的项目都是用 Go 构建的,所以不论是想要学习,或是精通云原生技术,Go 语言都是根底。 说到 Go 语言,有人说简略,有人说难,两种说法都对。Go 语言简略在极易入门,甚至一个早晨便能学完所有的语言,不简略在精通是极难的,须要消耗大量精力刻苦磨难,可能几年都无奈达到高级工程师的规范。那么,咱们如何疾速入门,精通 Go 语言呢? 其实,想学好 Go 语言的一个最大前提是要能保持,其次就是基础知识的可靠把握。就好比一座在建的大厦,只有地基松软、巩固,大厦才可能迎来建成并矗立云霄的那天。 这里分享 Tony Bai 整顿的入门办法,内容次要包含“心定、手勤、脑勤”三个窍门与“前置、入门、根底、外围、实战”五个阶段。辅助你顺利踏上对 Go 语言的摸索之路,同时能早日成为优良的 Go 开发。 1.前置篇,“心定”建设认同感;2.入门篇,“手勤”多入手实际;3.根底篇,“脑勤”多了解,夯实根底;4.外围篇,“脑勤+”建设本人的 Go 利用设计意识;5.实战篇,攻克 Go 开发的“最初一公里”。 下面这些内容在《TonyBai·Go语言第一课》中都有具体解说。作者 Tony Bai 是国内最早接触 Go 的那批人,Go 开发常识和教训都相当丰盛,倡议你学学他的专栏。 另外,大厂面试考查较多的是 Go 语言外围知识点和解决问题的能力。而 Go 语言的外围常识蕴含多方面的信息,例如语法用法、数据类型和测试等等,只有真正搞懂他们,能力玩转 Go 语言,拿下面试。 分享给你郝林整顿好的 Go 语言外围知识点。如果你了解了,再研读 Go 语言规范库和优良的第三方库,就能事倍功半。应用 Go 语言编写软件时,也会更熟能生巧。 这些内容都在《Go 语言外围 36 讲》专栏中有详解解说。除此之外,这个专栏还有一个特色——面试必备。郝林有多年的 Go 语言面试官教训,所以在专栏中,他从大厂面试角度登程,每期解析一组经典面试题,给出相应的典型答复和考点剖析,岂但让你理解面试题真正想考查的能力,还能带你彻底搞懂原理,助你轻松拿下面试。 你能够把这个专栏当作题库,以此训练本人的实战能力,例如这些问题,你是否真的都会:咱们应用互斥锁时有哪些注意事项?sync/atomic包中提供了几种原子操作?可操作的数据类型又有哪些?条件变量的Signal办法和Broadcast办法有哪些异同?长期对象池存储值所用的数据结构是怎么的?怎么保障并发平安字典中的键和值的类型正确性?在io包中,io.Reader的扩大接口和实现类型都有哪些?它们别离都有什么功能? 最初,利用上云曾经成为不可逆转的趋势,无论大厂小厂,纷纷将业务全面云化,这也对专攻云原生我的项目的 Go 开发者提出了更高的要求。 而你可能不晓得如何去找到最佳的构建办法,以及如何从 0 到 1 开发 Go 我的项目,平时也没机会接触一线大厂的大型项目构建办法和研发教训,不足一线我的项目练手,天然也难以测验本人的学习效果。 ...

March 16, 2022 · 1 min · jiezi

关于golang:第四十二期米哈游后台golang开发面经

介绍一下本人一开始问我的项目(我的我的项目跟网络相干)中的拥塞管制、流量管制;简略介绍了一下协定做的事件。有什么拥塞控制协议:Reno和BBR介绍一下Reno协定的工作形式;UDP 和 TCP 的区别,都适宜什么场景:在游戏中应用KCP协定比拟多。引申了一下HTTP 的状态码:1~5结尾各是什么作用用HTTP能够实现被动推送的性能吗,为什么不应用HTTP而是应用 websocket(我的项目中应用了websocket )HTTP1.1 中也实现了长连贯,然而这个长连贯中服务器还是被动的,而且HTTP都是基于文本的,尽管底层TCP没有断开,发送音讯还是蕴含太多不必要的头部信息(带宽耗费大),所以在某些场景还是 websocket 好用。HTTP2中对上述的两个毛病做了些优化,比方压缩头部,再比方能够反对服务器被动推送(相当于预加载),然而客户端还是主导地位,能够发送RST_STREAM 来显式的进行这种推送。TCP 的各种标记位(发现我不熟这些标记位),又开始问TCP的三次握手TCP 有多个管制位,SYNC是开启连贯,FIN是完结连贯(单向断开,优雅断开),ACK是指回复包,RST是异样断开(双向都间接不能解决了),PSH是相似于FLUSH,通知对方能够将缓冲区的数据间接上报道应用层了(还是有序的),URG(把这一个包上报应用层,数据包可能是无序的)问 golang 的协程:Goroutine 阻塞的话,是不是对应的M也会阻塞问一道思考题:如何并发100个工作,然而同一时间最多运行的10个工作(waitgroup + channel)

March 16, 2022 · 1 min · jiezi

关于golang:Go-118-正式发布

美国工夫 2022 年 3 月 15 日,Go 团队官宣 Go 1.18 正式公布! Go 团队示意:Go 1.18 是一个蕴含大量新性能的版本,包含对语言自身做了有史以来最大的扭转(泛型)、工具链的实现、运行时和库的更改,还改善了性能。毫不夸大地说,Go 1.18 的局部设计十多年前,在第一次公布 Go 时就开始了构思。 上面让咱们来疾速预览一下这些最新个性: 泛型(Generics)Go 1.18 引入了对应用参数化类型的泛型代码的新反对。反对泛型是 Go 最常被要求增加的性能,后续版本将持续为一些更简单的泛型用例提供额定反对。 Go 激励用户应用泛型教程来理解这一新性能,并摸索应用泛型来优化和简化用户的代码的最佳办法。 泛型教程链接:https://go.dev/doc/tutorial/g... 在 Go 1.18 版本公布阐明中有更多应用泛型的细节。 含糊测试(Fuzzing)随着 Go 1.18 版本的公布,Go 成为第一个将含糊测试齐全集成到其规范工具链中的次要语言。与泛型一样,含糊测试曾经设计了很长时间。 请联合 Fuzzing 教程开始应用此新性能。 含糊测试教程链接:https://go.dev/doc/tutorial/fuzz 工作区(Workspaces)现在 Go 模块简直已被广泛采纳,在 Go 年度考察中,用户表白了十分高的满意度。在2021 年用户考察中,用户反馈 Go 模块最常见的挑战是跨多个模块工作。 在 Go 1.18 中,通过应用新的 Go 工作区模式解决了这个问题,这使得在多个模块中工作变得简略。 工作区教程链接: https://go.dev/doc/tutorial/w... 20% 的性能晋升苹果 M1、ARM64 和 PowerPC64 用户必定会快乐!因为 Go 1.17 的寄存器 ABI 调用约定扩大到这些架构,Go 1.18 的 CPU 性能晋升幅度高达 20%。 ...

March 16, 2022 · 1 min · jiezi

关于golang:golang-并发编程总结

package mainimport ( "context" "fmt" "sync" "time")func main() {}////例子中咱们通过select判断stop是否承受到值,如果承受到值就示意能够推出进行了,如果没有承受到,//就会执行default外面的监控逻辑,持续监控,直到收到stop的告诉//以上管制goroutine的形式在大多数状况下能够满足咱们的应用,然而也存在很多局限性,比方有很多goroutiine,//并且这些goroutine还衍生了其余goroutine,此时chan就比拟艰难解决这样的问题了func testChan() { stop := make(chan bool) go func() { for { select { case <-stop: fmt.Println("") return default: fmt.Println("groutine监控中...") time.Sleep(1 * time.Second) } } }() time.Sleep(10 * time.Second) fmt.Println("能够了,监控进行了") stop <- true time.Sleep(5 * time.Second)}//以上例子肯定要等到两个goroutine同时做完才会全副实现,这种管制并发形式尤其实用于多个goroutine协同做一件事件的时候。func testWaitGroup() { var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() time.Sleep(2 * time.Second) }() go func() { defer wg.Done() time.Sleep(3 * time.Second) }() wg.Wait() fmt.Println("好了,大家都干完活了")}func CancelTest() { ctx, cancel := context.WithCancel(context.Background()) go func(ctx context.Context) { for { select { case <-ctx.Done(): fmt.Println("协程退出,进行了...") return default: fmt.Println("协程运行中...") time.Sleep(2 * time.Second) } } }(ctx) time.Sleep(time.Second * 30) fmt.Println("两分钟工夫到了,敞开子协程") cancel() time.Sleep(time.Second * 10) fmt.Println("演示完结")}// TimeOutTest WithTimeoutfunc TimeOutTest() { ctx, _ := context.WithTimeout(context.Background(), time.Minute*1) go func(ctx context.Context) { for { select { case <-ctx.Done(): fmt.Println("协程退出,进行了...") return default: fmt.Println("协程运行中...") time.Sleep(2 * time.Second) } } }(ctx) time.Sleep(time.Second * 70) fmt.Println("演示完结")}// DeadLineTest WithDeadlinefunc DeadLineTest() { ctx, _ := context.WithDeadline(context.Background(), time.Now().Add(time.Minute*1)) go func(ctx context.Context) { for { select { case <-ctx.Done(): fmt.Println("协程退出,进行了...") return default: fmt.Println("协程运行中...") time.Sleep(2 * time.Second) } } }(ctx) time.Sleep(time.Second * 70) fmt.Println("演示完结")}// WithValueTest WithCancelfunc WithValueTest() { ctx, cancel := context.WithCancel(context.Background()) //附加值 valueCtx := context.WithValue(ctx, "test", "子协程1") go func(ctx context.Context) { for { select { case <-ctx.Done(): //取出值 fmt.Println(ctx.Value("test"), "监控退出,进行了...") return default: //取出值 fmt.Println(ctx.Value("test"), "goroutine监控中...") time.Sleep(2 * time.Second) } } }(valueCtx) time.Sleep(10 * time.Second) fmt.Println("能够了,告诉监控进行") cancel() //为了检测监控过是否进行,如果没有监控输入,就示意进行了 time.Sleep(5 * time.Second)}

March 16, 2022 · 2 min · jiezi

关于golang:Golang力扣Leetcode剑指Offer数组61-扑克牌中的顺子

题目:从若干副扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这5张牌是不是间断的。2~10为数字自身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,能够看成任意数字。A 不能视为 14。 链接: 力扣Leetcode—剑指Offer—数组—61. 扑克牌中的顺子. 示例 1: 输出: [1,2,3,4,5]输入: True示例 2: 输出: [0,0,1,2,5]输入: True思路: 除了大小王皆为0示意,如果有其余牌(其余数字)反复,必定不是顺子。如果不存在大小王0 又因扑克牌为5张,数字排序后是一个等差序列,差值为1,则最大值最小值之差必然为4如果存在大小王0, 则最大值最小值之差不大于4 max-min<=4 即为顺子Go代码如下: package mainimport ( "fmt" "sort")func isStraight(nums []int) bool { //nums 转化为递增序列 sort.Ints(nums) //记录每个数字之间差值的和 sub := 0 n := len(nums) if n != 5 { return false } for i := 0; i < 4; i++ { if nums[i] == 0 { //continue 不进行上面的代码,进入下一次循环 continue } //如果扑克牌(非0数字)反复,不是顺子 if nums[i] == nums[i+1] { return false } //差值记录 sub += nums[i+1] - nums[i] } //总的差值小于5(或sub<=4)则为顺子 return sub < 5}func main() { a := []int{1, 2, 3, 4, 5} fmt.Println(isStraight(a))}提交截图: ...

March 15, 2022 · 1 min · jiezi

关于golang:Go-xml文件处理

在开发中会常遇到xml数据序列化和反序列化,这里咱们介绍go语言解决xml数据。encoding/xml 包实现了一个简略的xml 1.0解析器,能够了解xml名称空间。 读取xml示例: package mainimport ( "encoding/xml" "fmt")type Note struct { XMLName xml.Name `xml:"note"` To string `xml:"to"` From string `xml:"from"` Heading string `xml:"heading"` Body string `xml:"body"` Files FilesArr `xml:"files"`}type FilesArr struct { Flag string `xml:"flag,attr"` // 读取flag属性 User []string `xml:"user"` // 读取user数组}func main() { //读取xml文件到缓存中,返回[]byte //xmlDoc, err := ioutil.ReadFile("test.xml") //if err != nil { // fmt.Println("xml文件读取失败!") // return //} //fmt.Println(string(xmlDoc)) xmlDoc := `<?xml version="1.0" encoding="UTF-8"?> <note> <to>Tony</to> <from>jack</from> <heading>title</heading> <body>love you</body> <files flag="true"> <user>zhang</user> <user>li</user> </files> </note>` note := Note{} err := xml.Unmarshal([]byte(xmlDoc), &note) if err != nil { fmt.Println(err.Error()) } else { fmt.Println(note) }}读取递归数据xmlpackage mainimport ( "encoding/xml" "fmt")type ListItem struct { Name string `xml:"name"` List []ListItem `xml:"list"`}func main() { //读取xml文件到缓存中,返回[]byte //xmlDoc, err := ioutil.ReadFile("test.xml") //if err != nil { // fmt.Println("xml文件读取失败!") // return //} //fmt.Println(string(xmlDoc)) xmlDoc := `<?xml version="1.0" encoding="UTF-8"?> <list> <name>zhang</name> <list> <name>li</name> </list> </list>` list := ListItem{} err := xml.Unmarshal([]byte(xmlDoc), &list) if err != nil { fmt.Println(err.Error()) } else { fmt.Println(list) }}写入xml示例: ...

March 15, 2022 · 2 min · jiezi

关于golang:Golang力扣Leetcode剑指Offer数组57-和为s的两个数字双指针

题目:输出一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输入任意一对即可。 链接: 力扣Leetcode—剑指Offer—数组—57. 和为s的两个数字. 示例 1: 输出:nums = [2,7,11,15], target = 9输入:[2,7] 或者 [7,2]示例 2: 输出:nums = [10,26,30,31,47,60], target = 40输入:[10,30] 或者 [30,10]思路: 一开始用两个 for 循环(蛮力法),不出意外超时了.而后就想到 双指针 。因为元素是递增的,用一个指针 left 和 一个指针 right 别离记录右边和左边 如果 nums[left] + nums[right] > s, 右指针左挪动如果 nums[left] + nums[right] < s, 左指针右挪动相等就返回后果超时办法: package mainimport "fmt"func twoSum(nums []int, target int) []int { n := len(nums) var res []int for i := 0; i < n; i++ { for j := i + 1; j < n; j++ { if nums[i]+nums[j] == target { res = []int{nums[i], nums[j]} } } } return res}func main() { a := []int{2, 7, 11, 15} fmt.Println(twoSum(a, 9))} ...

March 15, 2022 · 1 min · jiezi

关于golang:golang-常见设计模式

创立型模式1.简略工厂模式2.工厂办法模式3.形象工厂模式4.创建者模式5.原型模式6.单例模式 结构型模式1.外观模式2.适配器模式3代理模式4.组合模式5.享元模式6.装璜模式7.桥模式 行为型模式1.中介者模式2.观察者模式3.命令模式4.迭代器模式5.模板办法模式6.策略模式7.状态模式8.备忘录模式9.解释器模式10.职责链模式

March 15, 2022 · 1 min · jiezi

关于golang:Golang力扣Leetcode剑指Offer数组56-I-数组中数字出现的次数哈希

题目:一个整型数组 nums 里除两个数字之外,其余数字都呈现了两次。请写程序找出这两个只呈现一次的数字。要求工夫复杂度是O(n),空间复杂度是O(1)。 链接: 力扣Leetcode—剑指Offer—数组—56 - I. 数组中数字呈现的次数. 示例 1: 输出:nums = [4,1,4,6]输入:[1,6] 或 [6,1]示例 2: 输出:nums = [1,2,10,4,1,4,3,3]输入:[2,10] 或 [10,2]思路:哈希表存储呈现的数和呈现次数,遍历输入 value 为一的 key 代码: package mainimport "fmt"func singleNumbers(nums []int) []int { m := make(map[int]int) var res []int for _, v := range nums { m[v]++ } for key, v := range m { if v == 1 { res = append(res, key) } } return res}func main() { a := []int{1, 2, 10, 4, 1, 4, 3, 3} fmt.Println(singleNumbers(a))}提交截图: ...

March 15, 2022 · 1 min · jiezi

关于golang:golang-简单工厂模式

简略工厂模式思路:多个struct实现同一个接口,在内部接口调用的时候,通过传参来表名创立哪一个实例。 毛病:新增一个类型的实例,就要大量批改多处代码。 package design_modetype ApiInter interface { Say(msg string) string}type SpeakImpls struct {}func (s SpeakImpls) Say(msg string) string { return msg}type WrangleImpls struct { }func (a WrangleImpls) Say(msg string) string { return msg}func NewApiImpls(facType string) ApiInter { if facType == "speak" { return SpeakImpls{} } return WrangleImpls{}}

March 14, 2022 · 1 min · jiezi

关于golang:第四十期shopeegolang后台一面面经

45分钟左右,编程题没写进去,感觉凉凉......记录一下 首先自我介绍 balabala... 数据库:索引的长处与毛病,底层怎么实现的?B+树的特点,与二叉树的区别事务的个性,解释一下它们其中的隔离性分几个级别?每个级别解释一下什么意思?串行化的优缺点TCP:TCP与UDP的区别TCP的长处与毛病TCP的可靠性是通过什么来保障的?解释一下确定重传机制,讲讲窗口滑动操作系统:讲讲过程与线程,零碎是怎么调度线程的?hash抵触的解决办法有哪些?看我用的golang问了go的长处怎么原生反对高并发?介绍一下协程算法题:用数组实现栈,实现pop与push,反对扩容保障性能。

March 14, 2022 · 1 min · jiezi

关于golang:Golang力扣Leetcode剑指Offer数组53-II-0~n1中缺失的数字求和二分法

题目:一个长度为n-1的递增排序数组中的所有数字都是惟一的,并且每个数字都在范畴0~n-1之内。在范畴0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。 链接: 力扣Leetcode—剑指Offer—数组—53 - II. 0~n-1中缺失的数字. 示例 1: 输出: [0,1,3]输入: 2示例 2: 输出: [0,1,2,3,4,5,6,7,9]输入: 8思路: 法一:求出 0-n 的和 sum ,再求出给定数组的和,一减就是 0-n 中缺失的数字法二:二分法 初始化: 左边界 left = 0,右边界 right = len(nums) - 1;代表闭区间 [i, j] 。循环二分: 当 i ≤ j 时循环 (即当闭区间 [i, j] 为空时跳出);计算中点 mid = (i + j) / 2若 nums[mid] = mid ,则 “右子数组的首位元素” 肯定在闭区间 [mid + 1, j] 中,因而执行 left = mid + 1;若 nums[mid] != mid ,则 “左子数组的末位元素” 肯定在闭区间 [i, mid - 1] 中,因而执行 right = mid - 1;返回值: 跳出时,变量 i 和 j 别离指向 “右子数组的首位元素” 和 “左子数组的末位元素” 。因而返回 i 即可。法一代码: ...

March 14, 2022 · 1 min · jiezi

关于golang:学习笔记带你十天轻松搞定-Go-微服务系列九-链路追踪

1、学习课程带你十天轻松搞定 Go 微服务系列(九)- 服务监控 明天是学习 go 微服务的第九天,明天是学习链路追踪 2、go-zero 应用 Jaeger 链路追踪2.1 增加 user api 服务 Telemetry 配置$ vim mall/service/user/api/etc/user.yamlName: UserHost: 0.0.0.0Port: 8000...Telemetry: Name: user.api Endpoint: http://jaeger:14268/api/traces Sampler: 1.0 Batcher: jaeger2.2 增加 user rpc 服务 Telemetry 配置$ vim mall/service/user/rpc/etc/user.yamlName: user.rpcListenOn: 0.0.0.0:9000...Telemetry: Name: user.rpc Endpoint: http://jaeger:14268/api/traces Sampler: 1.0 Batcher: jaeger2.3 增加 product api 服务 Telemetry 配置$ vim mall/service/product/api/etc/product.yamlName: ProductHost: 0.0.0.0Port: 8001...Telemetry: Name: product.api Endpoint: http://jaeger:14268/api/traces Sampler: 1.0 Batcher: jaeger2.4 增加 product rpc 服务 Telemetry 配置$ vim mall/service/product/rpc/etc/product.yamlName: product.rpcListenOn: 0.0.0.0:9001...Telemetry: Name: product.rpc Endpoint: http://jaeger:14268/api/traces Sampler: 1.0 Batcher: jaeger2.5 增加 order api 服务 Telemetry 配置$ vim mall/service/order/api/etc/order.yamlName: OrderHost: 0.0.0.0Port: 8002...Telemetry: Name: order.api Endpoint: http://jaeger:14268/api/traces Sampler: 1.0 Batcher: jaeger2.6 增加 order rpc 服务 Telemetry 配置$ vim mall/service/order/rpc/etc/order.yamlName: order.rpcListenOn: 0.0.0.0:9002...Telemetry: Name: order.rpc Endpoint: http://jaeger:14268/api/traces Sampler: 1.0 Batcher: jaeger2.7 增加 pay api 服务 Telemetry 配置$ vim mall/service/pay/api/etc/pay.yamlName: PayHost: 0.0.0.0Port: 8003...Telemetry: Name: pay.api Endpoint: http://jaeger:14268/api/traces Sampler: 1.0 Batcher: jaeger2.8 增加 pay rpc 服务 Telemetry 配置$ vim mall/service/pay/rpc/etc/pay.yamlName: pay.rpcListenOn: 0.0.0.0:9003...Telemetry: Name: pay.rpc Endpoint: http://jaeger:14268/api/traces Sampler: 1.0 Batcher: jaeger提醒:配置批改后,须要重启服务才会失效。 ...

March 13, 2022 · 1 min · jiezi

关于golang:go-excelize-批量写入数据到Excel

// CreateXlS data为要写入的数据,fileName 文件名称, headerNameArray 表头数组func CreateXlS(data [][]string, fileName string, headerNameArray []string) { f := excelize.NewFile() sheetName := "sheet1" sheetWords := []string{ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", } for k, v := range headerNameArray { f.SetCellValue(sheetName, sheetWords[k]+"1", v) } //设置列的宽度 f.SetColWidth("Sheet1", "A", sheetWords[len(headerNameArray)-1], 18) headStyleID, _ := f.NewStyle(`{ "font":{ "color":"#333333", "bold":false, "family":"arial" }, "alignment":{ "vertical":"center", "horizontal":"center" }}`) //设置表头的款式 f.SetCellStyle(sheetName, "A1", sheetWords[len(headerNameArray)-1]+"1", headStyleID) line := 1 // 循环写入数据 for _, v := range data { line++ for kk, _ := range headerNameArray { f.SetCellValue(sheetName, sheetWords[kk]+strconv.Itoa(line), v[kk]) } } // 保留文件 if err := f.SaveAs(fileName + ".xlsx"); err != nil { fmt.Println(err) }}参考文章: https://www.cnblogs.com/jrzh/... ...

March 13, 2022 · 1 min · jiezi

关于golang:Go进阶基础特性接口

接口定义了一种标准,形容了类的行为和性能。咱们都晓得,Go 语言中的接口是所谓的 Duck Typing,实现接口的所有办法也就隐式地实现了接口,那么,它是怎么实现的呢? 数据结构在 Go 语言中,接口分为两类: eface:用于示意没有办法的空接口类型变量,即 interface{} 类型的变量。iface:用于示意其余领有办法的接口类型变量。efaceeface 的数据结构如下: type eface struct { _type *_type data unsafe.Pointer}eface 有两个属性,别离是 _type 和 data,别离指向接口变量的动静类型和动静值。 再进一步看看 type 属性的构造: type _type struct { size uintptr // 类型大小 ptrdata uintptr // 蕴含所有指针的内存前缀的大小 hash uint32 // 类型的 hash 值 tflag tflag // 类型的 flag 标记,次要用于反射 align uint8 // 内存对齐相干 fieldAlign uint8 // 内存对齐相干 kind uint8 // 类型的编号,蕴含 Go 语言中的所有类型,如 kindBool、kindInt 等 equal func(unsafe.Pointer, unsafe.Pointer) bool // 用于比拟此对象的回调函数 gcdata *byte // 存储垃圾收集器的 GC 类型数据 str nameOff ptrToThis typeOff}注:Go 语言的各种数据类型都是在 _type 字段的根底上,减少一些额定的字段来进行治理的。 ...

March 13, 2022 · 5 min · jiezi

关于golang:学习笔记带你十天轻松搞定-Go-微服务系列八-服务监控

1、学习课程带你十天轻松搞定 Go 微服务系列(八)- 服务监控 明天是学习 go 微服务的第八天,咱们持续接着昨天的步骤,搭建服务监控 2、增加服务2.1 增加 user api 服务 Prometheus 配置$ vim mall/service/user/api/etc/user.yamlName: UserHost: 0.0.0.0Port: 8000...Prometheus: Host: 0.0.0.0 Port: 9080 Path: /metrics2.2 增加 user rpc 服务 Prometheus 配置$ vim mall/service/user/rpc/etc/user.yamlName: user.rpcListenOn: 0.0.0.0:9000...Prometheus: Host: 0.0.0.0 Port: 9090 Path: /metrics2.3 增加 product api 服务 Prometheus 配置$ vim mall/service/product/api/etc/product.yamlName: ProductHost: 0.0.0.0Port: 8001...Prometheus: Host: 0.0.0.0 Port: 9081 Path: /metrics2.4 增加 product rpc 服务 Prometheus 配置$ vim mall/service/product/rpc/etc/product.yamlName: product.rpcListenOn: 0.0.0.0:9001...Prometheus: Host: 0.0.0.0 Port: 9091 Path: /metrics2.5 增加 order api 服务 Prometheus 配置$ vim mall/service/order/api/etc/order.yamlName: OrderHost: 0.0.0.0Port: 8002...Prometheus: Host: 0.0.0.0 Port: 9082 Path: /metrics2.6 增加 order rpc 服务 Prometheus 配置$ vim mall/service/order/rpc/etc/order.yamlName: order.rpcListenOn: 0.0.0.0:9002...Prometheus: Host: 0.0.0.0 Port: 9092 Path: /metrics2.7 增加 pay api 服务 Prometheus 配置$ vim mall/service/pay/api/etc/pay.yamlName: PayHost: 0.0.0.0Port: 8003...Prometheus: Host: 0.0.0.0 Port: 9083 Path: /metrics2.8 增加 pay rpc 服务 Prometheus 配置$ vim mall/service/pay/rpc/etc/pay.yamlName: pay.rpcListenOn: 0.0.0.0:9003...Prometheus: Host: 0.0.0.0 Port: 9093 Path: /metrics提醒:配置批改后,须要重启服务才会失效。 ...

March 13, 2022 · 3 min · jiezi

关于golang:goland进阶调试本地进程

大部分人都用过goland的debug,但这种debug只是一个初级阶段的利用,适宜用于单体服务,数据流转比拟繁多的,在开发或调试过程中,http申请能够间接发到由goland启动的过程中。 但如果是申请并非间接到goland,而是发送给曾经是二进制的过程呢? 如果是单纯点击“Debug”按钮的话,尽管进入了debug状态,但会发现http申请发动了,但没有被goland捕捉到,所以没有方法通过goland的“Step into”、“Step out”等调试按钮实现调试过程。 解决方案: Attach to Process package mainimport ( "github.com/gin-gonic/gin")func main() { r := gin.Default() r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) }) r.Run()}①为了可能Attach to Process过程绑定,不便调试,须要用以下命令生成二进制文件,运行程序go build -gcflags="all=-N -l" # -gcflags="all=-N -l"目标是去掉编译优化,不便调试②进入goland,打上断点,鼠标点击菜单栏“Run” ③点击Attach to Process ④这时候ide会弹出过程抉择框,即抉择绑定哪个过程,进行调试。 ⑤绑定过程后就进入到了ide的调试状态 留神:肯定要用指定的命令生成的二进制文件,能力被ide捕捉到,否则就会说“No process to attach to” go build -gcflags="all=-N -l" # -gcflags="all=-N -l"目标是去掉编译优化,不便调试试验一下,发动申请,能够看到申请在之前打的断点中拦住了,阐明操作是正确的,能够debug本地机器的go过程了。 浏览器拜访 http://127.0.0.1:8080/ping 参考文章: https://blog.csdn.net/qq_4240...

March 13, 2022 · 1 min · jiezi

关于golang:一个用go实现的有限状态机

easyfsm一个用go实现的超容易上手的无限状态机。 它的特点: 应用简略,疾速了解。对应状态事件只需全局注册一次,不须要多处注册。反对不同业务->雷同状态值->自定义不同事件处理器(上面会举)为什么不应用looplab/fsm,star挺多的啊。 不是特地喜爱,每次实例化fsm都须要从新传递对应events(尽管咱们能够对立封装),我更冀望在我的项目启动时把此我的项目波及到不同业务状态机流转注册到fsm,对应:不同业务->[状态]->[事件]->处理事件主体(蕴含handler、params、hooks、observers等)。 这就是easyfsm的由来。 当你开始进行状态流转时,只须要, 为什么须要辨别业务? 因为绝大多数业务的状态值都是从数据库中获取的,比方订单表的订单状态,商品表中的商品状态,有可能值是雷同的。 同一个业务同一属性对应状态值表白繁多,不同业务下属性状态可能会呈现值雷同,但所表白的含意是不同的。 整体设计: 简略解释一下: 业务:比方有商品状态业务、订单状态业务.....状态:订单待付款、待发货....事件:对应状态仅可达事件汇合。比方待付款状态的可达事件仅有:领取事件和勾销事件(取决于本人的业务)执行事件主体:执行自定义的事件函数,如果有须要,还能够自定义执行事件前后hook,事件订阅者(比方领取事件产生后,异步告诉用户等)应用姿态 首先自定义业务、状态、事件。 自定义事件主体, 注册到easyfsm。 开始应用。 残缺示例代码如下, Hook如果想在处理事件函数的前后执行一些hook,或者在事件执行结束,异步执行一些其余业务,easyfsm定义了这两个接口, 咱们能够实现这两个接口, 残缺代码: 总结 下面简略介绍了下easyfsm设计以及对应应用姿态。 如果有其余不一样的需要,欢送大家在issue留言提需要。https://github.com/wuqinqiang/easyfsm

March 12, 2022 · 1 min · jiezi

关于golang:Go-Quiz-从Go面试题看锁的注意事项

背景Google工程师Valentin Deleplace出了2道对于锁的题目,拿进去和大家分享下。 题目1// quiz_lock1.gopackage mainimport ( "fmt" "sync")func main() { var m sync.Mutex fmt.Print("1, ") m.Lock() m.Lock() m.Unlock() fmt.Println("2")}A: 1, 2B: 1, C: 1, fatal error:......D: 编译报错题目2// quiz_lock2.gopackage mainimport ( "fmt" "sync" "time")func main() { var m sync.Mutex fmt.Print("1, ") m.Lock() go func() { time.Sleep(200 * time.Millisecond) m.Unlock() }() m.Lock() fmt.Println("2")}A: 1, 2B: 1, C: 1, fatal error:......D: 编译报错解析Go语言里的sync.Mutex和sync.RWMutex都是不可重入的,Go语言里没有可重入锁(也叫递归锁)。 如果mutex没有开释,在同一个goroutine就不能对这个mutex加2次锁,否则第2次加锁就会阻塞,如果没有其它goroutine去开释这个mutex,就会导致死锁,呈现runtime error: fatal error: all goroutines are asleep - deadlock!。 ...

March 12, 2022 · 1 min · jiezi

关于golang:go算法组合排列1

组合算法(一)组合算法在面试中可能会出相干的口试题以此来考验面试者的功底,解决口试题目以外咱们还能够在一些利用场景中应用典型场景: 01. 介绍场景利用1. 属性组合 依据商品的属性规格计算能够组合的sku有多少种【什么是sku?这个不介绍了】如下 某某商品的属性规格(电脑) 色彩 = {银灰色,纯彩色,淡绿色}CPU/运行内存 = {i7-8/16G, i7-8/8G, i5-8/16G, i5-8/8G}存储空间 = {1T, 512G}以下面三中规格属性组成具体的sku则就是;有如下24种 sku1 = {银灰色, i7-8/16G, 1T}sku2 = {纯彩色, i7-8/16, 512G}sku3 = {淡绿色, i5-8/16, 512G}...尽管我脑子通知咱们晓得如何去计算然而,理论要用程序来写一脸懵,说的就是你 2. 随机礼品赠送 比方在20个礼品中抉择10个礼品赠送给客户,这里就波及到话题是给定一个元素列表从中抉择n个元素进行排列组合; 等其余场景... 面试题在面试题中,当然不乏有以下面的利用场景作为面试题的;还有的则为如下状况 给定一个字符串a,b,c,d利用程序计算它的组合形式如abcd,abdc,adcb...计算共有多少种组合形式;并且还能够输入,还要求工夫复杂度最低....; 个别看到这样的口试题目,心里就会说句:“好家伙脑子晓得怎么排,然而下手有蒙圈了” 除了下面的题目外也可能存在给定一个数组或字符串从中随机抉择几个元素进行排序等等,组合排序有很多.. 等其余面试题... 优雅永不过期 我也遇到过,略微沉着一下,咋们往下合成 02. 题1. 给定一个字符串abcd,求整体元素的组合类型实现形式1思路:在思路上抉择后面的元素地位不进行变动,对前面的元素进行组合;将组合之后的后果与后面的元素拼接组合则实现组合排序; 如同;对abc进行组合,选中a不动对bc进行组合;也就是咱们思考两个元素的组合实现; a := "bc"var ret []stringfor k, v := range a { tmp = fmt.Sprintf("%s%s", data[:k], data[k+1:]) for _, j := range tmp { ret = append(ret, string(v) + ""+ r ) }}fmt.Printf("ret = %v", ret)在实现上咱们能够通过如上代码实现;先对a循环,在循环实现之后能够通过切片的形式获取v的前后元素并写入到tmp中,再利用外部的循环实现对程序的组合 ...

March 12, 2022 · 3 min · jiezi

关于golang:Golang-基础之基础语法梳理-三

大家好,明天将梳理出的 Go语言根底语法内容,分享给大家。 请多多指教,谢谢。 本次《Go语言根底语法内容》共分为三个章节,本文为第三章节 Golang 根底之根底语法梳理 (一)Golang 根底之根底语法梳理 (二)Golang 根底之根底语法梳理 (三)本章节内容interface反射泛型interface介绍在Go语言中接口 (interface) 是一种类型, 一种形象的类型。 接口 (interface) 定义了一个对象的行为规范, 只定义标准不实现,由具体的对象来实现标准的细节。 接口做的事件就像是定义一个协定(规定)。 Interface 是一组method的汇合, 是duck-type programming 的一种体现。 接口的定义 接口是一个或多个办法签名的汇合接口只有办法申明,没有实现,没有数据字段接口能够匿名嵌入其余接口,或嵌入到构造中接口调用不会做receiver的主动转换接口同样反对匿名字段办法接口也可实现相似OOP中的多态任何类型的办法集中只有领有该接口'对应的全副办法'签名只有当接口存储的类型和对象都为nil时,接口才等于nil用 interface{} 传递任意类型数据是Go语言的常规用法,而且 interface{} 是类型平安的空接口能够作为任何类型数据的容器一个类型可实现多个接口接口命名习惯以 er 结尾应用每个接口由数个办法组成,接口的定义如下 type 接口类型 interface { 办法名1 (参数列表1) 返回值列表1 办法名2 (参数列表2) 返回值列表2 ...}留神 接口名:应用type将接口定义为自定义的类型名。Go语言的接口在命名时,个别会在单词前面增加er,如有写操作的接口叫Writer,有字符串性能的接口叫Stringer等。接口名最好要能突出该接口的类型含意。办法名:当办法名首字母是大写且这个接口类型名首字母也是大写时,这个办法能够被接口所在的包(package)之外的代码拜访。参数列表、返回值列表:参数列表和返回值列表中的参数变量名能够省略。例子 type writer interface { Write([]byte) error}值接收者和指针接管接口 type Mover interface { move()}type dog struct {}func (d dog) move() { fmt.Println("狗狗")}func main() { var x Mover var wangcai = dog{} x = wangcai // x 能够接管dog类型 var fugui = &dog{} // fugui是 *dog 类型 x = fugui // x能够接管*dog类型 指针接管 x.move() }多个类型实现同一接口 ...

March 11, 2022 · 4 min · jiezi

关于golang:第三十八期字节跳动后台开发二面凉经

简历上写了C++和golang,所以两个语言都波及了 一面:golang如何设计一个生产者消费者的模型对channel和goroutine的了解字符串实现减法疾速排序c++虚函数过程的通信形式死锁二面:Linux的几个操作找出二叉树中的某门路,使其和为定值二叉树转为双向[表CPU调度形式channel缓冲的问题一二面都还有几个问题的,然而几天后面的切实是想不起来了,其实面得都比拟根底,就是面很广。 算法我基本上都没问题了,然而二面的Linux和其余几个答得太差,而且一点我最善于的计算机网络一点都没问,也是挺郁闷的。

March 11, 2022 · 1 min · jiezi

关于golang:Golang-基础之基础语法梳理-二

大家好,明天将梳理出的 Go语言根底语法内容,分享给大家。 请多多指教,谢谢。 本次《Go语言根底语法内容》共分为三个章节,本文为第二章节 Golang 根底之根底语法梳理 (一)Golang 根底之根底语法梳理 (二)Golang 根底之根底语法梳理 (三)本章节内容channel构造体指针管制语句channel介绍单纯地将函数并发执行是没有意义的。函数与函数间须要替换数据能力体现并发执行函数的意义,channel就是它们之间的连贯。 channel能够让一个 goroutine 发送特定值到另一个 goroutine 的通信机制。 Go 语言中的通道(channel)是一种非凡的类型。通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规定,保障收发数据的程序。每一个通道都是一个具体类型的导管,也就是申明channel的时候须要为其指定元素类型。 留神:goroutine 是go语言中特有的机制,能够了解为go语言中的线程。 应用goroutine, 能够应用go关键字 go并发方面的常识会放到后续文章中,和大家分享。 此知识点中简略理解即可 应用channel 申明 channel是一种类型,一种援用类型。语法格局: var 变量 chan 元素类型例子 var ch1 chan int // 申明一个传递整型的通道 var ch2 chan bool // 申明一个传递布尔型的通道 var ch3 chan []int // 申明一个传递int切片的通道 创立 channel 通道是援用类型,通道类型的空值是nil。 申明的通道后须要应用make函数初始化之后能力应用。 make(chan 元素类型, 缓冲大小) // 格局例子 ch4 := make(chan int)ch5 := make(chan bool)ch6 := make(chan []int)channel操作 ...

March 10, 2022 · 4 min · jiezi

关于golang:golang-获取三种不同的路径方法执行路径项目路径文件路径

func checkErr(err error) { if err != nil { panic(err) }}//获取以后的执行门路//C:\Users\Vic\AppData\Local\Temp\func getCurrentPath() string { s, err := exec.LookPath(os.Args[0]) checkErr(err) i := strings.LastIndex(s, "\\") path := string(s[0 : i+1]) return path}//获取以后文件的具体门路//D:/Go/workspace/port/network_learn/server/server.gofunc CurrentFile() string { _, file, _, ok := runtime.Caller(1) if !ok { panic(errors.New("Can not get current file info")) } return file}func main() { //D:\Go\workspace\port 以后我的项目的门路 pa,_:=os.Getwd() path:=getCurrentPath() filePath:=CurrentFile() fmt.Println(pa) fmt.Println(path) fmt.Println(filePath)}

March 10, 2022 · 1 min · jiezi

关于golang:运行goctl-model运行模板生成命令报错解决方法

1、问题Linux 下部署 go-zero,运行 goctl model 运行模板生成命令报以下错 Command 'goctl' not found, did you mean: command 'doctl' from snap doctl (v1.69.0+git2.8af78470)See 'snap info <snapname>' for additional versions. 2、解决办法在宿主机未装置 goctl 是不能拜访的应用的,咱们进入 golang 容器应用就好了(前面有须要 goctl 都要进入容器应用 goctl ) 2.1 查找golang 容器信息 $ docker ps | grep golang #查找golang 容器信息这外面列出所有在运行的容器信息,第一项就是CONTAINER ID,上面要用到 CONTAINER ID IMAGE COMMAND ... PORTS NAMES2.2 进入 golang 容器$ docker exec -it container-id /bin/bash #进入容器 默认进入到/usr/src/code 可用dir查看目录这里的 container-id 就换成下面 CONTAINER ID 的信息,我这里是 13258ded6d62 ...

March 9, 2022 · 1 min · jiezi

关于golang:Golang-基础之基础语法梳理-一

大家好,明天将梳理出的 Go语言根底语法内容,分享给大家。 请多多指教,谢谢。 本次《Go语言根底语法内容》共分为三个章节,本文为第一章节 Golang 根底之根底语法梳理 (一)Golang 根底之根底语法梳理 (二)Golang 根底之根底语法梳理 (三)本章节内容Go关键字示例Demo申明、赋值援用类型slicemapGo关键字Go语言中共有25个关键字,根底语法章节中将为大家介绍全副关键字的应用。 break default func interface selectcase defer go map structchan else goto package switchconst fallthrough if range typecontinue for import return var预约义名称列表 // 内建常量 true false iota nil// 内建类型 int int8 int16 int32 int64uint uint8 uint16 uint32 uint64 uintptrfloat32 float64 complex128 complex64bool byte rune string error// 内建函数make len cap new append copy close deletecomplex real imagpanic recover内建函数局部,将由后续章节介绍。 示例Demo 在以上Go语言示例代码中,次要由三局部蕴含组成: ...

March 9, 2022 · 2 min · jiezi

关于golang:第三十六期B站一面

总共36分钟,面试官很准时,没有写算法题。 自我介绍介绍我的项目并发问基于我实习期间学习了go语言(并且B站服务端用的也是go),发问了一些go语言的根底问题go的值类型和援用类型go的slice底层原理go的GC机制用go结构一个链表怎么做,想要从链表尾部插入,怎么做(我听到这个问题懵了一下?而后就基于ListNode和List构造体,说了一下,而后在List构造体里保留头尾指针这样)B站app的页面分区怎么设计(这个一开始没想到应该怎么答复,最初答复的是数据库表的设计,主键和外键)数据库的索引(不太记得问了什么)介绍TCP和UDP的区别,说一下tcp的拥塞算法(四个)你还有什么要问我的吗?

March 9, 2022 · 1 min · jiezi

关于golang:golang的json过滤器随心所欲的构造自己的json数据随意复用结构体

反对过滤的数据结构github地址:https://github.com/liu-cn/jso... json-filter 构造体/嵌套构造体/匿名构造体/指针构造体切片/数组map 应用场景有时候你可能会遇到这种状况:一个构造体想要在不同的接口下返回不同的json数据字段。举个例子:一个模仿用户的model,实在环境中的字段会要比这个多得多。 type User struct { UID uint `json:"uid"` Avatar string `json:"avatar"` Nickname string `json:"nickname"` Sex int `json:"sex"` VipEndTime time.Time `json:"vip_end_time"` Price string `json:"price"` //上面可能还有更多的字段,实在的环境中可能有几十个字段。}设计的起因文章接口中须要返回用户User的数据,然而你只须要在文章接口中返回用户的 UID Avatar 和Nickname这三个字段就够了,并不想暴露出其余用不上的字段,因为返回更多的字段意味着更大的数据,编解码更加耗时,而且也会耗费更多的网络带宽,传输速度会变慢。 这时候你可能须要创立一个新的构造体而后把这三个字段赋值,序列化并返回,而后业务越来越多,用到User 的中央越来越多,profile接口下须要返回用户的 Nickname VipEndTime 和Price这三个字段,这时候比可能又要再创立一个构造体,再复制字段,赋值,序列化返回,就像这样 传统的解决方案 user:=User{}------------------------------形式1------------------------//定义一个新的model type UserArticleRes struct { UID uint `json:"uid"` Avatar string `json:"avatar"` Nickname string `json:"nickname"` } userRes :=UserArticleRes{ UID: user.UID, Avatar: user.Avatar, Nickname: user.Nickname, } return userRes------------------------------形式2------------------------//或者间接应用匿名构造体。 res:= struct { UID uint `json:"uid"` Avatar string `json:"avatar"` Nickname string `json:"nickname"` }{ UID: user.UID, Avatar: user.Avatar, Nickname: user.Nickname, } return res方正这两种形式都大差不差,而后更多的场景都用到了User 构造体,私信接口,直播接口,评论等等,而后可能须要反复以上的操作,如果这样搞的话会有很多model须要治理,而且开发效率很低,一个字段改掉其余很多构造体都会受到影响,治理起来麻烦,不灵便,不易扩大, ...

March 8, 2022 · 4 min · jiezi

关于golang:Leetcode专题二叉树110平衡二叉树

力扣链接:https://leetcode-cn.com/probl...解题思路: 均衡二叉树的定义:二叉树每个节点的左右两个子树的高度差的绝对值不超过 1求二叉树的门路或者活深度的时候,应用的是前序遍历,而求高度的时候,应用的是后序遍历递归求解三部曲:(1)确定参数:传入的参数就是节点,初始化就是根节点 (2)完结条件,当root == nil时返回的就是true (3)单层递归条件:后序遍历,先遍历左子树,再遍历右子树,最初解决根节点// 应用递归的方法,求出左右子树,判断左右子树是否是均衡二叉树func isBalanced(root *TreeNode) bool { if root == nil { return true } // 别离递归判断左右子树是不是均衡二叉树 if !isBalanced(root.Left) || !isBalanced(root.Right) { return false } leftHigh := maxDepth(root.Left) + 1 rightHign := maxDepth(root.Right) + 1 if abs(leftHigh, rightHign) > 1 { return false } return true}func maxDepth(node *TreeNode) int { if node == nil { return 0 } left := maxDepth(node.Left) right := maxDepth(node.Right) return max(left, right) + 1}func max(a, b int) int { if a > b { return a } return b}func abs(x, y int) int { r := x - y if r < 0 { return -1 * r } return r}

March 8, 2022 · 1 min · jiezi

关于golang:Leetcode专题二叉树257二叉树的所有路径

力扣链接:https://leetcode-cn.com/probl...解题思路: 二叉树的所有门路,这里其实是DFS深度优先遍历,须要从跟节点遍历,直到遇到字节点,为一个门路递归前序遍历,递归三部曲:(1)传入参数:这里传入的参数是每个节点,初始化为根节点 (2)完结条件:当某个节点的左右子树均为空时即为一次后果 (3)单次遍历规定:因为是DFS,所以能够应用前序遍历// 递归法func binaryTreePaths(root *TreeNode) []string { res := []string{} var traver func(node *TreeNode, s string) traver = func(node *TreeNode, s string) { if node.Left == nil && node.Right == nil { s = s + strconv.Itoa(node.Val) res = append(res, s) return } s = s + strconv.Itoa(node.Val) + "->" if node.Left != nil { traver(node.Left, s) } if node.Right != nil { traver(node.Right, s) } } traver(root, "") return res}

March 8, 2022 · 1 min · jiezi

关于golang:Golang力扣Leetcode剑指Offer数组17打印从1到最大的n位数遍历

题目:输出数字 n,按程序打印出从 1 到最大的 n 位十进制数。比方输出 3,则打印出 1、2、3 始终到最大的 3 位数 999。 链接: 力扣Leetcode—剑指Offer—数组—17.打印从1到最大的n位数. 示例 1: 输出: n = 1输入: [1,2,3,4,5,6,7,8,9]思路:依据位数找到最大值,而后遍历打印进去 Go代码如下: package mainimport ( "fmt" "math")func printNumbers(n int) []int { var sum int var numbers []int for i := n; i > 0; i-- { a := 9 * int(math.Pow(10, float64(i-1))) sum += a } fmt.Println(sum) for i := 1; i <= sum; i++ { numbers = append(numbers, i) } return numbers}func main() { fmt.Println(printNumbers(0))}提交截图: ...

March 8, 2022 · 1 min · jiezi

关于golang:第三十五期校招golang工程师面经-华为

简略的排序算法和大学期间做的我的项目经验;问了一道对于ip筛选的题目;写了个冒泡算法,简历上写了相熟linux内核,问了拥塞相干的常识;问了mysql,redis,出了一道数据结构题,问了golang,手撕代码。问了http协定,golang 开源框架的源码了解;负载平衡怎么实现,分布式锁;我的项目上遇到的艰难,做的称心的我的项目怎么设计的。问了golang的interface的区别,继承,gc的原理、区别,双向链表等。- 问:mysql innodb的底层构造,画进去。 答:b+tree 。 - 问:取链表的两头节点。 答:快慢指针 - 问:给定n个并发量,并发解决数组 答:应用channel实现。 - 问:redis list的底层实现。

March 8, 2022 · 1 min · jiezi

关于golang:学习笔记带你十天轻松搞定-Go-微服务系列四-产品服务

1、学习课程带你十天轻松搞定 Go 微服务系列(四) 2、产品服务(product)进入服务工作区 $ cd mall/service/product2.1 生成 product model 模型创立 sql 文件 $ vim model/product.sql编写 sql 文件 CREATE TABLE `product` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL DEFAULT '' COMMENT '产品名称', `desc` varchar(255) NOT NULL DEFAULT '' COMMENT '产品描述', `stock` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '产品库存', `amount` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '产品金额', `status` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '产品状态', `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;运行模板生成命令(和昨天一样要在golang容器下运行) ...

March 8, 2022 · 7 min · jiezi

关于golang:学习笔记带你十天轻松搞定-Go-微服务系列三-用户服务

1、学习课程带你十天轻松搞定 Go 微服务系列(三) 2、生成 user model 模型在昨天代码目录 xxx/gonivinck/code 下 $ cd mall/service/user # 进入mall/service/user文件夹$ vim model/user.sql #创立 sql 间接 copy 上面语句就行了sql 语句如下: CREATE TABLE `user` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL DEFAULT '' COMMENT '用户姓名', `gender` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '用户性别', `mobile` varchar(255) NOT NULL DEFAULT '' COMMENT '用户电话', `password` varchar(255) NOT NULL DEFAULT '' COMMENT '用户明码', `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `idx_mobile_unique` (`mobile`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;再运行模板生成命令 ...

March 7, 2022 · 7 min · jiezi

关于golang:第三十四期Golang社招面经快手

快手:4轮技术1hr 口头offer 一面:欢畅局 看你简历大学有比赛经验,算法都懂吧?我:理解 面试官:嗯,理解就不问了raft算法懂不?我:懂 面试官:嗯,懂就不问了讲讲tidb讲讲newsql我的项目吞吐量,怎么优化的性能?工作有啥亮点?产出?共识怎么做的?二面mmap操作原理 答:1.内存映射 2.逻辑/物理地址转换 3. 程序拜访触发缺页中断 4. 调页诘问:mmap的问题?答了内存过大时会呈现频繁的页面置换 影响效率tidb我的项目介绍 sql parser做了啥?planner做了啥?讲 epoll过程线程区别(刨根问底式各种OS问题虚拟内存, 缺页置换?MMU?写个代码 (忘了问啥了三面:我的项目介绍设计一个kv存储说一下你了解的共识算法说一下多路复用四面:我的项目介绍间接io与mmap区别?分布式系统保证数据一致性?redis主从怎么做的数据统一?redis哨兵?讲讲排序算法 优缺点http连环问题 tcp连环问题 长链接短链接http header 干啥用的?写个代码 dijkstra模版题(用go写可真吃力hr 面大学做过骄傲的事一堆小问题

March 7, 2022 · 1 min · jiezi

关于golang:Golang力扣Leetcode剑指Offer数组11旋转数组的最小数字遍历

题目:把一个数组最开始的若干个元素搬到数组的开端,咱们称之为数组的旋转。 给你一个可能存在 反复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情景进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为1。 链接: 力扣Leetcode—剑指Offer—数组—11.旋转数组的最小数字. 示例 1: 输出:[3,4,5,1,2]输入:1示例 2: 输出:[2,2,2,0,1]输入:0思路:设最小值 min 在 numbers[0] ,遍历数组,如果比 min 小就取代变成新的 min,直到遍历实现,输入 min Go代码如下: package mainimport "fmt"func minArray(numbers []int) int { n := len(numbers) min := numbers[0] for i := 0; i < n; i++ { if numbers[i] <= min { min = numbers[i] } } return min}func main() { a := []int{3, 4, 5, 1, 2} fmt.Println(minArray(a))}提交截图: ...

March 7, 2022 · 1 min · jiezi

关于golang:Golangpointer

指针特点:Go语言不存在指针操作,波及两个符号:& 与 *,即"取地址"与"依据地址取值"分配内存的函数:new 与 makemake: 只作用于slice、map、chan三种援用类型的内存创立,所以返回的值并不是指针,而是这三个类型自身。new: 个别是给根本数据类型申请内存的,如int,string,返回的是对应类型的指针,如int,string。package mainimport "fmt"func main() { //*与&的应用 var a = 100 p := &a fmt.Println(p) b := *p fmt.Println(b) //make 与 new var a1 = new(int) fmt.Println(a1) fmt.Printf("%T", a1) //返回值类型是*int fmt.Println() var a2 = make([]int, 3, 3) fmt.Printf("%T", a2) //返回值类型是int,是根底数据类型自身}运行后果: 0xc00001a0801000xc00001a088*int[]int

March 7, 2022 · 1 min · jiezi

关于golang:Golangunicode

//对字符串中汉字数量进行统计//unicode.Is() package mainimport ( "fmt" "unicode")//Han示意汉字,其它语言表达可在字符集中查问func main() { a := "すごい,明天你pass了English考试" count := 0 for _, v := range a { if unicode.Is(unicode.Han, v) { count++ } } fmt.Println(count)}运行后果:6

March 7, 2022 · 1 min · jiezi

关于golang:利用go实现mysql批量测试数据生成TDG

利用go实现mysql批量测试数据生成-TDG组件代码:https://gitee.com/dn-jinmin/tdg 下载go get gitee.com/dn-jinimin/tdg 目前只针对mysql,只反对多个单表批量新增,关联新增还未实现实现 01. 登程之所以开发TDG这个工具次要是因为,很多敌人在学习数据库索引及SQL优化、本人我的项目开发等状况的时候都会面临一个问题;就是没有数据能够测试; 比方SQL优化最显著,在目前零碎中数据量在500w以上及1000w的时候建设索引并尝试去进行优化,这样的成果比几条数据仅通过explain剖析更为直观,我也遇到过这个问题 测试数据的生成形式有很多种;比方利用数据库的存储过程,或者本人用程序写一个等等,因而就一不小心本人就写了一个,顺带再好好坚固go; 利用go开发的,并且编译成了可执行文件能够间接下载使用; 舒适提醒:应用中请留神看代码文档配置,稍有不慎就...; __当然心愿这个工具可能给你带来好的帮忙,上面是对工具的实现介绍,及实现思路,集体能力无限如果你应用中有更好意见欢送指导,冀望能star一下Thanks♪(・・)ノ 02. 构思mysql对于数据的写入mysql对于数据的写入惯例的形式就是执行如下SQL命令写入数据 insert into table_name (col1,col2)values(data1, data2)如果存在一份 xxx.sql 的文件能够通过 source xxx.sql还能够采纳mysql中的 load data xxx xxx.txt针对mysql如何疾速批量生成测试数据须要解决的几个问题如何疾速生成?如何针对表生成须要针对不同字段要求生成数据可自定义对不同的表去生成这是针对mysql如何高效的生成测试数据必须要思考并要解决的问题,我的思考过程...(因为篇幅太长此处省略....N..字) tdg实现思路首先在整体的思路上是基于sql,通过insert的形式写入的策略实现的;利用insert语句批量新增的形式;如下格局 insert into table_name (col1,col2) values(data1, data2),(data1,data2)tdg对于SQL的生成分为三块 1. SQL开始与table_name insert into table_name2. 字段列 (col1, col2)3. 写入数据 values(data1, data2),(data1, data2)tdg则就是针对SQL的生成与拼接组装最终构建一条批量新增的insert语句,将生成的数据写入到mysql中; 03. 具体实现在整体的实现中能够分为四个节点:初始化、数据生成规定、SQL生成、SQL写入 数据生成规定这里咱们先理解一下规定是如何实现的,因为思考到在mysql中对于字段咱们会因为数据的特点会有对应的要求,比方id能够是int也能够是string、order会有属于它本人的要求形式,phone,date,name等等会存在多种类型的数据要求; 因而规定的设计次要是依据列的利用所对应的类型设计会蕴含如下的规定 这些规定会在初始化的时候加载;整体的设计上是定义一个对立的规定接口在build/filed.go中 type Column struct { // 字段标签,确定字段生成形式 Tag string `json:"tag"` // 字段固定长度 Len int `json:"len"` // 长度范畴,可变长度 FixedLen interface{} `json:"fixed_len"` // 字段最大值 Max int `json:"max"` // 字段最小值 Min int `json:"min"` // 其它参数 Params interface{} `json:"params"` // 默认值 Default struct { Value interface{} `json:"value"` Frequency int `json:"frequency"` } `json:"default"` // 指定随机内容 Content []interface{} `json:"content"`}type Tag interface { Name() string Handler(column *Column) string Desc() string}Name() 代表是规定的标签名称,Hander具体的随机办法,Desc打印输出的形容;思考到规定的丰富性定义一个对立的column构造体作为hander的参数,而不同规定能够依据column中的参数设置进行随机生成想要的后果; 如下为示例, ...

March 6, 2022 · 3 min · jiezi

关于golang:Golang力扣Leetcode剑指Offer数组03数组中重复的数字哈希表

题目:找出数组中反复的数字。 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范畴内。数组中某些数字是反复的,但不晓得有几个数字反复了,也不晓得每个数字反复了几次。请找出数组中任意一个反复的数字。 链接: 力扣Leetcode—剑指Offer—数组—03.数组中反复的数字. 示例 1: 输出:[2, 3, 1, 0, 2, 5, 3]输入:2 或 3思路:一开始用两个 for 循环遍历,一下子就超时了,代码如下: func findRepeatNumber(nums []int) int { n := len(nums) res := 0 for i := 0; i < n; i++ { for j := i + 1; j < n; j++ { if nums[i] == nums[j] { res = nums[i] break } else { continue } } } return res}简简单单超时: ...

March 6, 2022 · 1 min · jiezi

关于golang:学习笔记带你十天轻松搞定-Go-微服务系列二

1、学习课程带你十天轻松搞定 Go 微服务系列(二) 2、服务拆分2.1 按业务服务拆分用户服务(user)订单服务(order)产品服务(product)领取服务(pay)售后服务(afterSale)... ... 2.2 按调用形式拆分区别API 服务RPC 服务传输协定基于 HTTP 协定能够基于 HTTP 协定,也能够基于 TCP 协定传输效率如果是基于 http1.1 的协定,申请中会蕴含很多无用的内容,如果是基于 HTTP2.0,那么简略的封装下能够作为一个 RPC 来应用,这时规范的 RPC 框架更多的是服务治理。应用自定义的 TCP 协定,能够让申请报文体积更小,或者应用 HTTP2 协定,也能够很好的减小报文体积,进步传输效率性能耗费大部分是基于 json 实现的,字节大小和序列化耗时都比 thrift 要更耗费性能能够基于 thrift 实现高效的二进制传输负载平衡须要配置 Nginx、HAProxy 配置根本自带了负载平衡策略服务治理:(上游服务新增,重启,下线时如何不影响上游调用者)须要当时告诉,如批改 NGINX 配置。能做到主动告诉,不影响上游3、创立我的项目目录3.1 在 code 中新建我的项目$ cd gonivinck/code/ 3.2 创立 mall 工程$ mkdir mall && cd mall$ go mod init mall3.3 创立 common 目录$ mkdir common3.4 创立 service 目录$ mkdir service && cd service3.5 创立 user api,user rpc,user model 目录$ mkdir -p user/api$ mkdir -p user/rpc$ mkdir -p user/model3.6 创立 product api,product rpc,product model 目录$ mkdir -p product/api$ mkdir -p product/rpc$ mkdir -p product/model3.7 创立 order api,order rpc,order model 目录$ mkdir -p order/api$ mkdir -p order/rpc$ mkdir -p order/model3.8 创立 pay api,pay rpc,pay model 目录$ mkdir -p pay/api$ mkdir -p pay/rpc$ mkdir -p pay/model3.9 最终我的项目目录├── common # 通用库├── service # 服务│ ├── order│ │ ├── api # order api 服务│ │ ├── model # order 数据模型│ │ └── rpc # order rpc 服务│ ├── pay│ │ ├── api # pay api 服务│ │ ├── model # pay 数据模型│ │ └── rpc # pay rpc 服务│ ├── product│ │ ├── api # product api 服务│ │ ├── model # product 数据模型│ │ └── rpc # product rpc 服务│ └── user│ ├── api # user api 服务│ ├── model # user 数据模型│ └── rpc # user rpc 服务└── go.mod ...

March 6, 2022 · 2 min · jiezi

关于golang:go优化记录01随机数值优化策略

利用Go随机数值优化用例代码:https://gitee.com/dn-jinmin/g... 01 根底性能实现优化在go中对于随机int数值的办法能够利用规范库在的"math/rand"进行实现; package utilsimport ( "time" "math/rand")func docGoRandInt32(maxN int) int { rand.Seed(time.Now().UnixNano()) return rand.Intn(maxN)}测试用例 package utilsimport "testing"func Test_docGoRandInt32(t *testing.T) { for i := 0; i < 10; i++ { t.Logf("docGoRandInt32() = %v", docGoRandInt32(26)) }}基准测试用例 func Benchmark_docGoRandInt32(b *testing.B) { for i := 0; i < b.N; i++ { docGoRandInt32(26) }}基于bench进行测试,如下为测试性能后果 D:\project\go\src\gitee.com\dn-jinmin\gen-id\utils>go test -bench=docGoRandInt32 -benchmemgoos: windowsgoarch: amd64pkg: gitee.com/dn-jinmin/gen-id/utilscpu: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHzBenchmark_docGoRandInt32-8 122416 8281 ns/op 0 B/op 0 allocs/opPASSok gitee.com/dn-jinmin/gen-id/utils 1.523s依据测试结果显示对docGoRandInt32函数进行基准测试,每次调用docGoRandInt32函数耗费8281ns,基于122416次调用的平均值,每次操作的上没有内存调配; ...

March 6, 2022 · 5 min · jiezi

关于golang:学习笔记带你十天轻松搞定-Go-微服务系列一

1、学习课程带你十天轻松搞定 Go 微服务系列(一) 2、集体环境Ubuntu 20.04.4docker-compose version 1.21.2, build a133471 3、步骤3.1 装置Docker Composeapt install docker-compose3.2 创立目录 mkdir 与 touch 命令创立如下目录: gonivinck├── dtm # DTM 分布式事务管理器│ ├── config.yml # DTM 配置文件│ └── Dockerfile├── etcd # Etcd 服务注册发现│ └── Dockerfile├── golang # Golang 运行环境│ └── Dockerfile├── grafana # Grafana 可视化数据监控│ └── Dockerfile├── jaeger # Jaeger 链路追踪│ └── Dockerfile├── mysql # Mysql 服务│ └── Dockerfile├── mysql-manage # Mysql 可视化治理│ └── Dockerfile├── prometheus # Prometheus 服务监控│ ├── Dockerfile│ └── prometheus.yml # Prometheus 配置文件├── redis # Redis 服务│ └── Dockerfile├── redis-manage # Redis 可视化治理│ └── Dockerfile├── .env # env 配置└── docker-compose.ymlmkdir新建文件夹,touch新建文件 ...

March 5, 2022 · 4 min · jiezi

关于golang:gocontainerregistry-实战篇之容器镜像下载

go-containerregistry 实战篇之容器镜像下载一、库介绍go-containerregistry 是 google 公司开源的用于解决容器镜像的golang客户端库,它提供了一个对镜像的操作接口,这个接口背地的资源能够是 镜像仓库的近程资源,镜像的tar包,甚至是 docker daemon 过程。 它次要基于同名的python我的项目 上面咱们就简略介绍下如何应用这个我的项目来实现咱们的指标—— 在代码中解析镜像。 库提供了crane和近程近程镜像进行交互。 二、crane初体验2、1 crane 装置和应用Crane 是一个与近程镜像和仓库交互的工具。 1)装置Crane go install github.com/google/go-containerregistry/cmd/crane@latesthttps://github.com/google/go-... 在go-containerregistry的crane的文档目录中,有crane的具体文档。 2)crane命令 crane append - 将 tarball 的内容附加到近程镜像crane auth - 登录或拜访凭证crane blob - 从仓库中读取blobcrane catalog - 枚举仓库中的reposcrane config - 获取镜像的配置crane copy - 在保留摘要值的同时,无效地将近程镜像从 src 复制到 dstcrane delete - 从registry仓库中删除镜像的援用crane digest - 获取图像的摘要crane export - 将近程镜像的内容导出为 tarballcrane flatten - 将镜像的多层合并为单个层crane ls - 列出 repo 中的标签crane manifest - 获取镜像的manifestcrane mutate - 批改镜像标签和正文,需将容器推送到仓库并更新manifest。crane pull - 通过援用拉取近程镜像,并将其内容存储在本地。crane push - 将本地镜像内容推送到近程仓库crane rebase - 将镜像重定位到新的根底镜像上crane tag - 无效地标记近程镜像crane validate - 验证image镜像格局是否正确crane version - 打印版本对于容器镜像下载性能来说,就是执行crane pull <镜像全名>这个命令 ...

March 5, 2022 · 2 min · jiezi

关于golang:Go进阶并发编程Context

Context 是 Go 利用开发罕用的并发控制技术,它与 WaitGroup 最大的不同点是 Context 对于派生 goroutine 有更强的控制力,它能够管制多级的 goroutine。 只管有很多的争议,然而在很多场景下应用 Context 都很不便,所以当初它曾经在 Go 生态圈中流传开来了,包含很多的 Web 利用框架,都切换成了规范库的 Context。规范库中的 database/sql、os/exec、net、net/http 等包中都应用到了 Context。而且,如果遇到了上面的一些场景,也能够思考应用 Context: 上下文信息传递 ,比方解决 http 申请、在申请解决链路上传递信息;管制子 goroutine 的运行;超时管制的办法调用;能够勾销的办法调用。实现原理接口定义包 context 定义了 Context 接口,Context 的具体实现包含 4 个办法,别离是 Deadline、Done、Err 和 Value,如下所示: type Context interface { Deadline() (deadline time.Time, ok bool) Done() <-chan struct{} Err() error Value(key interface{}) interface{}}Deadline 办法会返回这个 Context 被勾销的截止日期。如果没有设置截止日期,ok 的值是 false。后续每次调用这个对象的 Deadline 办法时,都会返回和第一次调用雷同的后果。 Done 办法返回一个 Channel 对象,基本上都会在 select 语句中应用。在 Context 被勾销时,此 Channel 会被 close,如果没被勾销,可能会返回 nil。当 Done 被 close 的时候,能够通过 ctx.Err 获取错误信息。Done 这个办法名其实起得并不好,因为名字太过抽象,不能明确反映 Done 被 close 的起因。 ...

March 5, 2022 · 4 min · jiezi

关于golang:Leetcode专题二叉树十连杀二叉树的层序遍历

力扣链接:102:https://leetcode-cn.com/probl...107:https://leetcode-cn.com/probl...199:https://leetcode-cn.com/probl...637:https://leetcode-cn.com/probl...429:https://leetcode-cn.com/probl...515:https://leetcode-cn.com/probl...116:https://leetcode-cn.com/probl...117:https://leetcode-cn.com/probl...104:https://leetcode-cn.com/probl...111:https://leetcode-cn.com/probl...解题思路:以上这些题目的解题思路,都是能够用二叉树的层序遍历,层序遍历是有模版的,上面总结下:(0)头节点判空,避免二叉树为空(1)首先借助队列来实现,初始化一个队列,将头节点放入队列,同时新建一个长期数组搁置每一层的节点数据(2)开启循环,直到队列为空(3)求出以后层队列的大小,挨个出队列,放入长期数组。同时将下一层的左右节点退出队列(4)将长期队列赋值给后果队列,同时将长期队列置空(5)返回后果

March 5, 2022 · 1 min · jiezi

关于golang:Golangmap

map 1.概念:Go语言中map是一种非凡的数据结构,一种元素对(pair)的无序汇合,蕴含一个key和value值,被称为关联数组或字典。2.初始化3.判空4.遍历:个别遍历与条件遍历5.删除6.查 若在map中找不到某个key,则返回key对应类型的零值,e.g. int对应0,string对应空,bool7.元素类型为map的slice8.元素类型为slice的map 练习题: 统计how do you do中每个单词呈现的次数 package mainimport ( "fmt")func main() { //初始化 var a = make(map[string]int) a["勇者的等级"] = 10 //赋值 a["勇者的HP"] = 107 a["勇者的MP"] = 55 a["勇者的攻击力"] = 99 a["勇者的防御力"] = 99 fmt.Println(a) //判空 //常设变量ok来判空 v, ok := a["勇者的颜值"] if !ok { fmt.Println("无此属性") } else { fmt.Println(v) } fmt.Println(a["勇者的颜值"]) //查无此key,则返回值为int的零值 //遍历 //1.个别遍历 for range for v, k := range a { fmt.Println(v, k) } //2.条件遍历 //步骤:将key存入切片,用sort对该切片进行排序,再存入map,最初遍历 //删除 fmt.Println(a) delete(a, "勇者的防御力") fmt.Println(a) //元素类型为map的slice A := make([]map[string]int, 4, 4) fmt.Println(A) A[0] = a fmt.Println(A) //元素类型为slice的map B := make(map[string][]string, 2) fmt.Println(B) B["援救公主的壮士"] = []string{"莱安", "杜鲁特"} fmt.Println(B) //vs code下如果不对外部的slice或map进行初始化,则会报错 //练习题对"to be or not to be"的每个单词呈现的次数进行统计 C := make(map[string]string) C["单词1"] = "to" C["单词2"] = "be" C["单词3"] = "or" C["单词4"] = "not" C["单词5"] = "to" C["单词6"] = "be" count1 := 0 count2 := 0 count3 := 0 count4 := 0 for _, k := range C { if k == "to" { count1++ } else if k == "be" { count2++ } else if k == "or" { count3++ } else if k == "not" { count4++ } } fmt.Println(C) fmt.Println("to:", count1) fmt.Println("be:", count2) fmt.Println("or:", count3) fmt.Println("not:", count4)}运行后果: ...

March 5, 2022 · 2 min · jiezi