[Go] Template 使用简介

Golang 提供了两个标准库用来处理模板 text/template 和 html/template。我们使用 html/template 格式化 html 字符。

模板引擎

模板引擎很多,Python 的 jinja,nodejs 的 jade 等都很好。所谓模板引擎,则将模板和数据进行渲染的输出格式化后的字符程序。对于 Go,执行这个流程大概需要三步。

  1. 创建模板对象
  2. 加载模板字串
  3. 执行渲染模板

其中最后一步就是把加载的字符和数据进行格式化。其过程可以总结下图:

warming up

Go 提供的标准库 html/template 提供了很多处理模板的接口。我们的项目结构为:

├── main.go
└── templates├── index.html└── layout.html

templates 文件夹有两个文件,分别为模板文件。 layout.html 文件如下:

<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>layout</title></head><body><h3>This is layout</h3>template data: {{ . }}</body>
</html>

我们可以使用 ParseFiles 方法加载模板,该方法会返回一个模板对象和错误,接下来就可以使用模板对象执行模板,注入数据对象。Go 的提供了一些模板标签,称之为 action,. 也是一种 action,更多的action 稍后解释。

func templateHandler(w http.ResponseWriter, r *http.Request) {t, _ := template.ParseFiles("templates/layout.html")fmt.Println(t.Name())t.Execute(w, "Hello world")
}

我们打印了 t 模板对象的 Name 方法,实际上,每一个模板,都有一个名字,如果不显示指定这个名字,Go 将会把文件名(包括扩展名当成名字)本例则是 layout.html。访问之后可以看见返回的 html 字串:

$  curl -i http://127.0.0.1:8000/
HTTP/1.1 200 OK
Date: Fri, 09 Dec 2016 09:04:36 GMT
Content-Length: 223
Content-Type: text/html; charset=utf-8<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>layout</title></head><body><h3>This is layout</h3>template data: Hello world</body>
</html>

Go 不仅可以解析模板文件,也可以直接解析模板字串,这就是标准的处理,新建 -> 加载 -> 执行 三部曲:

func templateHandler(w http.ResponseWriter, r *http.Request) {tmpl := `<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Go Web Programming</title></head><body>{{ . }}</body>
</html>`t := template.New("layout.html")t, _ = t.Parse(tmpl)fmt.Println(t.Name())t.Execute(w, "Hello World")
}

实际开发中,最终的页面很可能是多个模板文件的嵌套结果。Go 的 ParseFiles 也支持加载多个模板文件,不过模板对象的名字则是第一个模板文件的文件名。

func templateHandler(w http.ResponseWriter, r *http.Request) {t, _ :=template.ParseFiles("templates/layout.html", "templates/index.html")fmt.Println(t.Name())t.Execute(w, "Hello world")
}

可见打印的还是 layout.html 的名字,执行的模板的时候,并没有 index.html 的模板内容。

此外,还有 ParseGlob 方法,可以通过 glob 通配符加载模板。

模板命名与嵌套

模板命名

前文已经提及,模板对象是有名字的,可以在创建模板对象的时候显示命名,也可以让 Go 自动命名。可是涉及到嵌套模板的时候,该如何命名模板呢,毕竟模板文件有好几个?

Go 提供了 ExecuteTemplate 方法,用于执行指定名字的模板。例如加载 layout.html 模板的时候,可以指定 layout.html

func templateHandler(w http.ResponseWriter, r *http.Request) {t, _ :=template.ParseFiles("templates/layout.html")fmt.Println(t.Name())t.ExecuteTemplate(w, "layout", "Hello world")
}

似乎和 Execute 方法没有太大的差别。下面修改一下 layout.html 文件:

{{ define "layout" }}<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>layout</title></head><body><h3>This is layout</h3>template data: {{ . }}</body>
</html>{{ end }}

在模板文件中,使用了 define 这个 action 给模板文件命名了。虽然我们 ParseFiles 方法返回的模板对象 t 的名字还是 layout.html, 但是 ExecuteTemplate 执行的模板却是 html 文件中定义的layout。

不仅可以通过 define 定义模板,还可以通过 template action 引入模板,类似 jinja 的 include 特性。修改 layout.html 和 index.html

{{ define "layout" }}
<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>layout</title></head><body><h3>This is layout</h3>template data: {{ . }}{{ template "index" }}</body>
</html>
{{ end }}

index.html

{{ define "index" }}<div style="background: yellow">this is index.html
</div>{{ end }}

Go 的代码也需要修改,使用 ParseFiles 加载需要渲染的模板文件:

func templateHandler(w http.ResponseWriter, r *http.Request) {t, _ :=template.ParseFiles("templates/layout.html", "templates/index.html")t.ExecuteTemplate(w, "layout", "Hello world")
}

访问可以看到 index 被 layout 模板 include 了:

$ curl http://127.0.0.1:8000/<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>layout</title></head><body><h3>This is layout</h3>template data: Hello world<div style="background: yellow">this is index.html</div></body>
</html>

单文件嵌套

总而言之,创建模板对象后和加载多个模板文件,执行模板文件的时候需要指定 base 模板(layout),在 base 模板中可以 include 其他命名的模板。无论点 .,define,template 这些花括号包裹的东西都是 Go 的 action(模板标签)

Action

action 是 Go 模板中用于动态执行一些逻辑和展示数据的形式。大致分为下面几种:

  1. 条件语句
  2. 迭代
  3. 封装
  4. 引用

我们已经见识了 template 引用的用法,下面么再看看其他的用法

条件判断

条件判断的语法很简单:

{{ if arg }}some content
{{ end }}{{ if arg }}some content
{{ else }}other content
{{ end }}

arg 可以是基本数据结构,也可以是表达式:if-end 包裹的内容为条件为真的时候展示。与 if 语句一样,模板也可以有 else 语句。

func templateHandler(w http.ResponseWriter, r *http.Request) {t, _ := template.ParseFiles("templates/layout.html")rand.Seed(time.Now().Unix())t.ExecuteTemplate(w, "layout", rand.Intn(10) > 5)
}

layout.html 文件

{{ define "layout" }}
<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>layout</title></head><body><h3>This is layout</h3>template data: {{ . }}{{ if . }}Number is greater than 5!{{ else }}Number is 5 or less!{{ end }}</body>
</html>
{{ end }}

此时就能看见,当 . 的值为 true 的时候显示 if 的逻辑,否则显示 else 的逻辑。

迭代

对于一些数组,切片或者是 map,可以使用迭代的 action,与 Go 的迭代类似,使用 range 进行处理:

func templateHandler(w http.ResponseWriter, r *http.Request) {t := template.Must(template.ParseFiles("templates/layout.html"))daysOfWeek := []string{"Mon", "Tue", "Wed", "Ths", "Fri", "Sat", "Sun"}t.ExecuteTemplate(w, "layout", daysOfWeek)
}

layout.html 文件

{{ define "layout" }}
<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>layout</title></head><body><h3>This is layout</h3>template data: {{ . }}{{ range . }}<li>{{ . }}</li>{{ end }}</body>
</html>
{{ end }}

可以看见输出了一堆 li 列表。迭代的时候,还可以使用 $ 设置循环变量:

{{ range $key, $value := . }}<li>key: {{ $key }}, value: {{ $value }}</li>
{{ else }}empty
{{ end }}

可以看见和迭代切片很像。range 也可以使用 else 语句:

func templateHandler(w http.ResponseWriter, r *http.Request) {t := template.Must(template.ParseFiles("templates/layout.html"))daysOfWeek := []string{}t.ExecuteTemplate(w, "layout", daysOfWeek)
}

layout.html 部分内容

{{ range . }}<li>{{ . }}</li>
{{ else }}empty
{{ end }}

当 range 的结构为空的时候,则会执行 else 分支的逻辑。

with封装

with 语言在 Python 中可以开启一个上下文环境。对于 Go 模板,with 语句类似,其含义就是创建一个封闭的作用域,在其范围内,可以使用 . action,而与外面的 . 无关,只与 with 的参数有关:

{{ with arg }}
    此时的点 . 就是arg
{{ end }}

{{ define "layout" }}
<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>layout</title></head><body><h3>This is layout</h3>template data: {{ . }}{{ with "world"}}Now the dot is set to {{ . }}{{ end }}</body>
</html>
{{ end }}

访问结果如下:

$ curl http://127.0.0.1:8000/<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>layout</title></head><body><h3>This is layout</h3>template data: [Mon Tue Wed Ths Fri Sat Sun]Now the dot is set to world</body>
</html>

可见 with 语句的 . 与其外面的 . 是两个不相关的对象。with 语句也可以有 else。else 中的 . 则和 with 外面的 . 一样,毕竟只有 with 语句内才有封闭的上下文:

{{ with ""}}Now the dot is set to {{ . }}
{{ else }}{{ . }}
{{ end }}

访问效果为:

$ curl http://127.0.0.1:8000/<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>layout</title></head><body><h3>This is layout</h3>template data: [Mon Tue Wed Ths Fri Sat Sun][Mon Tue Wed Ths Fri Sat Sun]</body>
</html>

引用

我们已经介绍了模板嵌套引用的技巧。引用除了模板的 include,还包括参数的传递。

func templateHandler(w http.ResponseWriter, r *http.Request) {t := template.Must(template.ParseFiles("templates/layout.html", "templates/index.html"))daysOfWeek := []string{"Mon", "Tue", "Wed", "Ths", "Fri", "Sat", "Sun"}t.ExecuteTemplate(w, "layout", daysOfWeek)
}

修改 layout.html, layout 中引用了 index 模板:

{{ define "layout" }}
<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>layout</title></head><body><h3>This is layout</h3>layout template data: ({{ . }}){{ template "index" }}</body>
</html>
{{ end }}

index.html模板的内容也打印了 .:

{{ define "index" }}<div style="background: yellow">this is index.html ({{ . }})
</div>{{ end }}

访问的效果如下,index.html 中的点并没有数据。

$ curl http://127.0.0.1:8000/<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>layout</title></head><body><h3>This is layout</h3>layout template data: ([Mon Tue Wed Ths Fri Sat Sun])<div style="background: yellow">this is index.html ()
</div></body>
</html>

我们可以修改引用语句 {{ template "index" . }},把参数传给子模板,再次访问,就能看见 index.html 模板也有数据啦。

<div style="background: yellow">this is index.html ([Mon Tue Wed Ths Fri Sat Sun])
</div>

参数,变量和管道

模板的参数可以是go中的基本数据类型,如字串,数字,布尔值,数组切片或者一个结构体。在模板中设置变量可以使用 $variable := value。我们在 range 迭代的过程使用了设置变量的方式。

Go 还有一个特性就是模板的管道函数,熟悉 django 和 jinja 的开发者应该很熟悉这种手法。通过定义函数过滤器,实现模板的一些简单格式化处理。并且通过管道哲学,这样的处理方式可以连成一起。

{{ p1 | p2 | p3 }}

例如 模板内置了一些函数,比如格式化输出:

{{ 12.3456 | printf "%.2f" }}

函数

既然管道符可以成为模板中的过滤器,那么除了内建的函数,能够自定义函数可以扩展模板的功能。幸好 Go 的模板提供了自定义模板函数的功能。

想要创建一个定义函数只需要两步:

  1. 创建一个 FuncMap 类型的 map,key 是模板函数的名字,value 是其函数的定义。
  2. 将 FuncMap 注入到模板中。
func templateHandler(w http.ResponseWriter, r *http.Request) {funcMap := template.FuncMap{"fdate": formDate}t := template.New("layout").Funcs(funcMap)t = template.Must(t.ParseFiles("templates/layout.html", "templates/index.html"))t.ExecuteTemplate(w, "layout", time.Now())
}

然后在模板中使用 {{ . | fdate }},当然也可以不适用管道过滤器,而是使用正常的函数调用形式,{{ fdate . }} 。

注意,函数的注入,必须要在 parseFiles 之前,因为解析模板的时候,需要先把函数编译注入。

智能上下文

上面所介绍的特性,基本上是大多数模板引擎都具有的功能。Go 还提供了一个更有意思的特性。那就是根据上下文显示模板的内容。例如字符的转义,会根据所显示的上下文环境而智能变化。比如同样的 html 标签,在 Js 和 html 环境中,其转义的内容是不一样的:

func templateHandler(w http.ResponseWriter, r *http.Request) {t, _ := template.ParseFiles("templates/layout.html")content := `I asked: <i>What's up?</i>`t.ExecuteTemplate(w, "layout", content)
}

模板文件:

{{ define "layout" }}
<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>layout</title></head><body><h3>This is layout</h3>layout template data: ({{ . }})<div><a href="/{{ . }}">Path</a></div><div><a href="/?q={{ . }}">Query</a></div><div><a οnclick="f('{{ . }}')">Onclick</a></div></body>
</html>
{{ end }}

访问结果

layout template data: (I asked: <i>What's up?</i>)<div><a href="/I%20asked:%20%3ci%3eWhat%27s%20up?%3c/i%3e">Path</a></div><div><a href="/?q=I%20asked%3a%20%3ci%3eWhat%27s%20up%3f%3c%2fi%3e">Query</a></div><div><a οnclick="f('I asked: \x3ci\x3eWhat\x27s up?\x3c\/i\x3e')">Onclick</a></div>

可以看见 Go 会自动为我们处理 html 标签的转义。这对 web 安全具有重要作用。避免了一些 XSS 攻击。

XSS安全

安全是一个很大的话题,XSS 安全也包含很多内容,关于模板我们已经介绍了很多内容。XSS 安全就简单介绍一下即可。

XSS 主要分为三种,我们先测试其中一种。即通过提交待 script 标签的内容执行 js。例如下面的 html

layout.html 加一个表单

<form action="/" method="post">Comment: <input name="comment" type="text"><hr/><button id="submit">Submit</button>
</form>

一个最普通不过的表单。Go 的处理函数为:

func templateHandler(w http.ResponseWriter, r *http.Request) {t, _ := template.ParseFiles("templates/layout.html")t.ExecuteTemplate(w, "layout", r.FormValue("comment"))
}

提交一段 js,可以看到 Go 在表达处理的时候,自动帮我们做了 xss 过滤

当然,如果不想转义标签,需要使用 template.HTML 方法包裹:

func templateHandler(w http.ResponseWriter, r *http.Request) {w.Header().Set("X-XSS-Protection", "0")t, _ := template.ParseFiles("templates/layout.html")t.ExecuteTemplate(w, "layout", template.HTML(r.FormValue("comment")))
}

开发者尤其要注意 XSS 的安全处理,然而 XSS 原不是这么简单,更多的内容请阅读安全相关的资料。

 


 

补充

显示 字典 数据

package main
import ("fmt""html/template""net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {t, _ := template.ParseFiles("index.html")err := t.Execute(w, map[string]string{"Title": "My title", "Body": "Hi this is my body"})if err != nil {panic(err)}
}
func main() {http.HandleFunc("/", handler)http.ListenAndServe(":8080", nil)
}

index.html

Title is {{.Title}}

 


 

遇到的问题

// testtmpl.go
type UserInfo struct {Name string
}func main() {t := template.New("My Reporter")t, err := t.ParseFiles("views/report.html")if err != nil {fmt.Println("parse error")return}err = t.Execute(os.Stdout, UserInfo{Name: "tonybai"})if err != nil {fmt.Println("exec error", err)}return
}

执行结果,报错:

go run testtmpl.go
exec error template: My Reporter: "My Reporter" is an incomplete or empty template; defined templates are: "report.html"

看起来似乎 template 对象与模板名字对不上导致的错误啊。修改一下:

t := template.New("report.html")

执行结果:

<html>
<head>
</head>
<body>Hello, tonybai
</body>
</html>

这回对了,看来 template 的名字在与 ParseFiles 一起使用时不是随意取的,务必要与模板文件名字相同。

ParseFiles 支持解析多个文件,如果是传入多个文件该咋办?godoc 说了,template 名字与第一个文件名相同即可。

 

 

参考:

http://www.jianshu.com/p/05671bab2357

[鸟窝]Go 模板嵌套最佳实践

[Tony Bai]近期遇到的3个Golang代码问题

转载于:https://www.cnblogs.com/52php/p/6412554.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/456425.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内存泄露监测

2019独角兽企业重金招聘Python工程师标准>>> iOS 内存泄露监测 144 作者 谢谢生活 已关注 2017.05.19 17:38* 字数 4235 阅读 209评论 0喜欢 6 iOS可能存在的内存泄露&#xff1a;block 循环引用。当一个对象有一个block属性&#xff0c;而block属性又引用这个对象…

玩Azkaban跳过的坑

文章目录一号坑&#xff1a;启动Azkaban报错&#xff1a;User xml file conf/azkaban-users.xml doesnt exist.二号坑&#xff1a;报错&#xff1a;failed SslSocketConnector0.0.0.0:8443: java.io.FileNotFoundException: /home/hadoop/app/azkaban/azkaban-web-2.5.0/bin/ke…

删除节点removeChild()

http://www.imooc.com/code/1700 删除节点removeChild() removeChild() 方法从子节点列表中删除某个节点。如删除成功&#xff0c;此方法可返回被删除的节点&#xff0c;如失败&#xff0c;则返回 NULL。 语法: nodeObject.removeChild(node) 参数: node &#xff1a;必需&…

机器学习自主解决安全威胁离我们还有多远?

曾经听见不止一次这样的问题&#xff1a; “机器学习会替代基于人工经验规则的安全解决方案么&#xff1f;”把这个问题放在去年来看&#xff0c;我们已经得到了非常多的讨论甚至是一些已经实际应用的解决方案&#xff0c;对于人工智能在安全以及其它各种对数据进行价值挖掘的场…

Vue:解决[Vue warn]: Failed to resolve directive: modle (found in Anonymous)

解决问题 [Vue warn]: Failed to resolve directive: modle (found in <ComponentA>) console.error(("[Vue warn]: " msg trace)); 原因是 我把model 写成了 modle 这类错误一般是单词写错了 (found in <Anonymous>) 解决思路

一行Python代码制作动态二维码

目录 1、普通二维码 2、艺术二维码 3、动态二维码 在GitHub上发现了一个比较有意思的项目&#xff0c;只需要一行Python代码就可以快捷方便生成普通二维码、艺术二维码(黑白/彩色)和动态GIF二维码。 GitHub网站参加&#xff1a;https://github.com/sylnsfar/qrcode 用法比…

Vue常用经典开源项目汇总参考-海量

Vue常用经典开源项目汇总参考-海量 Vue是什么&#xff1f; Vue.js&#xff08;读音 /vjuː/, 类似于 view&#xff09; 是一套构建用户界面的 渐进式框架。与其他重量级框架不同的是&#xff0c;Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层&#xff0c;并且非常…

Pycharm常用高效技巧总结

文章目录1、PyCharm如何自动生成函数注释2、pycharm运行程序时在Python console窗口中运行3、Pycharm在创建py文件时,如何自动添加文件头注释4、Pycharm配置远程调试5、pycharm同一目录下无法import明明已经存在的.py文件1、PyCharm如何自动生成函数注释 一般在函数def()行下敲…

EntityFramework中常用的数据删除方式

最近在学EF&#xff0c;目前了解到删除操作有三种方式&#xff0c; 第一&#xff0c;官方推荐的先查询数据&#xff0c;再根据查询的对象&#xff0c;删除对象。 这是第一种&#xff0c;官方推荐 第二&#xff0c;自己创建一个对象&#xff0c;然后附加&#xff0c;然后删除。 …

Elasticsearch的前后台运行与停止(tar包方式)

备注&#xff1a;在生产环境中&#xff0c;往往一般用后台来运行。jps查看。 1、ES的前台运行 [hadoopdjt002 elasticsearch-2.4.3]$ pwd/usr/local/elasticsearch/elasticsearch-2.4.3[hadoopdjt002 elasticsearch-2.4.3]$ bin/elasticsearch 2、ES的后台运行 [hadoopdjt002 e…

解决pycharm运行Flask指定ip、端口更改无效

后来查了一下官网文档&#xff0c;原来Flask 1.0 版本不再支持之前的FLASK_ENV 环境变量了。 Prior to Flask 1.0 the FLASK_ENV environment variable was not supported and you needed to enable debug mode by exporting FLASK_DEBUG1. This can still be used to control…

Android中SimpleAdapter的使用—自定义列表

本人初学Android&#xff0c;今天研究到Adapter这块感觉挺有意思的&#xff0c;写了个自定义列表进行测试 首先我们新建一个layout列表布局文件&#xff0c;具体布局可以自己设定。 下面贴上我的自定义布局文件代码 1 <?xml version"1.0" encoding"utf-8&qu…

linux lvm扩容

linux lvm扩容 LVM磁盘管理 一、LVM简介... 1 二、 LVM基本术语... 2 三、 安装LVM... 3 四、 创建和管理LVM... 4 2、 创建PV.. 6 3、 创建VG.. 7 4、 创建LV.. 9 5、LV格式化及挂载... 10 一、LVM简介 LVM是 Logical Volume Manager(逻辑卷管理)的简写&#xff0c;它由Heinz …

Python基础常见面试题总结

文章目录基础知识题看程序写结果题编程题以下是总结的一些常见的Python基础面试题&#xff0c;帮助大家回顾基础知识&#xff0c;了解面试套路。会一直保持更新状态。PS&#xff1a;加粗为需要注意的点。基础知识题 1、深拷贝和浅拷贝的区别是什么&#xff1f; 深拷贝是将对象…

Flask-Script扩展命令行manager = Manager(app)

通过使用Flask-Script扩展&#xff0c;我们可以在Flask服务器启动的时候&#xff0c;通过命令行的方式传入参数。而不仅仅通过app.run()方法中传参&#xff0c;比如我们可以通过python hello.py runserver --host ip地址&#xff0c;告诉服务器在哪个网络接口监听来自客户端的连…

Python基础总结之常用内置方法总结

文章目录前言1、str1.1、内置方法&#xff1a;1.2、常用的内置方法1.3、String模块的一些方法2、list2.1、内置方法2.2、常用内置方法3、tupple3.1、内置方法3.2、常用内置方法4、dict4.1、内置方法4.2、常用内置方法5、其他5.1、几个sort的使用5.2、enumerate&#xff08;&…

线程的条件变量实例

情景1&#xff1a;Jack开着一辆出租车来到一个网站停车。看见没人就走了。过段时间。Susan来到网站准备乘车。可是没有来&#xff0c;于是就等着。过了一会Mike开着车来到了这个网站&#xff0c;Sunsan就上了Mike的车走了。如图所看到的&#xff1a;程序实现该情景&#xff1a;…

浅谈互联网寒冬与经济形势

文章目录前言&#xff1a;闲扯总结&#xff1a;前言&#xff1a; 作为刚进入职场一年多的小白来说&#xff0c;刚准备“猥琐发育涨经验”&#xff0c;却碰到这股互联网寒冬&#xff0c;也感到鸭梨山大。也许有人认为我在贩卖焦虑&#xff0c;但是现实真的很严峻。接下说下过去…

Java集合---LinkedList源码解析

一、源码解析1、 LinkedList类定义2、LinkedList数据结构原理3、私有属性4、构造方法5、元素添加add()及原理6、删除数据remove()7、数据获取get()8、数据复制clone()与toArray()9、遍历数据&#xff1a;Iterator()二、ListItr 一、源码解析 1、 LinkedList类定义。 public cla…

Mysql面试热身题集总结

文章目录前言1、热身题实践其他前言 一直有个想法&#xff1a;把面试需要的知识点全都总结一下&#xff0c;包括数据库&#xff0c;语言&#xff0c;算法&#xff0c;数据结构等知识&#xff0c;形成一个面试总结笔记&#xff0c;这样以后面试的时候只看这些文章回顾下就行了。…