Golang GORM使用
GORMSQLBuilderSQLBuilder是一个用于生成SQL语句的库。
项目地址:
https://gitee.com/iRainIoT/go-sqlbuilder、https://github.com/parkingwang/go-sqlbuilder
目前已支持MySQL基本Select/Update/Insert/Delete/Where 等语法
目前只支持MySQL语法
未支持多表查询
go get -u github.com/parkingwang/go-sqlbuilder
https://github.com/huandu/go-sqlbuilder,功能更强
go get github.com/huandu/go-sqlbuilder
package main
import (
"database/sql"
"fmt"
"log"
_ "github.com/go-sql-driver/mysql"
"github.com/huandu/go-sqlbuilder"
)
var db *sql.D ...
Golang 数据库标准开发
数据库标准开发驱动连接数据库是典型的CS变成,服务器端被动等待客户端建立TCP连接,并在此连接上进行特定的应用层协议。但是一般用户并不需要了解这些细节,这些都被打包到了驱动库中,只需要简单的调用打开就可以指定协议连接到指定的数据库中
数据库的种类和产品太多,协议太多,Go官方很难提供针对不同数据库的驱动程序,往往由各数据库官方或第三方给出不同开发语言的驱动库。但是,为了Go语言可以提前定义操作一个数据库的所有行为(接口)和数据(结构体)的规范,这些定义在databasq/sql下。
mysql驱动:
https://github.com/go-sql-driver/mysql 支持database/sql,推荐
https://github.com/ziutek/mymysql 支持database/sql,支持自定义接口
https://github.com/Philio/GoMySQL 不支持database/sql,支持自定义接口
安装mysql的驱动
$ go get -u github.com/go-sql-driver/mysql ...
Golang日志管理
日志标准库的log包Go标准库中有log包,提供了简单的日志功能。
输出
格式输出
换行输出
log.Print()
log.Printf()
log.Pringln()
类似fmt.print*
log.Fatal()
log.Fatalf()
log.Fatalln()
相当于log.Print* + os.Exit(1)
log.Panic()
log.Panicf()
log.Panicln()
相当于log.Print* + panic(0
日志输出需要使用日志记录器Logger。
log包提供了一个缺省的Logger即std。std是小写的,包外不可见,所以提供了Default()方法返回std给包外使用。如下:
package main
import (
"log"
)
func main() {
// 这里就是使用缺省的logger对象,可以点进Println查看源码
log.Println("这是缺省的logger")
}
源码如下:
// go源码
// Println calls Output ...
Golang包管理
包管理模块化用任何语言来开发,如果软件规模扩大,会编写大量的函数、结构体、接口等代码。这些代码不可能写在一个文件中,这就会产生大量的文件。如果这些文件杂乱无章,就会造成名称冲突、重复定义、难以检索、无法引用、共享不便、版本管理等一系列问题。有一些功能模块如何复用,如何共享方便其他项目使用。所以,一定要有模块化管理,解决以上诸多问题。
包
包由多个文件和目录组成
使用package<包名> 来定义包名
包名一般采用小写,符合标识符要求
当前目录名和package<包名> 中的包名不需要一致,但最好保持一致
同级文件归属一个包,就是说每个包目录中,只能统一使用同一个package的包名,否则编译出错
一般来说,开发项目时,可以吧相关功能的代码集中放在某几个包里面。例如在main包目录中新建一个calc包,将所有计算函数都放在其中,以供别的代码调用。
同一个目录就是同一个包,该包内go文件里面的变量、函数、结构体互相可见,可以直接调用。
跨目录就是跨包,使用时需要导入别的包,导入需要指定该包的路径,
包管理GOPATHGo 1.11版本之前,项目依赖包存于GOPAT ...
Golang时间操作
时间在Go语言中,时间定义为Time结构体。
var t = time.Now()
fmt.Printf("%T\n", t) // time.Time
fmt.Printf("%v %+[1]v\n", t) // 2022-10-06 19:35:00.1963422 +0800 CST m=+0.001534601
fmt.Printf("%#v\n", t) // time.Date(2022, time.October, 6, 19, 35, 0,
196342200, time.Local)
fmt.Printf("%T, %[1]v\n", t.UTC()) // UTC时间
// time.Time, 2022-10-06 11:35:00.1963422 +0000 UTC
m=+0.001530201为单调时间,利用的是晶体振荡器的间隔时间,很多时间函数计算都舍弃了它。如果不是非常精准的时间间隔计算,请忽略它。
时间格式化var t = time.Now()
fmt.Printf("%T, %[1]v\n", t)
fmt.Println(t.Form ...
Golang序列化和反序列化
序列化和反序列化内存中的map、slice、array以及各种对象,如何保存到一个文件中? 如果是自己定义的结构体的实例,如何保存到一个文件中?
如何从文件中读取数据,并让它们在内存中再次恢复成自己对应的类型的实例?要设计一套协议,按照某种规则,把内存中数据保存到文件中。文件是一个字节序列,所以必须把数据转换成字节序列,输出到文件。这就是序列化。 反之,从文件的字节序列恢复到内存并且还是原来的类型,就是反序列化。
序列化:将内存中的数据结构转换成字节序列
反序列化:将字节序列恢复到内存中并且还是之前的数据类型,就是反序列化
定义
serialization序列化:将内存中对象存储下来,把他变成一个个字节。转为二进制数据
deserialization反序列化:将文件的一个个字节恢复成内存中对象。从二进制数据中恢复。
序列化保存到文件就是持久化。
可以将数据序列化后持久化,或者网络传输;也可以将从文件中或网络中接收到的字节序列反序列化。
可以把数据和二进制序列之间的相互转换称为二进制序列化、反序列化,把数字和字符序列之间的相互转换称为字符序列化、反序列化
字符序列化:JSON、XML等 ...
Go中的面向对象
Go中的面向对象面相对象三要素
封装:将属性(数据)和方法(操作)封装,提供访问控制,隐藏实现细节,暴露该暴露的
继承:子类可以从父类直接获得属性和方法,减少重复定义。子类中如果与父类不同,可以自己定义新的属性和方法,也可以覆盖同名的属性和方法
多态:前提是继承和覆盖,使得子类中虽然使用同一个方法,但是不同子类表现不同,就是不同的态
实现了以上特征的语言,才能称为面向对象编程范式语言。
严格意义上说,Go语言不想实现面向对象编程范式。但是面相对象又有一些不错的特征,Go语言通过组合的方式实现了类似的功能。
只能说,Go语言实现了一种非常有自我特征的面向对象。
封装通过结构体,可以把数据字段封装在内,还可以为结构体提供方法。
访问控制:
属性、方法标识符首字母大写,实现了对包外可见的访问控制
属性、方法标识符首字母小写,仅包内可见
这些一定程度上实现了public、private的访问控制。
构造函数Go没有提供类似C++、Java一样的构造函数、析构函数。在Go中,用构造结构体实例的函数,这个函数没有特别的要求,只要返回结构体实例或其指针即可(建议返回指针,不然返回值会拷贝)。习 ...
Golang错误处理
错误处理异常处理Go的设计者认为其它语言异常处理太过消耗资源,且设计和处理复杂,导致使用者不能很好的处理错误,甚至觉得异常和错误处理起来麻烦而忽视、忽略掉,从而导致程序崩溃。
函数调用,返回值可以返回多值,一般最后一个值可以是error接口类型的值
如果函数调用产生错误,则这个值是一个error接口类型的错误
如果函数调用成功,则该值是nil
检查函数返回值中的错误是否是nil,如果不是nil,进行必要的错误处理
error是Go中声明的接口类型
type error interface{
Error() string
}
所有实现Error() string签名的方法,都可以实现错误接口。用Error()方法返回错误的具体描述
自定义errorpackage main
import "fmt"
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s }
func New(text str ...
Golang接口
接口接口interface,和java类似,是一组行为规范的集合,就是定义一组未实现的函数声明。谁使用接口就是参照接口的方法定义实现他们。
type 接口名 interface {
方法1 (参数列表1) 返回值列表1
方法2 (参数列表2) 返回值列表2
...
}
接口命名习惯在接口名后面加上er后缀
参数列表、返回值列表参数名可以不写
如果要在包外使用接口,接口名应该大写,方法要在包外使用,方法名首字母也要大写。
接口中的方法应该设计合理,不要太多
Go语言中,使用组合实现对象特性的描述。对象内部使用结构体内嵌组合对象应该具有的特性,对外通过接口暴露能使用的特性。
Go语言的接口设计是非侵入式的,接口编写者无需知道接口被哪些类型实现。而接口实现者只需知道实现的是什么样子的接口,但无需指明实现哪一个接口。编译器知道最终编译时使用哪个类型实现哪个接口,或者接口应该由谁来实现。
接口是约束谁应该具有什么功能,实现某接口的方法,就具有该接口的功能,简而言之,缺什么补什么。
接口实现如果一个结构体实现了一个接口声明的所有方法,就说结构体实现了 ...
Golang结构体
结构体Go语言的结构体有点像面向对象语言中的”类”,但不完全是,Go语言也没打算真正实现面向对象范式
定义使用type定义结构体,可以把结构体看做类型使用。必须指定结构体的字段(属性)名称和类型。
type User struct {
id int
name,addr string
score float32
}
User不过是个标识符,一个指代
真正的类型定义是struct{}的部分
初始化type User struct {
id int
name, addr string
score float32
}
// 1 var声明,非常常用
var u1 User // 这种方式声明结构体变量很方便,所有字段都是零值
fmt.Println(u1)
fmt.Printf("%+v\n", u1) // 加上字段打印
fmt.Printf("%#v\n", u1) // 加上更多信息打印
// 2 字面量初始化,推荐
u2 := User{} // 字段为零值
fmt.Print ...