[日常] Go语言圣经-匿名函数习题

[日常] Go语言圣经-匿名函数习题

Go语言圣经-匿名函数
1.拥有函数名的函数只能在包级语法块中被声明,通过函数字面量(function literal),我们可绕过这一限制,在任何表达式中表示一个函数值
2.通过这种方式定义的函数可以访问完整的词法环境(lexical environment),这意味着在函数中定义的内部函数可以引用该函数的变量
3.函数值不仅仅是一串代码,还记录了状态,意味着匿名函数和父函数中,存在变量引用,函数值属于引用类型和函数值不可比较的原因。Go使用闭包(closures)技术实现函数值,Go程序员也把函数值叫做闭包
4.给定一些计算机课程,每个课程都有前置课程,只有完成了前置课程才可以开始当前课程的学习,这类问题被称作拓扑排序。从概念上说,前置条件可以构成有向图。

 

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

练习5.11: 现在线性代数的老师把微积分设为了前置课程。完善topSort,使其能检测有向图中的环。

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

 

package main

import (
        "fmt"
        "golang.org/x/net/html"
        "net/http"
        "sort"
)

var prereqs = map[string][]string{
        "algorithms": {"data structures"},
        "calculus":   {"linear algebra"},
        "compilers": {
                "data structures",
                "formal languages",
                "computer organization",
        },  
        "data structures":       {"discrete math"},
        "databases":             {"data structures"},
        "discrete math":         {"intro to programming"},
        "formal languages":      {"discrete math"},
        "networks":              {"operating systems"},
        "operating systems":     {"data structures", "computer organization"},
        "programming languages": {"data structures", "computer organization"},
}

func main() {
        for i, course := range topoSort(prereqs) {
                fmt.Printf("%d:\t%s\n", i+1, course)
        }   
        fmt.Println("------------------------")
        for k, v := range topoSort2(prereqs) {
                fmt.Printf("%d:\t%s\n", k, v)
        }   
        fmt.Println("------------------------")
        outline("http://mail.sina.net")
}

/*
练习5.10: 重写topoSort函数,用map代替切片并移除对key的排序代码。验证结果的正确性(结果不唯一)。
*/
func topoSort2(m map[string][]string) map[int]string {
        var order = make(map[int]string)
        index := 1
        seen := make(map[string]bool)
        var visitAll func(items []string)
        visitAll = func(items []string) {
                for _, item := range items {
                        if !seen[item] {
                                seen[item] = true
                                visitAll(m[item])
                                order[index] = item
                                index++
                        }
                }
        }
        var keys []string
        for key := range m {
                keys = append(keys, key)
        }
        visitAll(keys)
        return order
}
func topoSort(m map[string][]string) []string {
        var order []string
        seen := make(map[string]bool)
        var visitAll func(items []string)
        visitAll = func(items []string) {
                for _, item := range items {
                        if !seen[item] {
                                seen[item] = true
                                visitAll(m[item])
                                order = append(order, item)
                        }
                }
        }
        var keys []string
        for key := range m {
                keys = append(keys, key)
        }
        sort.Strings(keys)
        visitAll(keys)
        return order
}

/*
练习5.11: 现在线性代数的老师把微积分设为了前置课程。完善topSort,使其能检测有向图中的环。
等着去看数据结构再看这个题
*/

/*
练习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 int
        var startElement func(n *html.Node)
        var endElement func(n *html.Node)

        startElement = func(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)
                }
        }
        endElement = func(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)
                }
        }
        //1.使用函数值
        forEachNode(doc, startElement, endElement)
        resp.Body.Close()
        return "", nil
}

func forEachNode(n *html.Node, pre, post func(n *html.Node)) {
        //显式的调用一下
        if pre != nil {
                pre(n)
        }

        //fmt.Println(n.Data)
        for c := n.FirstChild; c != nil; c = c.NextSibling {
                forEachNode(c, pre, post)
        }
        if post != nil {
                post(n)
        }
}

[日常] Go语言圣经-匿名函数习题  

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/101717.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 2011年全国电子设计大赛综合测试题_全国大学生英语竞赛 C类

    2011年全国电子设计大赛综合测试题_全国大学生英语竞赛 C类系统方案总体设计方案本系统主要由电位器模块、直流减速电机模块、电源模块、电机驱动模块、单片机最小系统班组成。电位器与主控芯片STM32F407ZGT6相连,通过电位的测算实时向MCU发送摆杆的状态,MCU通过控制LM298N电机驱动模块来控制直流减速电机,进而控制摆杆的状态,并使用LCD显示相关参数。方案的比较与选择2.1传感器的选择方案一:采用三轴陀螺仪测量摆杆的偏转角度。当选用三轴陀螺仪检测摆杆的偏转角度时,虽然可以计算摆杆的偏转角度,但是传感器必须要固定在摆杆上,同时需与M…

    2022年8月18日
    3
  • phpstorm新版激活码_在线激活[通俗易懂]

    (phpstorm新版激活码)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月31日
    130
  • 关于以太网没有有效的ip配置问题解决方法[通俗易懂]

    关于以太网没有有效的ip配置问题解决方法[通俗易懂]错误提示解决方法一,检查IP地址是否为自动获取1,首先右键任务栏右下角的网络图标点击进入”网络和共享中心”,然后点击”更改适配器设置”。2,在适配器界面右键”本地连接”点击打开属性3,在本地连接属性界面将“Internet协议版本6(ICP/IPv6)”前面的√去掉,然后选中“Internet协议版本4(ICP/IPv4)”双击打开属性界面。4,在属性界面设置IP地址为自动获取二,重置网络环境1,右键左下角的Windows徽标,打开管理员模式的命令提示符2,输入ne

    2022年5月14日
    51
  • unsigned char ch=249; int i=ch_char类型输出格式

    unsigned char ch=249; int i=ch_char类型输出格式(unsignedchar)~0>>1

    2022年9月20日
    1
  • ActivityManager 讲解

    ActivityManager 讲解1.ActivityManager是android框架的一个重要部分,它负责一新ActivityThread进程创建,Activity生命周期的维护,本blog就是着手对ActivityManager框架作一个整体的了解       2.先看一个静态类结构图:       上图很清楚地描述了ActivityManager框架的几个主要类之间的关系,我们做应用开发接触很多的

    2022年9月6日
    3
  • 如何打造一款直播App(方法流程)

    如何打造一款直播App(方法流程)概要分享内容:互联网内容载体变迁历程,文字——图片/声音——视频——VR/AR——…….。从直播1.0秀场时代(YY),2.0游戏直播(斗鱼、虎牙、熊猫)到如今全民直播3.0泛生活娱乐时代(映客、花椒),国外直播app(Meerkat、Periscope),随着VA/AR/MR提出的沉浸式视听体验,直播4.0时代很快就能到来。在这个全民娱乐的时代,直播已经火得不要不要的,

    2022年5月26日
    55

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号