![](https://img-blog.csdnimg.cn/20201014180756926.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
go
sdccone1
这个作者很懒,什么都没留下…
展开
-
集成gin 、zap和lumberjack
/** * @author:David Ma * @date:2021-02-01 */package mylogimport ( "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" "os")/** * 获取日志对象 * filePath 日志文件路径 * level 日志级别 * maxSize 每个日志文件保存的最大尺寸 单位:M * maxBackups 日原创 2021-02-01 16:29:34 · 832 阅读 · 1 评论 -
Go的context库(包)
一、问题的提出:在 Go http包的Server中,也就是在go的http服务器中,对每一个请求request都会有一个对应的 goroutine 去处理该请求,而且对应的请求处理函数在处理该请求时有可能又会启动新的的 goroutine 用来访问一些后端服务:比如数据库和RPC服务。而且用来处理同一个请求request的 各goroutine间 通常都需要访问与该request相关的数据,比如终端用户的身份认证信息、验证相关的token、请求的截止时间,那么如何方便的在这些goroutine间(也就原创 2021-01-08 17:21:00 · 282 阅读 · 2 评论 -
JSON对象与JSON串
一、Json对象最显著的特征:对象的值可以用 对象.属性的方式进行访问;例子如下:var person={"name":"shily","sex":"女","age":"23"}//json对象console.log(person);console.log(person.name);console.log(typeof person);输出结果是:二、Json字符串:本质 是一个JSON格式的字符串!!!【注意】JSON串不能像JSON对象那样通过对象.属性的方式访问某个值例子如原创 2021-01-06 15:38:06 · 311 阅读 · 0 评论 -
Gin与mysql进行日期交互
使用mysql的时间字段遇到如下两个问题使用go-sql-driver来连接mysql数据库,获取的时区默认是UTC +0的,与本地的东八区是有区别,在业务处理中会出现问题获取mysql中的日期,是string类型,需要在代码中用time.Parse进行转化解决方案:在连接的dsn中,添加parseTime=true 和loc=Local,此处的local可以换为具体的时区(Asia/Shanghai)func GetMySqlPoll() *sql.DB{ if db != nil{原创 2021-01-05 15:51:40 · 757 阅读 · 2 评论 -
Go之nil
nil是go语言中预先的标识符nil仅可以代表指针、通道(channel)、函数(function)、接口(interface)、映射(map)或切片(slice)的默认零值原创 2021-01-05 12:33:52 · 484 阅读 · 0 评论 -
go的互斥锁Mutex以及条件变量Condition
锁go中的锁分为两类:互斥锁Sync.Mutex:特别的如果要实现对象锁的话,可以在定义该对象的结构体时封装一个互斥锁成员,比如type struct Resource{ resource int lock sync.mutex}读写锁 sync.RWMutex:读-写、写-读 以及写-写操作互斥,但读-读操作可以并发执行,操作如下:func (*RWMutex) Lock() // 写锁func (*RWMutex) Unlock() // 解写锁原创 2020-12-21 16:45:14 · 675 阅读 · 0 评论 -
channel 及 select模型
channelchannel的本质是一个线程安全的队列(可以存储interface{}类型的变量),遵循先进先出规则(FIFO),内部实现了同步,确保了并发安全!,可以解决协程之间的通信问题channel有两种:无缓冲channel(初始容量为0),和有缓冲channel(初始容量不为0)无缓冲channel:无缓冲通道的收发操作必须在不同的两个goroutine间进行,因为通道的数据在没有接收方处理时(没读时),数据发送方会持续阻塞(写的一方被阻塞,反之亦然),所以通道的接收必定在另外一原创 2020-12-19 16:38:40 · 814 阅读 · 1 评论 -
GO的协程调度模型
一、线程模型1、用户级线程模型此时,用户态的线程和KSE(可以认为是内核线程)是M:1的关系,这m个用户级线程“共享”(对应)同一个内核线程,所以这m个用户级线程必须要互斥使用这1个内核线程,所以需要用户自己来管理调度这m个用户线程2、内核级线程模型此时用户线程和内核线程是1:1的关系,此时用户线程间的调度均可以交由内核来管理两级线程模型用户线程和内核线程是m:n也就是多对多的关系,一个用户线程可以对应多个内核线程,1个内核线程也可以对应多个用户线程。此时用户线程需由用户自己来管理,内核线程原创 2020-12-16 15:52:04 · 719 阅读 · 0 评论 -
GO的方法
在go中方法是那些与对象实例相绑定的函数,实现绑定的方式是定义方法的接收参数receiver,格式为func(receiver) funName (args) returnValue{...}接收参数receiver既可以是基础类型比如demo.User也可以是指针类型*demo.User,区别在于当调用该方法时绑定的对象实例是否会被整体复制,也就是当绑定的是基础类型时,会完整复制整个绑定对象实例,如果是指针类型,则只需复制绑定的对象实例的地址即可如何确定方法的接收参数receiver的类型:当该方.原创 2020-12-07 21:27:56 · 127 阅读 · 0 评论 -
Go的反射
Go的反射是通过接口的类型信息实现的,即反射建立在接口类型的基础上:当向接口变量赋予一个实体类型的时候,接口会存储实体的类型信息。接口类型变量(可以认为Go中的任意变量均,因为Go中所有变量都隐含实现了空接口)都有一个对应的pair,pair中记录了变量的实际值和类型(value, type)。即一个接口类型变量包含2个指针,一个指向对应的 concrete type (由pair中的type指向),另一个指向实际的值 value。(所以 nil != nil ),规定只有interface类型才有反射(原创 2020-12-04 16:46:39 · 389 阅读 · 0 评论 -
Go的异常体系-panic和recover机制
Panic和RecoverGo没有像Java那样的异常机制,它不能抛出异常,而是使用了panic和recover机制。一定要记住,你应当把它作为最后的手段来使用,也就是说,你的代码中应当没有,或者很少有panic的东西。这是个强大的工具,请明智地使用它。那么,我们应该如何使用它呢?Panic是一个内建函数,可以中断原有的控制流程,进入一个panic状态中。当函数F调用panic,函数F的执行被中断,但是F中的延迟函数会正常执行,然后F返回到调用它的地方。在调用的地方,F的行为就像调用了panic。这一原创 2020-12-03 17:35:06 · 260 阅读 · 0 评论 -
Defer
Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句。当函数执行到最后时但还没有返回时,这些defer语句会按照逆序执行,最后才轮到该函数执行返回操作。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题。如下代码所示,我们一般写打开一个资源是这样操作的:func ReadWrite() bool { file.Open("file")// 做一些工作 if failureX { file.Cl原创 2020-12-03 17:32:52 · 78 阅读 · 0 评论 -
断言及多态
断言package mainimport "fmt"// 定义一个通用接口:动物接口type Animal interface { Breath() // 动物都具备 呼吸方法}type Flyer interface { Fly()}type Swimer interface { Swim()}// 定义一个鸟类:其呼吸的方式是在陆地type Bird struct { Name string Food string Kind string}func (b原创 2020-12-03 16:32:14 · 93 阅读 · 2 评论 -
Go的interface
Go中的interface也是类型type,定义了方法规范,其内只有方法的声明没有实现,定义格式为:type interface_Name interface{ f1()....}需要注意的一点是go中的interface是非侵入式的,也就是不需要利用某个关键字(比如Java中的implements)显示的声明某个类型是否实现了某个interface,只需要某个类型的对象的某个方法是某个接口的方法的实现(go中不允许方法的重载),就表明该对象实现了该接口,其也是该接口的一个实例go中的接口不要求其内的.原创 2020-12-03 15:46:32 · 387 阅读 · 5 评论 -
go中实现继承(结构体组合和嵌套)
可以借助结构体嵌套来实现,一个子类结构体中去嵌套若干个匿名结构体,可以实现类似多重继承的效果,因为当嵌套匿名结构体时,外围结构体可以直接访问该匿名结构体的所有能被访问到的成员!!!当结构体和匿名结构体有相同的字段或者方法时,编译器采用就近访问原则访问,如果希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分。结构体嵌入多个匿名结构体,如果两个匿名结构体有相同的字段和方法(同时结构体本身没有同名的字段和方法),访问时必须明确指定匿名结构体名字,否则编译报错。如果一个 struct 嵌套了一个有名.原创 2020-12-03 11:58:11 · 1404 阅读 · 0 评论 -
init()
Go语言中,除了可以在全局声明中初始化实体,也可以在init函数中初始化。init函数是一个特殊的函数,它会在包完成初始化后自动执行,执行优先级高于main函数,并且不能手动调用init函数,每一个文件有且仅有一个init函数,初始化过程会根据包的依赖关系单线程顺序执行。package mainimport ( "fmt")func init() { //在这里可以书写一些初始化操作 fmt.Println("init...")}func main() { fmt.Println(".原创 2020-12-03 11:34:51 · 3452 阅读 · 0 评论 -
Go中将函数当做参数进行方法传参
package demoimport "math"/*@Author:David Ma@Content:将函数当做参数进行方法传参@Date:2020-12-03 10:46*/// step1 :先定义一个对应的函数类型,方便将函数作为一种类型进行传参type MyFunctionType func(int) bool// step2:定义测试函数 IsOdd(int)func IsOdd(num int) bool { if num % 2 == 0{ return f原创 2020-12-03 11:26:55 · 881 阅读 · 0 评论 -
Go面向对象编程OOP的实现
在go 中 在函数名前加上一个声明(Type *Type)表明该方法是属于哪个对象(Type),以此来实现OOP,且特别注意,在go中因为没有继承的概念,所以只能使用组合这种方式来实现代码复用func (Type *Type) func_Name(args) (return list){}package demo/*@Author:David Ma@Content:go中的面向对象编程(oop)的实现,以及类型别名和组合在使用时的区别@Date:202-12-01 15:41*/im..原创 2020-12-01 15:50:46 · 308 阅读 · 0 评论 -
Go中的string及相关操作
package mainimport ( "bytes" "fmt")func main() { s1 := "hello" s2 := "world" // 借助字节缓冲区byteBuffer来实现类似Java中StringBuilder的效果,因为在go中string底层是由byte数组实现的 // byte即为uint8类型,所以用byte来存储字符时保存的是其ascii码,同理string底层的byte数组实际上也是存储的该string的每个字符对应的ascii码 Strin原创 2020-11-30 21:21:51 · 1356 阅读 · 0 评论 -
Go之struct
一个命名为S的结构体类型将不能再包含S类型的成员:因为一个聚合的值不能包含它自身(但不同类型的聚合值可以相互嵌套!!!)。(该限制同样适应于数组。)但是S类型的结构体可以包含*S指针类型的成员,这可以让我们创建递归的数据结构,比如链表和树结构等...原创 2020-11-30 15:54:02 · 148 阅读 · 0 评论 -
Go中的make()和 new()的区别以及Go中的引用类型
make和new都是golang用来分配内存的內建函数,且在堆上分配内存,make 即分配内存,也初始化内存。new只是将内存清零,并没有初始化内存。make返回的还是引用类型本身;而new返回的是指向类型的指针。make只能用来分配及初始化类型为slice,map,channel的数据;new可以分配任意类型的数据。...原创 2020-11-30 15:31:33 · 475 阅读 · 0 评论 -
Go中方法传参的注意点
在Go语言中,所有的函数参数都是以值拷贝的方式传入的,函数的参数将不再是函数调用时的原始变量,而是一个拷贝后的变量,所以如果要在函数内部修改结构体成员的话,用指针传入是必须的!!!func AwardAnnualRaise(e *Employee) { e.Salary = e.Salary * 105 / 100}...原创 2020-11-30 15:20:33 · 532 阅读 · 0 评论 -
slices
1、slices的数据结构slice的底层确实引用一个数组对象。一个slice由三个部分构成:指针、长度和容量。指针指向第一个slice元素对应的底层数组元素的地址,长度对应slice中元素的数目;长度不能超过容量,容量一般是从slice的开始位置到底层数据的结尾位置。内置的len和cap函数分别返回slice的长度和容量。多个slice之间可以共享底层的数据,并且引用的数组部分区间可能重叠其他任何对slices所做的操作最终都会反馈到它的底层数组上,因为slice值包含指向第一个slice元原创 2020-11-27 13:56:57 · 797 阅读 · 0 评论 -
匿名函数、函数变量、闭包
package mainimport "fmt"import "./demo"/**@author:David Ma@Content:如何在func1中定义实现一个仅能在func1的作用域内被访问的私有func@Date:2020-11-18 21:07*/func saySomething2(prefix, name string){ fmt.Println(prefix + " " + name)}func main() { //效果上等价于func saySomething原创 2020-11-18 21:07:42 · 153 阅读 · 0 评论 -
go的模块化调用(怎么调用另一个.go文件中的func)
实现方式:1、先把.go文件放在相应的package下2、然后手动import所需要的模块所在的package3、最后,在调用相应的方法时通过 package_Name.func_Name()的形式来完成调用(这里注意,能被其他模块调用的函数其Name的首字符一定要大写!!)package demo/**@author:David Ma@Content:test for fmt package@Date:2020-11-18 19:33*/func Hello() string { /原创 2020-11-18 20:13:43 · 12193 阅读 · 1 评论