当前位置: 首页 > news >正文

GO语言圣经 第五章习题

练习5.1

修改findlinks代码中遍历n.FirstChild链表的部分,将循环调用visit,改成递归调用。

func visit(links []string, n *html.Node) []string {if n == nil {return links}if n.Type == html.ElementNode && n.Data == "a" {for _, a := range n.Attr {if a.Key == "href" {links = append(links, a.Val)}}}links = visit(links, n.NextSibling)links = visit(links, n.FirstChild)return links
}

练习5.2

编写函数,记录在HTML树中出现的同名元素的次数。

package mainimport ("fmt""os""golang.org/x/net/html"
)type NodeCount map[string]intfunc main() {doc, err := html.Parse(os.Stdin)if err != nil {fmt.Fprintf(os.Stderr, "findlinks1: %v\n", err)os.Exit(1)}nodeCount := NodeCount{}fill(&nodeCount, doc)fmt.Printf("%v", nodeCount)
}func fill(nc *NodeCount, cn *html.Node) {if cn.Type == html.ElementNode {(*nc)[cn.Data]++}for next := cn.FirstChild; next != nil; next = next.NextSibling {fill(nc, next)}
}

练习5.3

编写函数输出所有text结点的内容。注意不要访问<script>和<style>元素,因为这些元素对浏览者是不可见的。

func getText(texts []string, n *html.Node) []string {if n.Type == html.TextNode {texts = append(texts, n.Data)}for c := n.FirstChild; c != nil; c = c.NextSibling {if c.Data == "script" || c.Data == "style" {continue}texts = getText(texts, c)}return texts
}

练习5.4

扩展visit函数,使其能够处理其他类型的结点,如images、scripts和style sheets。

func visit(links []string, n *html.Node) []string {if n.Type == html.ElementNode && (n.Data == "a" || n.Data == "img" || n.Data == "link" || n.Data == "scripts") {for _, a := range n.Attr {if a.Key == "href" {// fmt.Println(n.Data)links = append(links, a.Val)}}}for c := n.FirstChild; c != nil; c = c.NextSibling {links = visit(links, c)}return links
}

练习5.5

实现countWordsAndImages。(参考练习4.9如何分词)

func countWordsAndImages(n *html.Node) (words, images int) {texts, images := visit(nil, 0, n)for _, v := range texts {words += len(strings.Split(v, " "))v = strings.Trim(strings.TrimSpace(v), "\r\n")if v == "" {continue}words += len(strings.Split(v, " "))}return
}func visit(texts []string, imgs int, n *html.Node) ([]string, int) {if n.Type == html.TextNode {texts = append(texts, n.Data)}if n.Type == html.ElementNode && (n.Data == "img") {imgs++}for c := n.FirstChild; c != nil; c = c.NextSibling {if c.Data == "script" || c.Data == "style" {continue}texts, imgs = visit(texts, imgs, c)}return texts, imgs
}

练习5.6

修改gopl.io/ch3/surface(§3.2)中的corner函数,将返回值命名,并使用bare return。

func corner(i, j int) (sx float64, sy float64) {// Find point (x,y) at corner of cell (i,j).x := xyrange * (float64(i)/cells - 0.5)y := xyrange * (float64(j)/cells - 0.5)// Compute surface height z.z := f(x, y)// Project (x,y,z) isometrically onto 2-D SVG canvas (sx,sy).sx := width/2 + (x-y)*cos30*xyscalesy := height/2 + (x+y)*sin30*xyscale - z*zscalereturn
}

练习5.7

完善startElement和endElement函数,使其成为通用的HTML输出器。要求:输出注释结点,文本结点以及每个元素的属性(< a href=‘…’>)。使用简略格式输出没有孩子结点的元素(即用<img/>代替<img></img>)。编写测试,验证程序输出的格式正确。(详见11章)

func startElement(n *html.Node) {if n.Type == html.ElementNode {attr := ""for _, a := range n.Attr {attr += " " + a.Key + "=" + "\"" + a.Val + "\" "}fmt.Printf("%*s<%s%s", depth*2, "", n.Data, attr)depth++}if n.Type == html.ElementNode && n.FirstChild == nil && n.Data != "script" {fmt.Printf("/>\n")} else if n.Type == html.ElementNode {fmt.Printf(">\n")}if n.Type == html.TextNode {fmt.Printf("%*s %s\n", depth*2, "", n.Data)}
}
func endElement(n *html.Node) {if n.Type == html.ElementNode && n.FirstChild == nil && n.Data != "script" {depth--fmt.Printf("\n")return}if n.Type == html.ElementNode {depth--fmt.Printf("%*s</%s>\n", depth*2, "", n.Data)}
}

练习5.8

修改pre和post函数,使其返回布尔类型的返回值。返回false时,中止forEachNoded的遍历。使用修改后的代码编写ElementByID函数,根据用户输入的id查找第一个拥有该id元素的HTML元素,查找成功后,停止遍历。

func ElementByID(n *html.Node, id string) *html.Node {if n.Type == html.ElementNode {for _, a := range n.Attr {if a.Key == "id" && a.Val == id {return n}}}for c := n.FirstChild; c != nil; c = c.NextSibling {ElementByID(c, id)}return n
}

练习5.9

编写函数expand,将s中的"foo"替换为f(“foo”)的返回值。

func expand(s string, f func(string) string) string {str := f("foo")s = strings.Replace(s, "foo", str, -1)return s
}
func f(s string) string {return s + "_expand_"
}

练习5.10

重写topoSort函数,用map代替切片并移除对key的排序代码。验证结果的正确性(结果不唯一)。

func topoSort2(m map[string][]string) map[int]string {var order = make(map[int]string)index := 1seen := make(map[string]bool)var visitAll func(items []string)visitAll = func(items []string) {for _, item := range items {if !seen[item] {seen[item] = truevisitAll(m[item])order[index] = itemindex++}}}var keys []stringfor key := range m {keys = append(keys, key)}visitAll(keys)return order
}

练习5.11

博客

练习5.12

gopl.io/ch5/outline2(5.5节)的startElement和endElement共用了全局变量depth,将它们修改为匿名函数,使其共享outline中的局部变量。

func outline(url string) (string, error) {resp, err := http.Get(url)if err != nil {return "", err}doc, _ := html.Parse(resp.Body)//使用匿名函数实现var depth intvar startElement func(n *html.Node)var endElement func(n *html.Node)startElement = func (n *html.Node) {if n.Type == html.ElementNode {fmt.Printf("%*s<%s>\n", depth*2, "", n.Data)depth++}}endElement = func (n *html.Node) {if n.Type == html.ElementNode {depth--fmt.Printf("%*s</%s>\n", depth*2, "", n.Data)}}forEachNode(doc, startElement, endElement)resp.Body.Close()return "", nil
}

练习5.15

编写类似sum的可变参数函数max和min。考虑不传参时,max和min该如何处理,再编写至少接收1个参数的版本。

func max(vals ...int) (int, error) {var m int = math.NaN()if len(vals) == 0 { return m, fmt.Errorf("max: %s", "至少传递一个参数")}   for _, v := range vals {if m < v { m = v }   }   return m, nil 
}

练习5.16

编写多参数版本的strings.Join。

func join(sep string, strs ...string) string {var res stringfor i, v := range strs {if i == (len(strs) - 1) {res += v} else {res += v + sep}}return res
}

练习5.17

编写多参数版本的ElementsByTagName,函数接收一个HTML结点树以及任意数量的标签名,返回与这些标签名匹配的所有元素。

var nodes []*html.Node
func ElementsByTagName(n *html.Node, names ...string) []*html.Node {for _, name := range names {if n.Type == html.ElementNode && n.Data == name {nodes = append(nodes, n)}}for c := n.FirstChild; c != nil; c = c.NextSibling {ElementsByTagName(c, names...)}return nodes
}

练习5.18

不修改fetch的行为,重写fetch函数,要求使用defer机制关闭文件。

参考博客

func fetch(url string) (filename string, n int64, err error) {resp, err := http.Get(url)if err != nil {return "", 0, err}defer resp.Body.Close()local := path.Base(resp.Request.URL.Path)if local == "/" {local = "index.html"}f, err := os.Create(local)if err != nil {return "", 0, err}defer func() {closeErr := f.close()if err == nil {err = closeErr}}()n, err = io.Copy(f, resp.Body)return local, n, err
}

相关文章:

GO语言圣经 第五章习题

练习5.1 修改findlinks代码中遍历n.FirstChild链表的部分&#xff0c;将循环调用visit&#xff0c;改成递归调用。 func visit(links []string, n *html.Node) []string {if n nil {return links}if n.Type html.ElementNode && n.Data "a" {for _, a : r…...

用kotlin 开发一个简单的多页面跳转

本文介绍一个简单的安卓应用的页面跳转例子&#xff0c;用的是kotlin。 运行时主页面是一个hello 和Jump 按钮&#xff0c;你按一下jump 按钮就转到 从页面&#xff0c;只是标识从页面。 开始建立一个简单工程&#xff0c;名为hello&#xff0c; 选择的是Empty views Activit…...

记录我的tensorrt 部署yolov8

系统 &#xff1a;ubuntu 18.04 代码 &#xff1a;GitHub - noahmr/yolov5-tensorrt: Real-time object detection with YOLOv5 and TensorRT conda 环境 &#xff1a; GitHub - noahmr/yolov5-tensorrt: Real-time object detection with YOLOv5 and TensorRT cuda : 11.8 …...

什么是用户界面? 优漫动游

什么是用户界面&#xff1f; 用户界面(UI&#xff0c;UserInterface)也称人机界面&#xff0c;是人机交互、操作逻辑和界面表现的整体设计。每一种设计都有其对应的职业角色&#xff0c;其中&#xff0c;人机交互的设计人员叫做用户研究工程师&#xff0c;操作逻辑设计人员叫…...

基于 Docker 的 MySQL 主从复制搭建(Mac M1版本)

系统&#xff1a;Macbook M1 镜像版本&#xff1a;mysql:5.7 如果是要查 slave连接不上 master的问题&#xff0c;可以直接跳到文章末尾踩坑处 准备工作 拉取镜像 docker pull mysql:5.7本地数据卷挂载 因为mysql不挂载的话&#xff0c;重启丢失数据&#xff0c;所以在本地创…...

【Locomotor运动模块】瞬移

文章目录 一、原理二、两种类型1、Instant(立刻)2、Dash&#xff08;猛冲&#xff09; 三、瞬移区域、瞬移点1、瞬移区域2、瞬移点 一、原理 抛物线指针选择好目标位置&#xff0c;然后告诉瞬移预设体&#xff1a;你想法把游戏区域弄到目标位置来 解释&#xff1a;抛物线指针选…...

【负载均衡】常见的负载均衡策略有哪些?

文章目录 前言负载均衡分类常见负载均衡策略小结 前言 负载均衡策略是实现负载均衡器的关键&#xff0c;而负载均衡器又是分布式系统中不可或缺的重要组件。使用它有助于提高系统的整体性能、可用性、可靠性和安全性&#xff0c;同时支持系统的扩展和故障容忍性。对于处理大量…...

ChatGPT如何应对紧急救援和医疗应急?

ChatGPT在紧急救援和医疗应急方面具有潜在的重要用途。它可以用于提供信息、建议和支持&#xff0c;以帮助应对各种突发事件&#xff0c;如自然灾害、流行病爆发、事故等。以下是ChatGPT如何应对紧急救援和医疗应急的方式以及相关挑战的详细讨论。 ### 紧急救援 #### 1. 提供…...

vue3 ref reactive响应式数据 赋值的问题

文章目录 vue3 ref reactive响应式数据 赋值的问题场景1:将响应式数据赋值请求后的数据错误示范&#xff1a;直接赋值正确写法 场景2&#xff1a;响应式数据解构之后失去响应式原因分析解决办法 toRefs/toRef方法创建ref引用对象 vue3 ref reactive响应式数据 赋值的问题 doing…...

【美团秋招】20230922小美的彩虹糖

小美的彩虹糖 小美有很多的彩虹糖&#xff0c;每颗彩虹糖都有一个颜色&#xff0c;她每天可以吃两颗彩虹糖&#xff0c;如果今天吃的彩虹糖组合是之前没吃过的组合&#xff0c;则小美今天会很高兴。 例如&#xff0c;小美有 6 颗彩虹糖&#xff0c;颜色分别是 [1,1,4,5,1,4]。…...

论文阅读_扩散模型_DM

英文名称: Deep Unsupervised Learning using Nonequilibrium Thermodynamics 中文名称: 使用非平衡热力学原理的深度无监督学习 论文地址: http://arxiv.org/abs/1503.03585 代码地址: https://github.com/Sohl-Dickstein/Diffusion-Probabilistic-Models 时间: 2015-11-18 作…...

【每日运维】RockyLinux8.6升级OpenSSH9.4p1

为什么需要升级openssh呢&#xff0c;因为很多项目进行漏扫结果都会涉及到这个服务器核心组件&#xff0c;一想到以前升级openssh带来的各种依赖性问题就头疼&#xff0c;不管是什么发行版&#xff0c;升级这个东西真的很烦&#xff0c;这次发现可能还会有好一点的通用一点的升…...

libdrm全解析三十八 —— 源码全解析(35)

接前一篇文章&#xff1a;libdrm全解析三十七 —— 源码全解析&#xff08;34&#xff09; 本文参考以下博文&#xff1a; DRM 驱动程序开发&#xff08;VKMS&#xff09; 特此致谢&#xff01; 前一篇文章讲解完了drmModeSetCrtc(crtc_id, fb_id, connector_id, mode)&#…...

jar包和war包的区别

SpringBoot项目既可以打成war包发布&#xff0c;也可以找成jar包发布。 jar包 jar包&#xff1a;直接通过内置Tomcat运行&#xff0c;不需要额外安装Tomcat。如需修改内置Tomcat的配置&#xff0c;只需要在SpringBoot的配置文件中配置。内置Tomcat没有自己的日志输出&#xff0…...

CloudCompare 二次开发(10)——点云投影到平面

目录 一、概述二、代码集成三、结果展示一、概述 不依赖任何第三方点云相关库,使用CloudCompare编程实现点云投影到指定平面,具体计算原理见:PCL 点云投影到拟合平面 二、代码集成 1、mainwindow.h文件public中添加: void doActionProjectToPlane(); // 投影到平面2、…...

如何制作并运行 jar 程序

以下是用 Intellij 制作 jar 程序&#xff0c;并运行的方法。 【1】新建工程&#xff0c;保持默认选项&#xff0c;Next 【2】保持默认选项&#xff0c;Next 【3】给工程命名&#xff0c;设置保存位置&#xff0c;Finish 【4】新建工程结束&#xff0c;进入开发界面 【5】展开…...

Hadoop MapReduce 调优参数

文章目录 MapReduce 调优参数详解MapReduce 调优参数一键复制 前言&#xff1a; 下列参数基于 hadoop v3.1.3 版本&#xff0c;共三台服务器&#xff0c;配置都为 4 核&#xff0c;4G 内存。 MapReduce 调优参数详解 这个参数定义了在 Reduce 阶段同时进行的拷贝操作的数量&…...

springboot 与 Redis整合

SpringBoot 操作数据&#xff1a;Spring-data jpa jdbc mongodb redis! SpringData 也是和SpringBoot 齐名的项目&#xff01; 说明&#xff1a;在SpringBoot2.X 之后&#xff0c;原来使用的jedis被替换成了lettuce jedis&#xff1a; 采用的直连&#xff0c;多个线程操作的话&…...

如何高效地设计测试用例并评审

编写出好的测试用例是每一个测试工程师的职责&#xff0c;但在实际工作中大家写的测试用例往往需要不断地修改才能使用&#xff0c;这不仅浪费了时间&#xff0c;还容易让测试工程师产生自我否定的情绪&#xff0c;甚至在团队中产生各种矛盾。 那如何高效地设计测试用例呢&…...

基于python+Django知识图谱的医疗问答系统设计与实现

摘 要 从信息技术的发展至今&#xff0c;各色各样的技术能够满足各类人群的需求&#xff0c;能够让各种业务行业的痛点变成能够可以解决的方法&#xff0c;随着我们经济的不断提高&#xff0c;越来越多的人都该关注健康&#xff0c;那么健康饮食、健康医疗是我们生活中所追求的…...

cuda编程常见问题

cuda环境配置 参考链接 https://blog.csdn.net/weixin_43788327/article/details/125823507?spm1001.2014.3001.5506 疑难问题 在学习《GPU高性能编程CUDA实战》这本书时&#xff0c;发现书里面的代码很多变量都没定义过&#xff0c;经过搜索发现这都是书上自带的代码。 代…...

QTday3

作业1&#xff1a;通过对话框实现保存文件 void burger::on_saveBtn_clicked() {//调用函数&#xff0c;获取文件路径QString filename QFileDialog::getSaveFileName(this,"选择文件夹","./","Text File(*.txt)");if(filename.isNull()){QMes…...

docker镜像是如何导入的?

镜像导入是由image/tarexport/load.go#tarexporter.Load()完成的 以下代码参考github.com/docker/docker版本v0.0.0-20181129155816-baab736a3649 主要是注册镜像信息以及解包镜像tar流到新root 导出和保存的区别在于 导出(export): 仅导出文件结构保存(save): 保存镜像历史和元…...

四川大学874考研真题00-23

22, 2022年硕士学位研究生入学考试试题回忆版 数据结构 1&#xff0e;一个时间复杂度为n2 的算法运行&#xff0c;m1算n个问题用时1秒&#xff0c;m2处理器是m1效率的64倍&#xff0c;则m2每秒能计算&#xff08;&#xff09;个问题。 A. 64n B. 8n …...

openGauss学习笔记-58 openGauss 高级特性-资源池化

文章目录 openGauss学习笔记-58 openGauss 高级特性-资源池化58.1 特性简介58.2 架构介绍58.3 功能特点58.4 适用场景与限制58.5 手动安装示例58.6 OCK RDMA使用示例58.7 OCK SCRLock使用示例 openGauss学习笔记-58 openGauss 高级特性-资源池化 58.1 特性简介 资源池化特性主…...

centos升级cmake之相关问题解决

1. yum安装(仓库默认版本) # 查看可安装版本 yum --showduplicates list xxxx# 安装指定版本 yum install xxxx-1.23.1 2. 安装高版本cmake 2.1 一开始下载的是cmake-xxx.zip&#xff0c;在 ./bootstrap 一直会报错“missing terminating " character”&#xff0c;后来…...

vcs仿真教程(查看断言)

VCS是在linux下面用来进行仿真看波形的工具&#xff0c;类似于windows下面的modelsim以及questasim等工具&#xff0c;以及quartus、vivado仿真的操作。 1.vcs的基本指令 vcs的常见指令后缀 sim常见指令 2.使用vcs的实例 &#xff08;1&#xff09;新建文件夹&#xff1a; …...

2023开学礼新疆石河子大学图书馆藏八一新书《乡村振兴战略下传统村落文化旅游设计》许少辉新财经理工

2023开学礼新疆石河子大学图书馆藏八一新书《乡村振兴战略下传统村落文化旅游设计》许少辉新财经理工...

javaee spring aop 切入点表达式

1、切入点表达式&#xff1a;对指定的方法进行拦截&#xff0c;并且生成代理表达式。 表达式语法&#xff1a;execution([修饰符] 返回值类型 包名.类名.方法名(参数))execution( public void com.test.service.impl.UsersService.add() )2、表达式不同写法 1.匹配指定方法 …...

js 获得元素的offsetLeft

要获得元素相对于其offsetParent元素左侧边缘的距离&#xff08;即offsetLeft&#xff09;&#xff0c;可以使用如下代码&#xff1a; var el document.getElementById(your-element-id); var offsetLeft el.offsetLeft;其中&#xff0c;el为要获取offsetLeft的元素对象&…...

石家庄网站建设机构/好用的磁力搜索引擎

四大函数类型一. 局部和全局变量二. 引用三. 匿名函数四. 递归前言作者&#xff1a;神的孩子都在跳舞 关注我的csdn博客&#xff0c;更多python知识还在更新 一. 局部和全局变量 局部变量 &#xff08;1&#xff09;含义&#xff1a;就是在函数内部定义的变量&#xff08;作用…...

网站后台怎么做alt标签/网站统计工具有哪些

现在的爬虫越来越难了&#xff0c;不再和之前的那样&#xff0c;随便抓个包就可以找到相关的 url &#xff0c;然后 post 一下或者 get 一下数据就出来了。还有一个可能就是可能你以前用来学习的爬虫网站太简单了&#xff0c;还没有看见过那些猛的。上两周我就想弄弄知乎登陆&a…...

学校网站开发研究的意义和目的/企业营销

本篇文章主要给大家介绍一下如何使用htmlcss实现元素的水平与垂直居中效果&#xff0c;这也是我们网页在编码制作中会经常用到的问题。 1&#xff09;单行文本的居中 主要实现css代码&#xff1a; 水平居中&#xff1a;text-align:center;垂直居中&#xff1a;line-height:X…...

汕头网站公司/品牌推广渠道有哪些

[20150806]scn headroom.txt 转载:http://www.askmaclean.com/archives/scn-headroom-1988-oracle.html SCN是Oracle数据库内部的一种逻辑时间戳&#xff0c;通过SCN将数据库内的事件理清次序&#xff0c; 这是保证事务属性ACID的必要信息。 数据库使用SCN来帮助实现查询和跟踪…...

电子政务网站建设流程/做做网站

Ajax的应用在平时的工作中&#xff0c;很是常见&#xff0c;这篇文章&#xff0c;完全是为了&#xff0c;巩固复习。 我们先看看不使用json格式返回分部视图&#xff1a; 先说需求吧&#xff1a; 我有两个实体&#xff0c;一个是出版商【Publisher】&#xff0c;一个是书【Book…...

网站收录更新/口碑营销策划方案

早晨起床时间&#xff1a;6:00 晚上休息时间&#xff1a;23:24 今日总结&#xff1a;休息。...