
go
文章平均质量分 78
ball球
这个作者很懒,什么都没留下…
展开
-
聊聊go语言逃逸分析
1. 从一个例子开始下面是一段c代码,函数getStr生成了a-z的串,我们分别在函数内部和main中对字串进行了输出。//例1.1#include <stdio.h>//返回字串char* getStr(){ //char数组 函数栈上分配内存 char buf[27]; int i; //产生a-z的串 for (i=0; i<sizeof(buf)-1; i++){ buf[i] = i + 'a';原创 2021-10-13 19:06:33 · 611 阅读 · 2 评论 -
go语言select语句中的求值问题
1. 从一个问题说起package mainimport ( "fmt")var ch0 = make(chan int)var ch1 = make(chan int)var chs = [](chan int){ch0, ch1}func getCh(i int) chan int{ fmt.Printf("get ch:%d\n", i) return chs[i]}func getNum(i int) int{ fmt.Printf("get num:%d\n",原创 2021-09-14 16:37:05 · 573 阅读 · 0 评论 -
db2gorm -- 将mysql数据表转为gorm struct
0. 为什么写这样一个工具找到的开源工具功能比较多,用起来也复杂些自己定制的更适合自己的项目学习go时间不长,写一款工具也是练习的过程项目地址https://github.com/qmhball/db2gorm1. 功能根据数据库表生成gorm需要的struct。支持指定单表生成,也可以全库生成。比如有如下数据表:Table: UserCreate Table: CREATE TABLE `User` ( `id` int(10) unsigned NOT NULL AUTO_I原创 2021-06-01 11:17:43 · 2242 阅读 · 8 评论 -
gorm hook使用中的问题及核心源码解读
本文针对的是gorm V2版本。hook官方文档可以点击这里,本文旨在对官方文档作一些补充说明。下文中所有的DB均指gorm.Open返回的DB对象。DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})1. hook作用的对象hook只能定义在model上,不能定义在gorm.DB上。假设我们有User表,对应model如下,则可以定义BeforeCreate hook,用于插入数据前的检查。type User struct { I原创 2021-05-24 10:32:09 · 2919 阅读 · 2 评论 -
使用logrus记录gorm sql
gorm可以方便的输出执行的sql或慢查询。logrus是常用的日志组件,如何将gorm输出的sql通过logrus记录到日志中呢?1. 代码实现我们先看代码。思路:使用logrus,实现gorm/logger.Writer接口var DB *gorm.DB//定义自己的Writertype MyWriter struct { mlog *logrus.Logger}//实现gorm/logger.Writer接口 func (m *MyWriter)Printf(format st原创 2021-05-17 10:03:03 · 1706 阅读 · 6 评论 -
如何让gorm输出执行的sql
1. 打印所有sql在打开连接时设置日志级别为InfoDB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{ Logger:logger.Default.LogMode(logger.Info),})2. 打印单条sql在操作前加Debug(), 相当于将临时将日志级别改为InfoDB.Debug().Where("ID = ?", 52).First(&newData)//输出//[0.773ms] [rows:1] SE原创 2021-05-14 16:34:07 · 13922 阅读 · 3 评论 -
logrus中输出文件名、行号及函数名
日志中输出文件名,行号及函数名是个比较有用的功能,那么在logrus中如何作到呢?1. 在处带Formatter中输出logrus有两个片带的Formatter,分别是:TextFormatter和JSONFormatter。要在这两个Formatter中输出文件名,行号和函数名,只需要设置logrus.SetReportCaller(true)1.1 在TextFormatter中输出func Demo(){ logrus.Info("i'm demo")}func main(){原创 2021-05-11 15:20:13 · 7886 阅读 · 2 评论 -
logrus自定义日志输出格式
1. 设置日志格式的方法logrus中,使用如下方法设置日志格式func SetFormatter(formatter Formatter) 其中Formatter是一个接口type Formatter interface { Format(*Entry) ([]byte, error)}所以,实现自定义日志格式,本质上就是实现Formatter接口,然后通过SetFormatter方式将其告知logrus。2. 已有Formatterlogrus包中自带两种Formatter,分别是原创 2021-05-11 14:23:36 · 6071 阅读 · 2 评论 -
go中类型的相等(==)及可比较规则
本文主要参考了The Go Programming Language Specification中的Comparison_operators。加入了自己的一些理解和示例。如果两个变量是可比较的(使用==或!=),那它们必可以相互赋值。这意味着可比较的两个变量必须是同一类型,或者他们的底层类型相同。1. 布尔类型可比较2. 整型可比较3. 浮点数可比较4. 复数可比较。5. 字串可比较6. 指针值可比较。两个指针指向同一个变量,则这两个指针相等,或者两个指针同为nil,它们也相等。原创 2021-02-09 15:21:09 · 2670 阅读 · 1 评论 -
《go in action》第5章(Go语言的类型系统)读书笔记
5.1 用户定义的类型不使用字段名创建结构类型的值,这咱形式下值的顺序很重要。type user struct { name string age int email string}lisa := user{"Lisa", 20, "lisa@email.com"}两种不同类型的值即便相互兼容,也不能互相赋值。编译器不会对不同类型的值做隐式转换。type Duration int64func main() { var dur Duration dur = int64(10原创 2021-02-07 17:01:49 · 209 阅读 · 0 评论 -
《go in action》第4章读书笔记
4.1 数组的内部实现和基础功能4.1.1 内部实现数组是一个长度固定的数据类型。4.1.2 声明和初始化一旦声明,数组里存储的数据类型的数组长度就都不能改变了。//声明一个包含5个元素的整型数组var array [5]int//声明一个包含5个元素的整型数组, 用初值初始化每个元素array := [5]int{10,20,30,40,50}在Go语言中声明变量时,总会使用对应类型的零值来对变量进行初始化。数组也不例外。如果使用…替代数组的长度,Go语言会根据初始化时数组元素的数原创 2021-02-03 14:22:22 · 150 阅读 · 0 评论 -
redis6.0 客户端缓存(Client side caching)及实践
1. 什么是客户端缓存(Client side caching)通常的缓存会放在应用和DB之间,比如redis。客户端缓存是指在应用服务内部再加一层缓存,也就是内存缓存,从而进一步提升访问速度。2. redis 6.0为此做了什么2.1 client cache的问题client cache的问题是缓存应该何时失效,更确切的说是如何保持与远端数据的一致性。为client cache设置过期时间是一个选择,但时间设置多久是一个问题。太长会有时效性问题,太短缓存的效果会打折扣。2.2 redis原创 2020-07-24 19:08:15 · 2379 阅读 · 0 评论 -
《Go语言入门经典》目录导航及思维导图
1. 目录导航第1章起步第2章理解类型第3章理解变量第4章使用函数第5章控制流程第6章数组、切片和映射第7章使用结构体和指针第8章创建方法和接口第9章使用字符串第10章处理错误第11章使用Goroutine第12章通道简介第13章使用包实现代码重用第14章Go语言命名约定第15章测试和性能第16章调试第17章使用命令行程序第18章创建HTTP服务器第19章创建HTTP客户端第20章处理JSON第21章处理文件第22章正则表达式简介第23章Go语言时间编程第24原创 2020-07-10 16:49:19 · 444 阅读 · 0 评论 -
go抽象的生产者消费者模型
这是一个单一生产者,多个消费者的模型。对之前的代码做了改进。目的:包装成包的形式。包的名子叫pc, producer/consumer的简写。使用者只需要写自己实际的生产逻辑和消费逻辑即可。1. 实现package pcimport ( "sync")type Task struct { Data string}type AbstructPC struct { ConsumerNum int ChanLen int Tasks chan Task原创 2020-07-09 18:23:26 · 311 阅读 · 0 评论 -
go实现生产者消费者模型
这是一个单一生产者,多消费者的模型。该模型主要实现了任务调度和同步。实际使用时需要修改的内容如下:type Task struct{} //自己实际需要的数据结构producer() //实际生产数据逻辑consumer() //实际处理逻辑main()中的consumerNum(消费者个数), channelLen(通道长度)也可根据实际需要修改代码如下:package mainimport ( "fmt" "sync")type Task struct { Dat原创 2020-07-08 18:45:10 · 803 阅读 · 2 评论 -
《Go语言入门经典》23章读书笔记
第23章 Go语言时间编程23.1 时间元素编程要使用Go语言打印计算机中的当前时间,可使用函数Now。import( "time")time.Now()23.2 让程序休眠time.Sleep(3 * time.Second)23.3 设置超时时间要在特定的时间过后执行某项操作,可使用函数After。package mainimport ( "fmt" "time")func main() { fmt.Println("You have 2 seconds原创 2020-07-07 16:08:10 · 243 阅读 · 0 评论 -
《Go语言入门经典》19~21章读书笔记
第19章创建HTTP客户端19.2 发出GET请求Go语言在net/http包中提供了一个快捷方法,可用于发出简单的GET请求。使用这个方法意味着不需要考虑如何配置HTTP客户端以及如何设置请求报头。如果只是要从远程网站获取一些数据,那么默认配置完全够用。package mainimport ( "net/http" "fmt" "io/ioutil" "log")func main(){ response, err := ht原创 2020-07-06 16:44:46 · 295 阅读 · 0 评论 -
《Go语言入门经典》16~18章读书笔记
第16章调试16.1 日志日志并非为报告Bug而提供的,而是可供在Bug发生时使用的基础设施。Go语言提供了log包,让应用程序能够将日志写入终端或文件。下面是一个简单的程序,它向终端输出一条日志消息。package mainimport ( "log")func main() { log.Printf("This is a log message");} 运行结果2020/06/30 19:26:59 This is a log message要将日志写入文件原创 2020-07-02 16:05:19 · 193 阅读 · 0 评论 -
《Go语言入门经典》13~15章读书笔记
第13章使用包实现代码重用13.1 导入包Go程序以package语句打头。main包是一种特殊的包,其特殊之处在于不能导入。对main包的唯一要求是,必须声明一个main函数,这个函数不接受任何参数且不返回任何值。简而言之,main包是程序的入口。在main包中,可使用import声明来导入其他包。导入包后,就可使用其中被导出的(即公有的)标识符。在Go语言中,标识符可以是变量、常量、类型、函数或方法。这让包能够通过接口提供各种功能。举一个函数导出的例子,strings包导出了函数ToLower,原创 2020-06-30 18:07:49 · 234 阅读 · 0 评论 -
《Go语言入门经典》10~12章读书笔记
第10章处理错误10.1 错误处理及Go语言的独特之处在Go语言中,一种约定是在调用可能出现问题的方法或函数时,返回一个类型为错误的值。这意味着如果出现问题,函数通常不会引发异常,而让调用者决定如何处理错误。package mainimport ( "fmt" "io/ioutil")func main() { file, err := ioutil.ReadFile("foo.txt"); if err != nil{ fmt.Printl原创 2020-06-24 11:49:41 · 218 阅读 · 0 评论 -
《Go语言入门经典》7~9章读书笔记
第7章 使用结构体和指针7.1 结构体是什么结构体是一系列具有指定数据类型的数据字段,它能够让您通过单个变量引用一系列相关的值。通过使用结构体,可在单个变量中存储众多类型不同的数据字段。通过使用结构体,可提高模块化程度,还能够让您创建并传递复杂的数据结构。package main原创 2020-06-22 17:28:02 · 226 阅读 · 0 评论 -
《Go语言入门经典》4~6章读书笔记
第4章 函数4.1 函数是什么4.1.2 返回单个值func isEven(i int) bool{ return i % 2 == 0;}4.1.3 返回多个值在Go语言中,可在函数签名中声明多个返回值,让函数返回多个结果。在这种情况下,终止语句可返回多个值。func getPrize()(int, string){ i := 2 s := "goldfish" return i,s}调用这个函数时,可直接将返回值赋给变量并使用它们。fun原创 2020-06-18 15:52:16 · 252 阅读 · 0 评论 -
《Go语言入门经典》1~3章读书笔记
第1章 起步1.4.1 使用go run编译并运行程序go run main.go在开发go代码时,go run提供了一种便利的方式编译并运行程序。第2章 理解类型go是一种静态类型语言2.2 区分静态类型和动态类型在go中,程序员可显式地声明类型,也可以让编译器推断类型。2.3 使用布尔类型可以像下面这样声明布尔类型var b bool如果没有给布尔变量赋值,它将默认为false。2.4 理解数据类型2.4.1 带符号整数和无符号整数在go语言中,声明整型的方式如下:va原创 2020-06-17 15:41:49 · 231 阅读 · 0 评论