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链表的部分,将循环调用visit,改成递归调用。 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 开发一个简单的多页面跳转
本文介绍一个简单的安卓应用的页面跳转例子,用的是kotlin。 运行时主页面是一个hello 和Jump 按钮,你按一下jump 按钮就转到 从页面,只是标识从页面。 开始建立一个简单工程,名为hello, 选择的是Empty views Activit…...
记录我的tensorrt 部署yolov8
系统 :ubuntu 18.04 代码 :GitHub - noahmr/yolov5-tensorrt: Real-time object detection with YOLOv5 and TensorRT conda 环境 : GitHub - noahmr/yolov5-tensorrt: Real-time object detection with YOLOv5 and TensorRT cuda : 11.8 …...
什么是用户界面? 优漫动游
什么是用户界面? 用户界面(UI,UserInterface)也称人机界面,是人机交互、操作逻辑和界面表现的整体设计。每一种设计都有其对应的职业角色,其中,人机交互的设计人员叫做用户研究工程师,操作逻辑设计人员叫…...
基于 Docker 的 MySQL 主从复制搭建(Mac M1版本)
系统:Macbook M1 镜像版本:mysql:5.7 如果是要查 slave连接不上 master的问题,可以直接跳到文章末尾踩坑处 准备工作 拉取镜像 docker pull mysql:5.7本地数据卷挂载 因为mysql不挂载的话,重启丢失数据,所以在本地创…...
【Locomotor运动模块】瞬移
文章目录 一、原理二、两种类型1、Instant(立刻)2、Dash(猛冲) 三、瞬移区域、瞬移点1、瞬移区域2、瞬移点 一、原理 抛物线指针选择好目标位置,然后告诉瞬移预设体:你想法把游戏区域弄到目标位置来 解释:抛物线指针选…...
【负载均衡】常见的负载均衡策略有哪些?
文章目录 前言负载均衡分类常见负载均衡策略小结 前言 负载均衡策略是实现负载均衡器的关键,而负载均衡器又是分布式系统中不可或缺的重要组件。使用它有助于提高系统的整体性能、可用性、可靠性和安全性,同时支持系统的扩展和故障容忍性。对于处理大量…...
ChatGPT如何应对紧急救援和医疗应急?
ChatGPT在紧急救援和医疗应急方面具有潜在的重要用途。它可以用于提供信息、建议和支持,以帮助应对各种突发事件,如自然灾害、流行病爆发、事故等。以下是ChatGPT如何应对紧急救援和医疗应急的方式以及相关挑战的详细讨论。 ### 紧急救援 #### 1. 提供…...
vue3 ref reactive响应式数据 赋值的问题
文章目录 vue3 ref reactive响应式数据 赋值的问题场景1:将响应式数据赋值请求后的数据错误示范:直接赋值正确写法 场景2:响应式数据解构之后失去响应式原因分析解决办法 toRefs/toRef方法创建ref引用对象 vue3 ref reactive响应式数据 赋值的问题 doing…...
【美团秋招】20230922小美的彩虹糖
小美的彩虹糖 小美有很多的彩虹糖,每颗彩虹糖都有一个颜色,她每天可以吃两颗彩虹糖,如果今天吃的彩虹糖组合是之前没吃过的组合,则小美今天会很高兴。 例如,小美有 6 颗彩虹糖,颜色分别是 [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呢,因为很多项目进行漏扫结果都会涉及到这个服务器核心组件,一想到以前升级openssh带来的各种依赖性问题就头疼,不管是什么发行版,升级这个东西真的很烦,这次发现可能还会有好一点的通用一点的升…...
libdrm全解析三十八 —— 源码全解析(35)
接前一篇文章:libdrm全解析三十七 —— 源码全解析(34) 本文参考以下博文: DRM 驱动程序开发(VKMS) 特此致谢! 前一篇文章讲解完了drmModeSetCrtc(crtc_id, fb_id, connector_id, mode)&#…...
jar包和war包的区别
SpringBoot项目既可以打成war包发布,也可以找成jar包发布。 jar包 jar包:直接通过内置Tomcat运行,不需要额外安装Tomcat。如需修改内置Tomcat的配置,只需要在SpringBoot的配置文件中配置。内置Tomcat没有自己的日志输出࿰…...
CloudCompare 二次开发(10)——点云投影到平面
目录 一、概述二、代码集成三、结果展示一、概述 不依赖任何第三方点云相关库,使用CloudCompare编程实现点云投影到指定平面,具体计算原理见:PCL 点云投影到拟合平面 二、代码集成 1、mainwindow.h文件public中添加: void doActionProjectToPlane(); // 投影到平面2、…...
如何制作并运行 jar 程序
以下是用 Intellij 制作 jar 程序,并运行的方法。 【1】新建工程,保持默认选项,Next 【2】保持默认选项,Next 【3】给工程命名,设置保存位置,Finish 【4】新建工程结束,进入开发界面 【5】展开…...
Hadoop MapReduce 调优参数
文章目录 MapReduce 调优参数详解MapReduce 调优参数一键复制 前言: 下列参数基于 hadoop v3.1.3 版本,共三台服务器,配置都为 4 核,4G 内存。 MapReduce 调优参数详解 这个参数定义了在 Reduce 阶段同时进行的拷贝操作的数量&…...
springboot 与 Redis整合
SpringBoot 操作数据:Spring-data jpa jdbc mongodb redis! SpringData 也是和SpringBoot 齐名的项目! 说明:在SpringBoot2.X 之后,原来使用的jedis被替换成了lettuce jedis: 采用的直连,多个线程操作的话&…...
如何高效地设计测试用例并评审
编写出好的测试用例是每一个测试工程师的职责,但在实际工作中大家写的测试用例往往需要不断地修改才能使用,这不仅浪费了时间,还容易让测试工程师产生自我否定的情绪,甚至在团队中产生各种矛盾。 那如何高效地设计测试用例呢&…...
基于python+Django知识图谱的医疗问答系统设计与实现
摘 要 从信息技术的发展至今,各色各样的技术能够满足各类人群的需求,能够让各种业务行业的痛点变成能够可以解决的方法,随着我们经济的不断提高,越来越多的人都该关注健康,那么健康饮食、健康医疗是我们生活中所追求的…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
加密通信 + 行为分析:运营商行业安全防御体系重构
在数字经济蓬勃发展的时代,运营商作为信息通信网络的核心枢纽,承载着海量用户数据与关键业务传输,其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级,传统安全防护体系逐渐暴露出局限性&a…...
