Name string
Age int
Gender string
}
赋值:
c.Data[“student”] = Student{Name:“知了课堂”,Age:18,Gender:“男”}
前端使用:
学生姓名:{{.student.Name}}
学生年龄:{{.student.Age}}
学生性别:{{.student.Gender}}
注意:结构体中的字段要在其他地方使用,比如首字母大写
- 数组数据渲染
lista := [5]int{1,2,3,4,5}
c.Data[“arr”] = lista
前端:
第一种:
{{range i , i, i,v := .arr}}
{{$i}}
{{$v}}
{{end}
第二种:
{{range .arr}}
{{.}}
{{end}}
- 结构体数组渲染
结构体:
type student struct {
Name string
Age int
Gender string
}
赋值:
arr_struct := [3]student{{Name:“hl”,Age:18,Gender:“男”},{Name:“hallen”,Age:19,Gender:“男”},{Name:“hallen1”,Age:191,Gender:“男”}}
c.Data[“arr_struct”] = arr_struct
前端获取:先循环数组,在获取结构体变量,注意是大写
{{range $v := .arr_struct}}
{{$v.Name}}
{{$v.Age}}
{{$v.Gender}}
{{range .books}}
{{.Name}}
{{.Author}}
{{end}}
- map数据渲染
//teacher :=map[string]string{“name”:“张三”,“age”:“18”}
teacher :=make(map[string]string)
teacher[“name”]=“老王”
teacher[“age”]=“30”
c.Data[“teacher”] = teacher
前端:
取出key对应的值
{{.teacher.name}}
{{.teacher.age}}
取出所有的key和value:
{{range k , k, k,v := .teacher}}
{{$k}}
{{$v}}
{{end}}
- 结构体和map组合渲染
结构体:
type student struct {
Name string
Age int
Gender string
}
赋值:
mapa := make(map[int]student)
mapa[101] = student{Name:“张三1”,Age:181,Gender:“男”}
mapa[102] = student{Name:“张三2”,Age:182,Gender:“男”}
mapa[103] = student{Name:“张三3”,Age:183,Gender:“男”}
c.Data[“hero_map”] = mapa
前端获取:先循环map,在获取结构体变量,注意是大写
{{range $v :=.hero_map}}
{{$v.Name}}
{{end}}
- 切片数据渲染
listb := []int{1,2,3,4,5,6,7}
c.Data[“list_b”] = listb
前端:只有一个值的时候默认是切片的元素,而不是角标
{{range $v := .list_b}}
{{$v}}
{{end}}
获取url上的参数,?后面的 :http://127.0.0.1:8090/user/?id=111
可以使用数据绑定,请看数据绑定章节
GetString获取数据:
路由: beego.Router(“/user”, &controllers_user.UserController{})
访问路径:http://127.0.0.1:8090/user/?id=111
获取数据:
id := c.Input().Get(“id”)
id2 := c.GetString(“id”)
这种方式不行:
id3 := c.Ctx.Input.Param(“:id”)
获取url上的参数,/:id的 :http://127.0.0.1:8090/user/111
路由:beego.Router(“/user/?🆔int”, &controllers_user.UserController{})
访问路径:http://127.0.0.1:8090/user/111
获取数据:
id := c.GetString(“:id”)
id2 := c.Ctx.Input.Param(“:id”)
这种方式不行:
id3 := c.Input().Get(“:id”)
获取请求信息:
this.Ctx.Request 所有的请求信息
this.Ctx.Request.Header 请求头
this.Ctx.Request.Host 请求的主机
this.Ctx.Request.Method 请求的方法
获取form表单数据:
GetString(key string) string
GetStrings(key string) []string
GetInt(key string) (int64, error) --返回两个值
GetBool(key string) (bool, error) --返回两个值
GetFloat(key string) (float64, error) --返回两个值
举例:
前端form表单:
年龄1:
姓名1:
地址:
姓名2:
年龄2:
是:
否:
价格:
获取数据:
name := c.Input().Get(“name”) 获取的是第一个name的值
names := c.GetStrings(“name”) 获取所有的name的值,是个数组
age := c.Input().Get(“age”)
age,_ := c.GetInt64(“age”)
is_true , _ := c.GetBool(“is_true”)
price , _ := c.GetFloat(“price”)
form表单解析到结构体
type Student struct {
Id int
Name string form:"user_name"
Password string form:"password"
}
func (s *StudentController) Post() {
student := Student{} // 这里注意,变量名不能和结构体对象名不能相同
if err := s.ParseForm(&student); err != nil {
//handle error
return
}
fmt.Println(student)
fmt.Println(student.Name)
fmt.Println(student.Age)
fmt.Println(student.Addr)
s.TplName = “index.tpl”
}
ajax提交
2.4.1 form方式上传
- 前端
前端:
上传文件:
注意:
这里必须设置enctype=“multipart/form-data”,不然浏览器不会传送文件
- 后端
type Upload struct {
beego.Controller
}
func (u *Upload)Get() {
u.TplName = “upload_file.html”
}
func (u *Upload)Post() {
// 获取上传的文件
f,h,err := u.GetFile(“upload_file”)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
// 生成时间戳,防止重名
timeUnix:=time.Now().Unix() // int64类型
time_str := strconv.FormatInt(timeUnix,10) // 将int64转为字符串 convert:转换
// 保存获取到的文件
err1 := u.SaveToFile(“upload_file”,“static/upload/”+time_str+h.Filename) // 这里必须有这个路径才会保存成功, 否则报错:The system cannot find the path specified
if err1 != nil{
fmt.Println(err1)
}
u.TplName = “index.tpl”
}
注意:
相同文件名的文件会被后面上传的覆盖,可以使用时间戳重命名文件
二、ajax方式上传
- 前端
-
processData 默认为true,当设置为true的时候,jquery ajax 提交的时候不会序列化 data,而是直接使用data
-
contentType: false 不使用默认的application/x-www-form-urlencoded这种contentType
-
分界符:目的是防止上传文件中出现分界符导致服务器无法正确识别文件起始位置
-
ajax 中 contentType 设置为 false 是为了避免 JQuery 对其操作,从而失去分界符
背景:假如前端或者提供的接口必须以指定的格式传输
json格式:会设置 content-type 为 application/json
type TestController struct {
beego.Controller
}
type Person struct {
Id int
Name string
Gender string
}
func (g *TestController)Get() {
test_data := Person{Id:123,Name:“zhiliao”,Gender:“男”}
g.Data[“json”] = &test_data -----这里必须叫json,因为ServeJSON()解析json变量的
fmt.Println(test_data)
g.ServeJSON()
//g.TplName = “test.html”
}
xml格式:会设置 content-type 为 application/xml
test_data := Person{Id:123,Name:“zhiliao”,Gender:“男”}
g.Data[“xml”] = &test_data -----这里必须叫xml,同上
g.ServeXML()
jsonp格式:会设置 content-type 为 application/javascript
test_data := Person{Id:123,Name:“zhiliao”,Gender:“男”}
g.Data[“jsonp”] = &test_data -----这里必须叫jsonp,同上
g.ServeJSONP()
yaml格式:会以文件传输的方式,yaml就是键值对
test_data := Person{Id:123,Name:“zhiliao”,Gender:“男”}
g.Data[“yaml”] = &test_data
g.ServeYAML()
yaml格式:
student:
-
name : “zhiliao”
-
age : 18
teacher:
- name : “laowang”
-age : 38
addr: “市区”
说明:
-
大小写敏感
-
使用缩进表示层级关系
-
缩进不允许使用tab,只允许空格
-
缩进的空格数不重要,只要相同层级的元素左对齐即可
-
'#'表示注释
-
以 - 开头的行表示构成一个数组,支持多维数组
===================================================================
3.1.1 基本语法
-
使用
.
来访问当前位置的上下文 -
使用
$
来引用当前模板根级的上下文 -
使用
$.
引用模板中的根级上下文
3.1.2其他常用模板语法
- 支持go语言的符号,这里只是符号的支持
① 字符串:{ { “zhiliao ” } }
② 原始字符串:{ { `zhiliao` } } 不会转义
③ 字节类型:{ { ’ a’ } } -->97 ascll码对应表: http://ascii.911cha.com/
④ nil:{ { print nil } } { {nil } }只有nil会报错:nil is not a command
-
if:判断
-
range:循环
注:range也支持else,表示空数组的时候执行
- template:对于模板的分模块处理很有用处,引入另一个模板文件
{{template “bottom.html” .}}
注意:如果引入的文件也需要获取动态数据,那{ {template “bottom.html” .} }中必须使用.访问当前位置的上下文
- and
{ {and .X .Y .Z} }
只要有一个为空,则整体为空,如果都不为空,则返回最后一个
- or
{ {or .X .Y .Z} }
只要有一个不为空,则返回第一个不为空的,否则返回空
- index:读取指定类型对应下标的值
获取
后端:
this.Data[“data_map”] = map[string]string{“name”: “Beego”}
this.Data[“arrs”] = []int{1,2,3,4,5}
前端:
{{index .data_map “name”}}
{{index .arrs 1}}
- len:返回对应类型的长度
{ { .Content|len } }
- not:返回输入参数的否定值
{{not .is_ok }}
6.eq / ne / lt / le / gt / ge
-
eq:等于 equls
-
ne:不等于
-
lt:小于 less
-
le:小于等于 区别于lte
-
gt:大于 greater
-
ge:大于等于 区别于gte
- 内置模板函数
1.date 格式化时间
{{date .T “Y-m-d H:i:s”}}
- compare 比较
{{compare ‘a’ 97}}
- substr 截取字符串
{{substr “我是中国人” 0 4}}
- map_get 获取map的指定key值
{{ map_get .m “a” }}
- url_for
{{urlfor “TestController.List”}}
第一步:定义函数
func hello(in string)(out string){
out = in + “world”
return
}
第二步:AddFuncMap
// 在beego.Run()之前
beego.AddFuncMap(“hi”,helle)
第三步:前端使用
{{“hello world” | hi}}
=========================================================================
4.1.1 读取配置
beego.AppConfig.String(“mysqluser”)
4.2.2 引入其他配置文件
app.conf是主配置文件。其他的配置文件需要再app.conf中引入
include “mysql_server.conf”
4.3.3 常用的配置
-
ViewsPath:模板路径,默认值是 views。
-
StaticDir:静态文件目录设置,默认是static
-
sessionon:session 是否开启,默认是 false
-
httpport:监听端口
-
EnableXSRF:EnableXSRF
-
XSRFExpire:XSRF 过期时间,默认值是 0,不过期。
-
MaxMemory:文件上传默认内存缓存大小,默认值是1 << 26(64M)。
-
RunMode:应用的运行模式,可选值为prod,dev或者test. 默认是dev, 为开发模式
4.2.1 固定路由
一个固定的路由,一个控制器,然后根据用户请求方法不同请求控制器中对应的方法
beego.Router(“/hello”, &controllers_user.Hello{})
4.2.2 正则路由
beego.Router(“/api/?:id”, &controllers.RController{})
beego.Router(“/api/?🆔int”, &controllers.RController{})
:id([0-9]+) 或者 :id([\d]+) 或者 🆔int
:username([\w]+) 或者 :username:string
4.2.3 自动路由
注册路由的时候不需要指定url,只需要注册控制器即可
beego.AutoRouter(&controllers.UserController{})
规则:
/控制器名/方法名/后面的都是参数。。。
如:/user/get/123/456
4.2.4 自定义路由
注册路由的时候可以指定第三个参数,这个参数就是用来自定义路由的
用法: method :函数名
post:Login post请求的时候访问Login函数
get:User get请求的时候访问User函数
*:LoginOut 所有的请求方法都访问LoginOut函数
需要登录才能访问的
/cms/user/add
/cms/user/list
/cms/user/edit
/cms/book/add
不需要登录可以访问:
/
/login
/register
beego.InsertFilter(pattern string, position int, filter FilterFunc, params …bool)
-
第一个参数表示过滤的路由规则,支持通配符
-
第二个参数就是过滤器的位置,beego支持的有5种
-
BeforeStatic 静态地址之前
-
BeforeRouter 寻找路由之前
-
BeforeExec 找到路由之后,开始执行相应的 Controller 之前
-
AfterExec 执行完 Controller 逻辑之后执行的过滤器
-
FinishRouter 执行完逻辑之后执行的过滤器
-
第三个参数为执行的函数
-
func(*context.Context) 参数必须是context.Context , context是beego包下的
-
其他参数:使用默认得到true即可
示例:
func main() {
// 过滤器
beego.InsertFilter(“/*”, beego.BeforeRouter, controllers.LoginSpider1Filter)
beego.Run()
}
func LoginSpider1Filter(ctx *context.Context) {
// 获取session
id := ctx.Input.Session(“spider1_uid”)
if id == nil { // 说明未登录
ctx.Redirect(302,“/main/spider1/to_login”)
// 路由反转:beego.URLFor(“TestController.Get”)
}
}
注意:使用 session 的 Filter 必须在 BeforeStatic 之后才能获取,因为 session 没有在这之前初始化。
4.4.1 安装
go get github.com/astaxie/beego/validation
4.4.2 使用
结构体定义tag
-
验证函数写在 “valid” tag 的标签里
-
各个函数之间用分号 “;” 分隔,分号后面可以有空格
-
参数用括号 “()” 括起来,多个参数之间用逗号 “,” 分开,逗号后面可以有空格
-
正则函数(Match)的匹配模式用两斜杠 “/” 括起来
-
各个函数的结果的 key 值为字段名.验证函数名
type LoginParams struct {
Name string valid:“Required”
Age int valid:“Required;MinSize(2)”
Addr string valid:“Required”
}
func (l *LoginController) Post() {
valid := validation.Validation{}
// 解析到结构体
params := LoginParams{}
if err := l.ParseForm(¶ms); err != nil {
//handle error
return
}
//重写错误信息:validation.SetDefaultMessage(map)
var messages = map[string]string{
“Required”: “不能为空”,
“MinSize”: “最短长度为 %d”,
“Length”: “长度必须为 %d”,
“Numeric”: “必须是有效的数字”,
“Email”: “必须是有效的电子邮件地址”,
“Mobile”: “必须是有效的手机号码”,
}
validation.SetDefaultMessage(messages)
// 校验
b, err := valid.Valid(¶ms)
// 验证StructTag 是否正确
if err != nil {
fmt.Println(err)
}
if !b {
// 验证没通过,则b为false
for _, err := range valid.Errors {
fmt.Println(err.Key, err.Message)
message := err.Key + err.Message
l.Ctx.WriteString(message)
}
}
}
4.5.1 什么是session?
-
Session是在_无状态_的HTTP协议下,服务端记录用户状态时用于标识具体用户的机制
-
它是在服务端保存的用来跟踪用户的状态的数据结构,可以保存在文件、数据库或者集群中
-
在浏览器关闭后这次的Session就消失了,下次打开就不再拥有这个Session。其实并不是Session消失了,而是Session ID变了,
4.5.2 什么是cookie?
-
Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息
-
每次HTTP请求时,客户端都会发送相应的Cookie信息到服务端。它的过期时间可以任意设置,如果你不主动清除它,在很长一段时间里面都可以保留着,即便这之间你把电脑关机了。
-
每次客户端发请求的时候会自动携带该域名下的Cookie,不用域名间的Cookie是不能共享的
4.5.3 session和cookie:
-
Cookie 在客户端(浏览器),Session 在服务器端。
-
Cookie的安全性一般,他人可通过分析存放在本地的Cookie并进行Cookie欺骗。在安全性第一的前提下,选择Session更优。重要交互信息比如权限等就要放在Session中,一般的信息记录放Cookie就好了。
-
单个Cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个Cookie。
-
Session 可以放在 文件、数据库或内存中
-
用户验证这种场合一般会用 Session。因此,维持一个会话的核心就是客户端的唯一标识,即Session ID。
-
Session 的运行依赖Session ID,而 Session ID 是存在 Cookie 中的,也就是说,如果浏览器禁用了 Cookie,Session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 Session ID)
4.5.4 beego中使用session:
-
开启session
-
main.go中开启:
-
beego.BConfig.WebConfig.Session.SessionOn = true
-
配置文件中开启:
-
sessionon = true
-
使用sessio
-
设置session
-
SetSession(name string, value interface{})
-
this.SetSession(“username”, “zhiliao”)
-
获取session
-
GetSession(name string) interface{}
-
this.GetSession(“username”)
-
删除session
-
this.DelSession(name string)
-
在过滤器中获取session
-
ctx.Input.Session(“user_name”)
-
关于session的一些其他配置
-
设置是否开启 Session
-
beego.BConfig.WebConfig.Session.SessionOn
-
默认为false
-
设置 Session 过期的时间
-
beego.BConfig.WebConfig.Session.SessionGCMaxLifetime
-
默认值是 3600 秒
-
设置 cookie 的过期时间
-
beego.BConfig.WebConfig.Session.SessionCookieLifeTime
-
设置sessionid加密算法
-
beego.BConfig.WebConfig.Session.SessionHashFunc
-
默认值为 sha1
-
修改sessionkey
-
beego.BConfig.WebConfig.Session.SessionHashKey
-
默认的 key 是 beegoserversessionkey,建议在使用的时候修改该参数
-
设置 cookies 的名字
-
beego.BConfig.WebConfig.Session.SessionName
-
Session 默认是保存在用户的浏览器 cookies 里面的,默认名是 beegosessionID,配置文件对应的参数名是:sessionname。
====================================================================
5.1.1 mysql安装
- 用户名和密码的配置
5.1.2 navicat安装
5.1.3 beego中使用
-
安装:
-
go get github.com/astaxie/beego/orm
-
go get github.com/go-sql-driver/mysql
-
连接数据库:
-
orm.RegisterDriver(“mysql”, orm.DRMySQL)
-
orm.RegisterDataBase(“default”, “mysql”, “用户名:密码@tcp(IP:端口号)/数据库?charset=utf8”, 30)
-
参数一:数据库的别名,用来在 ORM 中切换数据库使用
-
参数二:驱动名称
-
参数三:对应的链接字符串
-
参数四(可选):设置最大空闲连接
-
或根据数据库别名设置:orm.SetMaxIdleConns(“default”, 30)
-
参数五(可选):设置最大数据库连接
-
或根据数据库别名设置: orm.SetMaxOpenConns(“default”, 30)
-
注册模型
-
在init函数中:orm.RegisterModel(new(Article)),只有注册了模型才可以使用
-
创建表
-
在数据库中操作创建表即可,后面会讲自动迁移表
-
时区设置:
-
orm.DefaultTimeLoc = time.UTC // 设置为 UTC 时间
-
ORM 在进行 RegisterDataBase 的同时,会获取数据库使用的时区,然后在 time.Time 类型存取时做相应转换,以匹配时间系统,从而保证时间不会出错
-
示例代码
-
首先创建好数据库和表,表对应结构体中的属性
-
app.conf链接信息配置:
dbhost = 127.0.0.1
dbuser = root
dbpassword = root
dbport = 3306
db = user
main.go中初始化链接:
-
orm.RegisterDriver(“mysql”, orm.DRMySQL)
-
orm.RegisterDataBase(“default”, “mysql”, “root:root@/orm_test?charset=utf8”)
“github.com/astaxie/beego/orm”
_ “github.com/go-sql-driver/mysql”
func init() {
// 读取配置信息
dbhost := beego.AppConfig.String(“dbhost”)
dbport := beego.AppConfig.String(“dbport”)
dbuser := beego.AppConfig.String(“dbuser”)
dbpassword := beego.AppConfig.String(“dbpassword”)
db := beego.AppConfig.String(“db”)
//注册mysql Driver
orm.RegisterDriver(“mysql”, orm.DRMySQL)
//构造conn连接
//用户名:密码@tcp(url地址)/数据库
conn := dbuser + “:” + dbpassword + “@tcp(” + dbhost + “:” + dbport + “)/” + db + “?charset=utf8”
//注册数据库连接
orm.RegisterDataBase(“default”, “mysql”, conn)
fmt.Printf(“数据库连接成功!%s\n”, conn)
}
模型结构体:
注意:结构体的字段名首字母必须大写
type Article struct {
Id int
Name string
Author string
}
func init(){
orm.RegisterModel(new(Article))
}
增加数据:
o := orm.NewOrm()
o.Using(“default”) // default可以不用using
newStudent := Student{Name:“zhiliao”,Age:18,Gender:“男”}
//新增数据
id, err :=o.Insert(&newStudent) // 返回添加的数据id以及错误信息
注意:
- ORM 必须注册一个别名为 default 的数据库,作为默认使用
用作数据库数据转换和自动建表
5.2.1 模型名和表名映射
- 模型名和表名的映射规则:除了开头的大写字母以外,遇到大写会增加 _,原名称中的下划线保留。
① Article -> article
② AuthUser -> auth_user
③ Auth_User -> auth__user 两个下划线
④DB_AuthUser -> d_b__auth_user
- 自定义表名
type User struct {
Id int
Name string
}
func (u *User) TableName() string {
return “auth_user”
}
5.2.2 设置参数:使用structtag
-
忽略字段structtag:`orm:“-”`
-
pk设置为主键,适用于自定义其他类型为主键
-
null:Name string `orm:“null”`
-
auto:自增长
Id int orm:"pk;auto"
- index:索引
Name string orm:"index"
索引的作用:优化查询,相当于图书的目录
- unique
Name string orm:"unique"
- column
Name string orm:"column(user_name)"
- size:对string起作用
Title string orm:"size(60)"
- digits / decimals 4 2 12.21
Money float64 orm:"digits(12);decimals(4)"
总长度12,小数点后有4位小数
- auto_now / auto_now_add
Created time.Time orm:"auto_now_add;type(datetime)"
Updated time.Time orm:"auto_now;type(datetime)"
auto_now 每次 model 保存时都会对时间自动更新
auto_now_add 第一次保存时才设置时间
- type:日期还是时间
Created time.Time orm:"auto_now_add;type(date)"
Created time.Time orm:"auto_now_add;type(datetime)"
- default
Gender float64 orm:"default(0)"
- description
修改源码:cmd_utils.go的 getColumnAddQuery()最后加:fi.description,
Name string orm:"description(这是标签名称)"
5.2.3 表关系
- 一对一
① User模型中: Profile *Profile `orm:“rel(one)”` 正向关系,有外键字段
② Profile模型中: User *User `orm:“reverse(one)”` 反向关系,只是关系,没有外键
- 一对多
① article模型中:User *User `orm:“rel(fk)”` 正向关系,有外键,外键在多的一方
② user模型中:Articles []*Articles `orm:“reverse(many)” 反向关系,没有外键
一对多,外键在多的一方
- 多对多
① post模型中:Tags []*Tag `orm:“rel(m2m)”` 正向关系,没有外键
② tag模型中:Posts []*Post `orm:“reverse(many)”` 反向关系,没有外键
前提:注册模型:RegisterModel
5.3.1 使用QueryTable
o := orm.NewOrm()
qs := o.QueryTable(“user”) 表名作为参数
qs := o.QueryTable(new(User)) 也可以直接使用对象作为表名
返回的是QuerySeter
5.3.2 exper表达式的使用:两个下换线
- exact / iexact:等于,默认值,大小写敏感 / 不敏感
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
最后
你要问前端开发难不难,我就得说计算机领域里常说的一句话,这句话就是『难的不会,会的不难』,对于不熟悉某领域技术的人来说,因为不了解所以产生神秘感,神秘感就会让人感觉很难,也就是『难的不会』;当学会这项技术之后,知道什么什么技术能做到什么做不到,只是做起来花多少时间的问题而已,没啥难的,所以就是『会的不难』。
我特地针对初学者整理一套前端学习资料,免费分享给大家,戳这里即可免费领取
_add
Created time.Time orm:"auto_now_add;type(datetime)"
Updated time.Time orm:"auto_now;type(datetime)"
auto_now 每次 model 保存时都会对时间自动更新
auto_now_add 第一次保存时才设置时间
- type:日期还是时间
Created time.Time orm:"auto_now_add;type(date)"
Created time.Time orm:"auto_now_add;type(datetime)"
- default
Gender float64 orm:"default(0)"
- description
修改源码:cmd_utils.go的 getColumnAddQuery()最后加:fi.description,
Name string orm:"description(这是标签名称)"
5.2.3 表关系
- 一对一
① User模型中: Profile *Profile `orm:“rel(one)”` 正向关系,有外键字段
② Profile模型中: User *User `orm:“reverse(one)”` 反向关系,只是关系,没有外键
- 一对多
① article模型中:User *User `orm:“rel(fk)”` 正向关系,有外键,外键在多的一方
② user模型中:Articles []*Articles `orm:“reverse(many)” 反向关系,没有外键
一对多,外键在多的一方
- 多对多
① post模型中:Tags []*Tag `orm:“rel(m2m)”` 正向关系,没有外键
② tag模型中:Posts []*Post `orm:“reverse(many)”` 反向关系,没有外键
前提:注册模型:RegisterModel
5.3.1 使用QueryTable
o := orm.NewOrm()
qs := o.QueryTable(“user”) 表名作为参数
qs := o.QueryTable(new(User)) 也可以直接使用对象作为表名
返回的是QuerySeter
5.3.2 exper表达式的使用:两个下换线
- exact / iexact:等于,默认值,大小写敏感 / 不敏感
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-ULF80yB9-1713487852380)]
[外链图片转存中…(img-7QK1U82n-1713487852381)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
[外链图片转存中…(img-3yIy8nI9-1713487852381)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
[外链图片转存中…(img-36uKj5O0-1713487852381)]
最后
你要问前端开发难不难,我就得说计算机领域里常说的一句话,这句话就是『难的不会,会的不难』,对于不熟悉某领域技术的人来说,因为不了解所以产生神秘感,神秘感就会让人感觉很难,也就是『难的不会』;当学会这项技术之后,知道什么什么技术能做到什么做不到,只是做起来花多少时间的问题而已,没啥难的,所以就是『会的不难』。
我特地针对初学者整理一套前端学习资料,免费分享给大家,戳这里即可免费领取
[外链图片转存中…(img-qVxCnbge-1713487852382)]