极客时间Go实战训练营

极客时间Go实战训练营插图1

GO的进阶语法

1.1 定义

对于结构体,他的定义方式如下:

type 结构体名 struct {     字段1 类型     字段2 类型 }

1.2 声明

对于结构体的声明和初始化,有以下几种形式:

使用var关键字

var s T s.a = 1 s.b = 2

注意,在使用了var关键字之后不需要初始化,这和其他的语言有些不同。Golang会自动分配内存空间,并将该内存空间设置为默认的值,我们只需要按需进行赋值即可。

使用new函数

type people struct {     name string     age int } func main() {     ming := new(people)     ming.name = "xiao ming"     ming.age = 18 } 复制代码

使用字面量

type people struct {     name string     age int } func main() {     ming := &people{"xiao ming", 18} }

Go从零实现Web框架Gee

大部分时候,我们需要实现一个 Web 应用,第一反应是应该使用哪个框架。不同的框架设计理念和提供的功能有很大的差别。比如 Python 语言的djangoflask,前者大而全,后者小而美。Go语言/golang 也是如此,新框架层出不穷,比如BeegoGinIris等。那为什么不直接使用标准库,而必须使用框架呢?在设计一个框架之前,我们需要回答框架核心为我们解决了什么问题。只有理解了这一点,才能想明白我们需要在框架中实现什么功能。

我们先看看标准库net/http如何处理一个请求。

funcmain(){http.HandleFunc("/", handler)"/count", counter)log.Fatal(http.ListenAndServe("localhost:8000",nil))}funchandler(w http.ResponseWriter, r *http.Request){fmt.Fprintf(w,"URL.Path = %qn", r.URL.Path)}

提供了基础的Web功能,即监听端口,映射静态路由,解析HTTP报文。一些Web开发中简单的需求并不支持,需要手工实现。

  • 动态路由:例如hello/:namehello/*这类的规则。

  • 鉴权:没有分组/统一鉴权的能力,需要在每个路由映射的handler中实现。

  • 模板:没有统一简化的HTML机制。

当我们离开框架,使用基础库时,需要频繁手工处理的地方,就是框架的价值所在。但并不是每一个频繁处理的地方都适合在框架中完成。Python有一个很著名的Web框架,名叫bottle,整个框架由bottle.py一个文件构成,共4400行,可以说是一个微框架。那么理解这个微框架提供的特性,可以帮助我们理解框架的核心能力。

  • 路由(Routing):将请求映射到函数,支持动态路由。例如/hello/:name

  • 模板(Templates):使用内置模板引擎提供模板渲染机制。

  • 工具集(Utilites):提供对 cookies,headers 等处理机制。

  • 插件(Plugin):Bottle本身功能有限,但提供了插件机制。可以选择安装到全局,也可以只针对某几个路由生效。

Go数据库查询ORM 框架

数据库表与数据模型

//建表语句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,  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语句中。

通过ID来查询数据

若数据库表存在id字段,则可以通过ID函数来查询一条数据据记录:

func DemoGetById() {    var user model.User    _, err := worm.Model(&user).ID(1).Get()    if err != nil {        log.Error(err)        return    }    log.Debug(user)}//select id,name,age,passwd,created from user where id=? limit 1

执行该函数后的sql日志为:

[S] select id,name,age,passwd,created from user where id=1 limit 1[S] DB: time=18.816ms

通过Where函数来查询数据

Where函数的使用类似Sprintf函数,函数的第一个参数是sql语句(where语句)模板,后面的参数是模板变量的值。

func DemoWhere() {    var users []model.User    err := worm.Model(&model.User{}).Where("id>? and age>?", 1, 10).Find(&users)    if err != nil {        log.Error(err)        return    }}//对应的sql语句为://select id,name,age,passwd,created from user where id>? and age>?
  • worm占位符统一使用?,worm会根据数据库类型,自动替换占位符,例如postgresql数据库把?替换成$1,$2…

  • 可以在Where函数使用多个变量进行查询,这种方式比较直观,与数据库查询中的sql语句的写法比较类似。但是当查询条件比较多时,建议使用And、OR函数进行适当的分割,防止将查询变量与变量的值对应错误。例如:

func DemoWhere2() {    var users []model.User    err := worm.Model(&model.User{}).Where("id>?", 1).And("age>?", 10).Find(&users)    if err != nil {        log.Error(err)        return    }}//对应的sql语句为://select id,name,age,passwd,created from user where id>? and age>?
举报/反馈

原创文章 极客时间Go实战训练营,版权所有
如若转载,请注明出处:https://www.itxiaozhan.cn/202210426.html

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注