天道酬勤,学无止境

golang

golang 限流控制

限流日常开发中,一般会遇到几种场景需要限流,比如有个api-server, 需要限制单个用户的调用频率,避免用户恶意刷接口或者突发大流量导致服务不可用等,这边记录几个常用的限流方法。并发控制简单的并发控制,用户的所有请求丢到一个channel里,再指定一个带缓冲区的channel为并发池,缓冲池的长度就是可以同时存在的协程数量,然后将执行完的任务根据需要直接返回或者丢到另外一个channel 里, 这样做的问题是如果任务太多,后面的任务会慢慢等待(因为channel阻塞机制),用户体验不是太好。Code:package main import ( "fmt" "sync" ) func setJob() <-chan int { var wg sync.WaitGroup jobChan := make(chan int, 50) wg.Add(1) go func(){ for i := 0; i < 50; i++ { jobChan <- i } close(jobChan) wg.Done() }() wg.Wait() return jobChan } func main() { var wg sync.WaitGroup // 创建一个需要处理的数据来源, 假设是个channel jobChan := setJob() // 将结果存入一个channel resChan

2021-06-02 12:21:15    分类:博客    golang

golang 常见面试基础(2)

map的原理字典[map]:初始化: var amap map[string]string, 如果需要赋值,需要先make 一下 testMap := make(map[string]string) Go中的字典是引用类型,但Golang中是没有引用传递的,均为值传递。这意味着传递的是数据的拷贝,所以map 也存在线程安全的问题 底层结构是hmap,hmap 的结构体里有一个buckets,他是一个指针,指向了一个bucket的结构体,bucket可以看错一个链表,bucket 里存放着k&&v 的数组,以及指向下一个bucket的指针。所以当hmap收到了key,会进行hash运算,然后基于运算结果找到对应的bucket里的数组,然后找到对应的Keymake和new的区别new:用来初始化一个对象,并且返回该对象的首地址.其自身是一个指针.可用于初始化任何类型make:返回一个初始化的实例,返回的是一个实例,而不是指针,其只能用来初始化:slice,map和channel三种类型go的GC 机制标记-清除模式: 从根变量开始遍历所有引用的对象,引用的对象标记为"被引用",没有被标记的进行回收。defer的执行顺序 多个defer 执行顺序类似堆栈,后进先出,defer、return、返回值三者的执行逻辑应该是:return最先执行,return负责将结果写入返回值中

2021-06-02 12:20:25    分类:博客    golang

golang 常见面试基础(1)

Big Picture年底了,面试/被面试的需求比较多,正好有需要让我整理一份面试题,干脆写一份,权当对自己的复习/整理了go语言切片和数组区别,go切片的原理:数组[array]:初始化后长度是固定的,无法修改其长度 初始化: array := [5]int{1,2,3,4,5}/ array := […]int{1,2,3,4,5} Go中的数组是值类型切片[slices]: s :=[]int{1,2,3} / s := make([]int,len,cap)长度可变的"数组",可以追加元素,一是len长度,二是cap容量,长度是指已经被赋过值的最大下标+1,可通过内置函数len()获得 初始化: 切片是引用类型, 数据结构其实如下:type SliceHeader struct { Data uintptr Len int Cap int }其中,Data是uintptr, 就是个指针类型,表示Data指向的一块连续的内存空间,所以切片可以理解为一片连续的内存空间加上长度与容量标识,扩容后,如果切片的容量小于1024个元素,那么扩容的时候slice的cap就翻番,乘以2;一旦元素个数超过1024个元素,增长因子就变成1.25,即每次增加原来容量的四分之一,如果扩容之后,还没有触及原数组的容量,那么,切片中的指针指向的位置,就还是原数组,如果扩容之后,超过了原数组的容量,那么

2021-06-02 12:20:09    分类:博客    golang

golang外部包与自定义包的导入问题

习惯使用Java开发的朋友,在切换到go语言上总会有些不适应。不管使用何种语言开发,包这个概念都会存在,即便没有包,也总有文件夹吧。如果没有包管理代码,所有代码文件都放在一个目录下,一个小的项目上百个代码文件,一个大项目几千个代码文件,如何快速的找到某个功能在哪个文件是件非常头疼的问题。在web项目开发中,通常我们会按mvc分层,每个层一个包名,除此之外,如果文件多的情况下,我们可能还会按业务分包。使用Go语言开发,导入开源的包非常简单,无需编写依赖配置文件,只需要一条go get xxx命令将依赖的包下载下来,在代码中使用import导入即可使用,非常简单。但如果依赖的包太多,首次下载项目需要一个个包去执行go get命令也是很蛋疼的,不过依然有各种插件可解决这些问题。对于初学Go,特别是Java转Go的朋友来说,可能遇到最多的问题就是,在一个项目内,定义的包,如何在其它地方导入使用。这通常是由于没有理解Go的环境变量配置所导致的。以mac系统为例,go的环境变量配置如下,配置文件~/.bash_profile#GOROOT,用pkg安装无需配置export GOROOT=/usr/local/go#GOPATHexport GOPATH="/Users/wjy/go:/Users/wjy/MyProjects/golang_projects"# GOBIN#export

2021-06-02 08:42:43    分类:博客    golang   编程开发

在windows系统下打包linux平台运行的go程序

一、用windows的cmd//cd到main.go目录下set GOARCH=amd64 //设置目标可执行程序操作系统构架,包括 386,amd64,armset GOOS=linux //设置可执行程序运行操作系统,支持 darwin,freebsd,linux,windowsgo build //打包 二、linux(centos7)设置chmod +x 应用 //1、这种方法仅用来调试测试,不是守护进程,关闭终端就会退出./应用//2、守护进程启动,启动的进程会在新的session中,后台运行setsid ./应用来源:https://blog.51cto.com/u_332532/2585825

2021-06-02 01:24:57    分类:博客    go程序打包   golang

【原创】golang快速入门[9.3]-精深奥妙的切片功夫

前言下面这段程序会输出什么?package mainimport "fmt"func f(s []string, level int) { if level > 5 { return } s = append(s, fmt.Sprint(level)) f(s, level+1) fmt.Println("level:", level, "slice:", s)}func main() { f(nil, 0)}其输出为:level: 5 slice: [0 1 2 3 4 5]level: 4 slice: [0 1 2 3 4]level: 3 slice: [0 1 2 3]level: 2 slice: [0 1 2]level: 1 slice: [0 1]level: 0 slice: [0]如果对输出结果有一些疑惑,你需要了解这篇文章的内容如果你知道了结果,你仍然需要了解这篇文章的内容,因为本文完整介绍了切片的典型用法切片的陷阱切片的逃逸分析切片的扩容切片在编译与运行时的研究如果你啥都知道了,请直接滑动最下方,双击666.切片基本操作切片是某种程度上和其他语言(例如C语言)中的数组在使用中有许多相似之处,但是go语言中的切片有许多独特之处Slice(切片)代表变长的序列,序列中每个元素都有相同的类型。一个slice类型一般写作[]T,其中T代表slice中元素的类型

2021-06-02 01:12:38    分类:博客    go   golang   切片

【原创】golang快速入门[9.3]-精深奥妙的切片功夫

前言下面这段程序会输出什么?package mainimport "fmt"func f(s []string, level int) { if level > 5 { return } s = append(s, fmt.Sprint(level)) f(s, level+1) fmt.Println("level:", level, "slice:", s)}func main() { f(nil, 0)}其输出为:level: 5 slice: [0 1 2 3 4 5]level: 4 slice: [0 1 2 3 4]level: 3 slice: [0 1 2 3]level: 2 slice: [0 1 2]level: 1 slice: [0 1]level: 0 slice: [0]如果对输出结果有一些疑惑,你需要了解这篇文章的内容如果你知道了结果,你仍然需要了解这篇文章的内容,因为本文完整介绍了切片的典型用法切片的陷阱切片的逃逸分析切片的扩容切片在编译与运行时的研究如果你啥都知道了,请直接滑动最下方,双击666.切片基本操作切片是某种程度上和其他语言(例如C语言)中的数组在使用中有许多相似之处,但是go语言中的切片有许多独特之处Slice(切片)代表变长的序列,序列中每个元素都有相同的类型。一个slice类型一般写作[]T,其中T代表slice中元素的类型

2021-06-02 01:12:31    分类:博客    go   golang   切片

golang快速入门[9.2]-深入数组用法、陷阱与编译时

前文golang快速入门[1]-go语言导论golang快速入门[2.1]-go语言开发环境配置-windowsgolang快速入门[2.2]-go语言开发环境配置-macOSgolang快速入门[2.3]-go语言开发环境配置-linuxgolang快速入门[3]-go语言helloworldgolang快速入门[4]-go语言如何编译为机器码golang快速入门[5.1]-go语言是如何运行的-链接器golang快速入门[5.2]-go语言是如何运行的-内存概述golang快速入门[5.3]-go语言是如何运行的-内存分配golang快速入门[6.1]-集成开发环境-goland详解golang快速入门[6.2]-集成开发环境-emacs详解golang快速入门[7.1]-项目与依赖管理-gopathgolang快速入门[7.2]-北冥神功—go module绝技golang快速入门[8.1]-变量类型、声明赋值、作用域声明周期与变量内存分配golang快速入门[8.2]-自动类型推断的秘密golang快速入门[8.3]-深入理解浮点数golang快速入门[8.4]-常量与隐式类型转换golang快速入门[9.1]-深入字符串的存储、编译与运行前言在本节我们将介绍go语言中重要的数据类型——数组数组是一个重要的数据类型,通常会与go语言另一个重要的结构:切片作对比

2021-06-02 01:11:36    分类:博客    go   golang   编译时

golang中 boltdb的学习和实践

golang boltdb的学习和实践1. 安装go get github.com/boltdb/bolt2.创建和启动数据库db, err := bolt.Open("my.db", 0600, nil)其中open的第一个参数为路径,如果数据库不存在则会创建名为my.db的数据库, 第二个为文件操作,第三个参数是可选参数, 内部可以配置只读和超时时间等,特别需要注意的地方就是因为boltdb是文件操作类型的数据库,所以只能单点写入和读取,如果多个同时操作的话后者会被挂起直到前者关闭操作为止, boltdb一次只允许一个读写事务,但一次允许多个只读事务。所以数据具有较强的一致性。因此单个事务和从它们创建的所有对象(例如桶、键)都不是线程安全的。与数据在多个概念你必须为每一个或使用锁机制来保证只有一个goroutine里操作改变数据。只读事务和读写事物通常不应该在同一个goroutine里同时打开。由于读写事务需要周期性地重新映射数据文件,这可能导致死锁。3.读写事务boltdb的读写事务操作我们可以使用DB.Update()来完成形如:err := db.Update(func(tx *bolt.Tx) error { ... return nil })在闭包fun中,在结束时返回nil来提交事务。您还可以通过返回一个错误在任何点回滚事务。所有数据库操作都允许在读写事务中进行

2021-06-02 00:45:25    分类:博客    golang   boltedb   区块链   区块链的知识和手动实现

Go语言个人学习笔记(Pythonista)

go是个什么语言? 引自知乎 go是面向过程的语言, go的代码不讲究封装和整理,很多源码都是几千行代码呆在单个文件里面,表现出了典型的过程式语言的基本特征. c也是过程式的,go的语言特性跟c语言很相似,只是增加了gc,goroitine等常用工具而已,作者本身就对oop,fp等缺乏了解,只是根据c的经验,整理出了一些常用的工具,然后将其放到语言的runtime中去罢了. 另外go官网对于是否面询对象编程语言,他们自己说是:Yes and No。明显go是允许OO的编程风格的,但又缺乏一些常见类型继承结构和类对象。Go自己觉得这一套挺好的,更加的容易使用且通用性更强。很多时候我们用OO的思想来组织我们的项目,但需要注意的是继承关系是一种非常强的耦合,有时候会给以后的升级带来麻烦。大型项目中可能是非常有帮助的,当然小型的项目可能好处不是很明显。 接下来正式学习Go语言 包 包的引入 和其他语言的单个文件就是一个包的组织方式不同,go的package不局限于一个文件,多个文件可以声明同一个名称的包,互相间可以直接调用,不用import,同一个package内全局变量和函数等不能同名。 go不要求package的名称和所在目录名相同,但建议最好保持相同。引入包的时候,go会使用子目录名作为包的路径,例如:import “root_dir/sub_dir/package”,

2021-05-19 03:48:23    分类:博客    golang   python