模板语法

news2024/11/15 22:59:45

模板语法

{{.}}

模板语法都包含在 {{}} 中间,其中{{ . }}中的点表示当前对象。
当传入一个结构体对象时,可以根据 . 来访问结构体的对应字段。
当传入的变量是map时,也可以在模板文件中通过 . 根据key来取值。

main.go

package main

import (
	"fmt"
	"net/http"
	"text/template"
)

type User struct {
	// 如果字段的首字母大写,则该字段是导出的(public),可以在结构体外部访问
	// 如果字段的首字母小写,则该字段是非导出的(private),只能在同一个包内访问
	Name   string
	Gender string
	Age    int
}

func sayHello(w http.ResponseWriter, r *http.Request) {
	// 解析指定文件生成模板对象
	t, err := template.ParseFiles("./hello.tmpl")
	if err != nil {
		http.Error(w, "Unable to parse template", http.StatusInternalServerError)
		fmt.Printf("parse template failed, err:%v\n", err)
		return
	}

	u1 := User{
		Name:   "小王子",
		Gender: "男",
		Age:    18,
	}

	m1 := map[string]interface{}{
		"name":   "小王子",
		"gender": "男",
		"age":    18,
	}

	t.Execute(w, map[string]interface{}{
		"u1": u1,
		"m1": m1,
	})
}

func main() {
	http.HandleFunc("/", sayHello)
	err := http.ListenAndServe(":9000", nil)
	if err != nil {
		fmt.Printf("HTTP server start failed, err:%v\n", err)
		return
	}
}

模板文件 hello.tmpl

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <title>Hello</title>
</head>
<body>
<p>u1 </p>
<p>Hello {{ .u1.Name }}</p>
<p>性别: {{ .u1.Gender }}</p>
<p>年龄: {{ .u1.Age }}</p>

<p>m1</p>
<p>Hello {{ .m1.name }}</p>
<p>性别: {{ .m1.gender }}</p>
<p>年龄: {{ .m1.age }}</p>
</body>
</html>

效果

在这里插入图片描述

注释

{{/* a comment */}}
注释,执行时会忽略。可以多行。
注释不能嵌套,并且必须紧贴分界符始止。

pipeline

pipeline是指产生数据的操作。比如 {{.}}{{.Name}} 等。
Go的模板语法中支持使用管道符号|链接多个命令,用法和Unix下的管道类似:| 前面的命令会将运算结果(或返回值)传递给后一个命令的最后一个位置。

注意:
并不是只有使用了 | 才是pipeline。
Go的模板语法中,pipeline的概念是传递数据,只要能产生数据的,都是pipeline。

变量

还可以在模板中声明变量,用来保存传入模板的数据或其他语句生成的结果。具体语法如下:

$obj := {{ . }}

$obj 是变量的名字,在后续的代码中就可以使用该变量了。

移除空格

有时候在使用模板语法的时候会不可避免的引入一下空格或者换行符,这样模板最终渲染出来的内容可能就和想的不一样,这个时候可以:

  • 使用 {{- 语法去除模板内容左侧的所有空白符号,
  • 使用 -}} 去除模板内容右侧的所有空白符号。

例如:

{{- .Name -}}

注意:
- 要紧挨 {{}},同时与模板值之间需要使用空格分隔。

条件判断

Go模板语法中的条件判断有以下几种:

{{if pipeline}} T1 {{end}}

{{if pipeline}} T1 {{else}} T0 {{end}}

{{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
{{ if lt .m1.age 22}}
好好上学
{{else}}
好好工作
{{end}}

range

Go的模板语法中使用 range 关键字进行遍历,有以下两种写法,其中 pipeline 的值必须是数组、切片、字典或者通道。

{{range pipeline}} T1 {{end}}
// 如果pipeline的值其长度为0,不会有任何输出

{{range pipeline}} T1 {{else}} T0 {{end}}
// 如果pipeline的值其长度为0,则会执行T0。
{{ range $idx,$hobby := .hobby }}
    <p>{{$idx}} - {{$hobby}}</p>
{{else}}
    没啥爱好
{{end}}

with

with 可以引导一块局部的作用域

{{with pipeline}} T1 {{end}}
// 如果pipeline为empty不产生输出,否则将dot设为pipeline的值并执行T1。不修改外面的dot。

{{with pipeline}} T1 {{else}} T0 {{end}}
// 如果pipeline为empty,不改变dot并执行T0,否则dot设为pipeline的值并执行T1。
<p>m1</p> 
{{with .m1}}
<p>{{ .name }}</p>
<p>{{ .age }}</p>
<p>{{ .gender }}</p>
{{end}}

预定义函数

执行模板时,函数从两个函数字典中查找:首先是模板函数字典,然后是全局函数字典。一般不在模板内定义函数,而是使用Funcs方法添加函数到模板里。

预定义的全局函数如下:

  • and

    函数返回它的第一个empty参数或者最后一个参数;
    就是说"and x y"等价于"if x then y else x";所有参数都会执行;

  • or
    返回第一个非empty参数或者最后一个参数;
    亦即"or x y"等价于"if x then x else y";所有参数都会执行;

  • not
    返回它的单个参数的布尔值的否定

  • len
    返回它的参数的整数类型长度

  • index
    执行结果为第一个参数以剩下的参数为索引/键指向的值;
    如"index x 1 2 3"返回x[1][2][3]的值;每个被索引的主体必须是数组、切片或者字典。

  • print
    即fmt.Sprint

  • printf
    即fmt.Sprintf

  • println
    即fmt.Sprintln

  • html
    返回与其参数的文本表示形式等效的转义HTML。
    这个函数在html/template中不可用。

  • urlquery
    以适合嵌入到网址查询中的形式返回其参数的文本表示的转义值。
    这个函数在html/template中不可用。

  • js
    返回与其参数的文本表示形式等效的转义JavaScript。

  • call
    执行结果是调用第一个参数的返回值,该参数必须是函数类型,其余参数作为调用该函数的参数;
    如"call .X.Y 1 2"等价于go语言里的dot.X.Y(1, 2);
    其中Y是函数类型的字段或者字典的值,或者其他类似情况;
    call的第一个参数的执行结果必须是函数类型的值(和预定义函数如print明显不同);
    该函数类型值必须有1到2个返回值,如果有2个则后一个必须是error接口类型;
    如果有2个返回值的方法返回的error非nil,模板执行会中断并返回给调用模板执行者该错误;

比较函数

布尔函数会将任何类型的零值视为假,其余视为真。

下面是定义为函数的二元比较运算的集合:

  • eq 如果 arg1 == arg2 则返回真
  • ne 如果 arg1 != arg2 则返回真
  • lt 如果 arg1 < arg2 则返回真
  • le 如果 arg1 <= arg2 则返回真
  • gt 如果 arg1 > arg2 则返回真
  • ge 如果 arg1 >= arg2 则返回真

为了简化多参数相等检测,eq(只有eq)可以接受2个或更多个参数,它会将第一个参数和其余参数依次比较,返回下式的结果:

{{ eq arg1 arg2 arg3 }}

比较函数只适用于基本类型(或重定义的基本类型,如"type Celsius float32")。但是,整数和浮点数不能互相比较。

自定义函数

main.go

package main

import (
	"fmt"
	"html/template"
	"net/http"
)

func f1(w http.ResponseWriter, r *http.Request) {
	// 定义一个函数kua
	// 要么只有一个返回值,要么有两个返回值,第二个返回值必须是error类型
	k := func(name string) (string, error) {
		return name + "年轻又帅气!", nil
	}
	// 定义模板 f.tmpl
	t := template.New("f.tmpl") // 创建一个模板对象, 名字一定要与模板的名字对应上
	// 告诉模板引擎,现在多了一个自定义的函数kua
	t.Funcs(template.FuncMap{
		"kua": k,
	})
	// 解析模板
	_, err := t.ParseFiles("./f.tmpl")
	if err != nil {
		fmt.Printf("parse temple failed, err:%v\n", err)
		return
	}
	name := "小王子"
	// 渲染模板
	t.Execute(w, name)
}

func main() {
	http.HandleFunc("/", f1)
	err := http.ListenAndServe(":9000", nil)
	if err != nil {
		fmt.Printf("HTTP server start failed, err:%v\n", err)
		return
	}
}

f.tmpl

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <title>自定义模板函数</title>
</head>
<body>
    {{ kua . }}
</body>
</html>

嵌套template

可以在template中嵌套其他的template。这个template可以是单独的文件,也可以是通过define定义的template。

main.go

package main

import (
	"fmt"
	"html/template"
	"net/http"
)

func f1(w http.ResponseWriter, r *http.Request) {
	// 定义一个函数kua
	// 要么只有一个返回值,要么有两个返回值,第二个返回值必须是error类型
	k := func(name string) (string, error) {
		return name + "年轻又帅气!", nil
	}
	// 定义模板 f.tmpl
	t := template.New("f.tmpl") // 创建一个模板对象, 名字一定要与模板的名字对应上
	// 告诉模板引擎,现在多了一个自定义的函数kua
	t.Funcs(template.FuncMap{
		"kua": k,
	})
	// 解析模板
	_, err := t.ParseFiles("./f.tmpl")
	if err != nil {
		fmt.Printf("parse temple failed, err:%v\n", err)
		return
	}
	name := "小王子"
	// 渲染模板
	t.Execute(w, name)
}

func demo1(w http.ResponseWriter, r *http.Request) {
	// 定义模板
	// 解析模板
	// 在解析模板时,被嵌套的模板一定要在后面解析
	// t.tmpl模板中嵌套了ul.tmpl,所以ul.tmpl要在t.tmpl后进行解析
	t, err := template.ParseFiles("./t.tmpl", "./ul.tmpl")
	if err != nil {
		fmt.Printf("parse temple failed, err:%v\n", err)
	}
	name := "小王子"
	// 渲染模板
	t.Execute(w, name)
}

func main() {
	http.HandleFunc("/", f1)
	// 注册一个demo1路由处理函数
	http.HandleFunc("/tmplDemo", demo1)
	err := http.ListenAndServe(":9000", nil)
	if err != nil {
		fmt.Printf("HTTP server start failed, err:%v\n", err)
		return
	}
}

t.tmpl

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>tmpl test</title>
</head>
<body>

<h1>测试嵌套template语法</h1>
<hr>
{{/* 嵌套了另外一个单独的模板文件 */}}
{{template "ul.tmpl"}}
<hr>
{{/* 嵌套另外一个define定义的模板 */}}
{{template "ol.tmpl"}}

<div>你好,{{ . }}</div>
</body>
</html>
{{/* 通过define定义一个模板 */}}
{{ define "ol.tmpl"}}
    <ol>
        <li>吃饭</li>
        <li>睡觉</li>
        <li>打豆豆</li>
    </ol>
{{end}}

ul.tmpl

<ul>
    <li>注释</li>
    <li>日志</li>
    <li>测试</li>
</ul>

效果

在这里插入图片描述

block

{{block "name" pipeline}} T1 {{end}}

block 是定义模板{{define "name"}} T1 {{end}} 和执行 {{template "name" pipeline}} 缩写,典型的用法是定义一组根模板,然后通过在其中重新定义块模板进行自定义。

main.go

package main

import (
	"fmt"
	"net/http"
	"text/template"
)

func index(w http.ResponseWriter, r *http.Request) {
	// 定义模板(模板继承的方式)
	// 解析模板
	t, err := template.ParseFiles("./templates/base.tmpl", "./templates/index.tmpl")
	if err != nil {
		fmt.Printf("parse template failed, err:%v\n", err)
		return
	}
	// 渲染模板
	name := "小王子"
	t.ExecuteTemplate(w, "index.tmpl", name)
}

func home(w http.ResponseWriter, r *http.Request) {
	// 定义模板(模板继承的方式)
	// 解析模板
	t, err := template.ParseFiles("./templates/base.tmpl", "./templates/home.tmpl")
	if err != nil {
		fmt.Printf("parse template failed, err:%v\n", err)
		return
	}
	// 渲染模板
	name := "七米"
	t.ExecuteTemplate(w, "home.tmpl", name)
}
func main() {
	http.HandleFunc("/index", index)
	http.HandleFunc("/home", home)
	err := http.ListenAndServe(":9000", nil)
	if err != nil {
		fmt.Printf("HTTP server start failed, err:%v\n", err)
		return
	}
}

templates

在这里插入图片描述

base.tmpl

<!DOCTYPE html>
<html lang="zh-CN">
<head>

    <title>模板继承</title>
    <style>
        * {
            margin: 0;
        }
        .nav {
            height: 50px;
            width: 100%;
            position: fixed;
            top: 0;
            background-color: burlywood;
        }
        .main {
            margin-top: 50px;
        }
        .menu {
            width: 20%;
            height: 100%;
            position: fixed;
            left: 0;
            background-color: cornflowerblue;
        }
        .center {
            text-align: center;
        }
    </style>
</head>
<body>

<div class="nav"></div>
<div class="main">
    <div class="menu"></div>
    <div class="content center" >
        {{block "content" .}}{{end}}
    </div>
</div>
</body>
</html>

home.tmpl

{{/*继承根模板*/}}
{{template "base.tmpl" .}}
{{/*重新定义块模板*/}}
{{define "content"}}
    <h1>这是home页面</h1>
    <p>Hello {{.}}</p>
{{end}}

index.tmpl

{{/*继承根模板*/}}
{{template "base.tmpl" .}}
{{/*重新定义块模板*/}}
{{define "content"}}
    <h1>这是index页面</h1>
    <p>Hello {{.}}</p>
{{end}}

效果

在这里插入图片描述
在这里插入图片描述

修改默认的标识符

Go标准库的模板引擎使用的花括号 {{}} 作为标识,而许多前端框架(如 VueAngular JS)也使用 {{}} 作为标识符,所以当同时使用Go语言模板引擎和以上前端框架时就会出现冲突,这个时候需要修改标识符,修改前端的或者修改Go语言的。这里演示如何修改Go语言模板引擎默认的标识符:

template.New("test").Delims("{[", "]}").ParseFiles("./t.tmpl")

main.go

package main

import (
	"fmt"
	"net/http"
	"text/template"
)

func index(w http.ResponseWriter, r *http.Request) {
	// 定义模板
	// 解析模板
	t, err := template.New("index.tmpl").
		Delims("{[", "]}").
		ParseFiles("./index.tmpl")
	if err != nil {
		fmt.Printf("parse template fail, err:%v\n", err)
		return
	}
	// 渲染模板
	name := "小王子"
	err = t.Execute(w, name)
	if err != nil {
		fmt.Printf("execute template fail, err:%v\n", err)
	}

}

func main() {
	http.HandleFunc("/index", index)
	err := http.ListenAndServe(":9000", nil)
	if err != nil {
		fmt.Printf("HTTP server start failed, err:%v\n", err)
		return
	}
}

index.tmpl

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <title>修改模板引擎的标识符</title>
</head>
<body>
<div>Hello {[ . ]}</div>
</body>
</html>

效果

在这里插入图片描述

text/template 与 html/tempalte 的区别

html/template 针对的是需要返回HTML内容的场景,在模板渲染过程中会对一些有风险的内容进行转义,以此来防范跨站脚本攻击。

定义模板文件 xss.tmpl

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>xss</title>
</head>
<body>
用户的评论是:{{.}}
</body>
</html>

使用 html/template 渲染模板

这个时候传入一段JS代码并使用 html/template 去渲染该文件,会在页面上显示出转义后的JS内容。 <script>alert(123);</script> 这就是 html/template 做的事。

  • 效果
    在这里插入图片描述

自定义函数 safe

不想转义的话,可以自行编写一个safe函数,手动返回一个 template.HTML 类型的内容。

main.go

package main

import (
	"fmt"
	"html/template"
	"net/http"
)

func xss(w http.ResponseWriter, r *http.Request) {
	// 定义模板
	// 解析模板
	// 解析模板之前定义一个自定义的函数safe
	t, err := template.New("xss.tmpl").Funcs(template.FuncMap{
		"safe": func(str string) template.HTML {
			return template.HTML(str)
		},
	}).ParseFiles("./xss.tmpl")
	if err != nil {
		fmt.Printf("parse template fail, err:%v\n", err)
		return
	}
	// 渲染模板
	str1 := "<script>alert(123);</script>"
	str2 := "<a href='http://liwenzhou.com'>liwenzhou的博客</a>"
	err = t.Execute(w, map[string]interface{}{
		"str1": str1,
		"str2": str2,
	})
}

func main() {
	http.HandleFunc("/xss", xss)
	err := http.ListenAndServe(":9000", nil)
	if err != nil {
		fmt.Printf("HTTP server start failed, err:%v\n", err)
		return
	}
}

xss.tmpl

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>xss</title>
</head>
<body>
用户的评论是:{{.str1}}
用户的评论是:{{.str2 | safe}}
</body>
</html>

效果

·

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

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

相关文章

S3C2440 ARM设备驱动(boot loader,kernel,rootfs)

一、开发板Linux启动需求 1、bootloader 为内核启动准备环境&#xff0c;并引导内核启动 2、kernel&#xff08;linux内核&#xff09; 操作系统的核心&#xff0c;&#xff08;狭义上的操作系统&#xff09; 3、rootfs 一堆有组织的文件 1. bootloader(一个裸机程序) 初始化C…

【MM24】【水下目标分割】Dual_SAM

论文&#xff1a;https://arxiv.org/abs/2404.04996 代码&#xff1a;https://github.com/Drchip61/Dual_SAM 点评 这篇文章介绍的改进SAM,面向海洋生物的分割。但是海洋图像易受噪声影响&#xff0c;论文中仅是通过一个gamma变换减弱了这种影响。双主干网络的参数量并没有提及…

2.队列和队列集

队列的本质就是环形buff,加了互斥操作,加了阻塞-唤醒. 1.介绍一下环形BUFF 2.阻塞和唤醒 在我们队列中是有一个读list 链表 和 一个写list链表 他们就是用来保存 读 或者 写阻塞 的任务 假设我们 就绪链表中有A 和 B两个任务 他们正常情况下都是轮流运行, 这个时候 A 想读队…

IDEA中集成Git及Github

我的博客大纲 我的GIT学习大纲 1、IDEA中集成Git 1.1.设置IDEA忽略一些文件&#xff1a; a.为什么要忽略一些文件 1.在将项目推送之前&#xff0c;有一些文件是可以忽略的&#xff0c;忽略这些文件与实际功能无关&#xff0c;不参与服务器上部署运行&#xff0c;把他们忽略掉…

【DCL】Dual Contrastive Learning for General Face Forgery Detection

文章目录 Dual Contrastive Learning for General Face Forgery Detectionkey points:贡献方法数据视图生成对比学习架构实例间对比学习实例内对比学习总损失函数实验实验细节定量结果跨数据集评估跨操作评估消融实验可视化Dual Contrastive Learning for General Face Forgery…

HarmonyOS开发5.0【封装request泛型方法】axios

一 准备工作 1. 先开启一下虚拟机的权限 src/main/module.json5 打开module.json5在15~19行 进行配置网络权限 2. 在终端下载安装一下 ohpm install ohos/axios 复制 粘贴进去回车就行 3. 这样显示就是安装好了 如果导入不行就关了重新启动 二 创建一个ETS文件&#xff0c;…

后端开发刷题 | 矩阵的最小路径和

描述 给定一个 n * m 的矩阵 a&#xff0c;从左上角开始每次只能向右或者向下走&#xff0c;最后到达右下角的位置&#xff0c;路径上所有的数字累加起来就是路径和&#xff0c;输出所有的路径中最小的路径和。 数据范围: 1≤n,m≤500&#xff0c;矩阵中任意值都满足 0≤ai,j…

Linux系统:cd命令

1、命令详解&#xff1a; cd命令用于改变当前工作目录的命令&#xff0c;切换到指定的路径&#xff0c;全称为change directory&#xff0c;若目录名称省略&#xff0c;则默认变换至使用者的 home 目录。 2、官方参数&#xff1a; 选项&#xff1a;-L 强制遵循符号链接-P 使用…

基于RFID技术的光交箱哑资源智能化管理方案

一、现状 &#xff08;一&#xff09;现状与挑战 在当前通信网络基础设施中&#xff0c;哑资源如光缆接头、跳线等在网络中占据着重要地位。然而&#xff0c;传统的哑资源管理方式存在诸多问题&#xff0c;一方面&#xff0c;管理主要依赖人工记录和定期巡检&#xff0c;效率…

每日OJ_牛客_合唱团(打家劫舍dp)

目录 牛客_合唱团&#xff08;打家劫舍dp&#xff09; 解析代码1 解析代码2 牛客_合唱团&#xff08;打家劫舍dp&#xff09; 合唱团__牛客网 有 n 个学生站成一排&#xff0c;每个学生有一个能力值&#xff0c;牛牛想从这 n 个学生中按照顺序选取 k 名学生&#xff0c;要求…

MongoDB高可用和分片集群知识

一、MongoDB实现高可用 1. MongoDB复制集(Replication Set) 在实际生产中&#xff0c;MongoDB要实现高可用&#xff0c;以免MongoDB单实例挂了&#xff0c;服务不可用。MongoDB实现高可用是以MongoDB复制集的形式实现&#xff0c;和集群部署概念相同&#xff0c;MongoDB复制集…

火柴人跑酷

运行图片&#xff1a; 这里面有三个boss&#xff0c;和各种元素属性列举一下&#xff1a; 元素作用 火 运用火元素将攻击抵消 水 和火元素一致 磁 自动吸取经验…

vscode设置vue标签不换行

1、打开 文件 --> 首选项 --> 设置 2、在设置里搜索 vetur.format&#xff0c;项较多&#xff0c;向下滑动找到 在 setting.json 中编辑 按钮 点进去 3、修改配置文件vetur.format.defaultFormatterOptions {"files.autoSave": "afterDelay","…

全网最适合入门的面向对象编程教程:47 Python函数方法与接口-回调函数Callback

全网最适合入门的面向对象编程教程&#xff1a;47 Python 函数方法与接口-回调函数 Callback 摘要&#xff1a; 回调函数是编程中一种非常常见的模式&#xff0c;用于将函数作为参数传递给其他函数或方法。这种模式在 Python 中广泛应用于事件处理、异步编程、函数式编程等场景…

cadence SPB17.4 - ORCAD - ERROR(ORCAP-1616): Reference is invalid for this part

文章目录 cadence SPB17.4 - ORCAD - ERROR(ORCAP-1616): Reference is invalid for this part概述笔记END cadence SPB17.4 - ORCAD - ERROR(ORCAP-1616): Reference is invalid for this part 概述 在抄GDLink on Board的原理图。 抄完之后进行原理图DRC, 有个元件报错。 …

C语言代码练习(第十八天)

今日练习&#xff1a; 48、猴子吃桃问题。猴子第1天摘下若干个桃子&#xff0c;当即吃了一半&#xff0c;还不过瘾&#xff0c;又多吃了一个。第2天早上又将剩下的桃子吃掉一半&#xff0c;又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时&…

digits Social Login插件 google OAuth 2.0登录 400 redirect_uri_mismatch错误解决

以下是Social Login插件google登录配置&#xff1a; 直接使用这个URI 会在登录时提示错误&#xff1a;400 redirect_uri_mismatch&#xff0c;此时需要点击错误详情把这个重定向URI设置到google中即可

Java:类和对象(2)

一 对象的构建和初始化 1.对象构建 (Object Construction) Student student1new Student("zhangsan",12,"123456"); Student student2new Student("lisi",10,"15236"); 2. 构造函数&#xff08;Constructor&#xff09; 构造函数的…

Android binder 机制驱动核心源码详解_binder_thread_read

binder 驱动中做的工作可以总结为以下几步&#xff1a; 准备数据&#xff0c;根据命令分发给具体的方法去处理找到目标进程的相关信息将数据一次拷贝到目标进程所映射的物理内存块记录待处理的任务&#xff0c;唤醒目标线程调用线程进入休眠目标进程直接拿到数据进行处理&…

maven安装依赖

这里以安装tomcat依赖为例 1, 访问maven公共仓库 2,搜索tomcat 3, 右侧点击Plugin 选择&#xff1a;Apache Tomcat Maven Plugin :: Tomcat 7.x 选择版本&#xff0c;这里我选择2.2 选择maven&#xff0c;将<dependency>中的内容copy到pom.xml中的<build>里面 …