> 一份2021年03月20日的信息流提炼 ### 每天学点Golang #### 如何破解25大Golang面试题 原文:[How To Crack the Top 25 Golang Interview Questions](https://betterprogramming.pub/how-to-crack-the-top-25-golang-interview-questions-a94396d6c808) - 与其他语言相比,使用Go的好处是什么? - 与其他以学术实验起家的语言不同,Go代码是实用性设计的。每一个功能和语法决策都是为了让程序员的生活更轻松而设计的。Golang针对并发性(**concurrency**)进行了优化,并且在规模上工作得很好。自动垃圾收集比Java或Python更有效率,因为它与程序同时执行。 - Go的数据类型 - (12种) Method, Boolean, Numeric, String, Array, Slice, Struct, Pointer, Function, Interface, Map, Channel - 如何用Go实现继承 - ```go type Animal struct { // … } func (a *Animal) Eat() { … } func (a *Animal) Sleep() { … } func (a *Animal) Run() { … } type Dog struct { Animal // … } ``` - Interface是什么,又是如何工作的 - 如何在运行时检查变量类型? - ```go package main import "fmt" func do(i interface{}) { switch v := i.(type) { case int: fmt.Printf("Double %v is %v\n", v, v*2) case string: fmt.Printf("%q is %v bytes long\n", v, len(v)) default: fmt.Printf("I don't know type %T!\n", v) } } func main() { do(21) do("hello") do(true) } ``` - Go的中的循环结构是什么? - Go只有一个循环结构:for循环。` for i := 0; i < 10; i++ {}` - 打印slice字符或字符串的所有排列组合(**permutations**)。 - ```go // Perm calls f with each permutation of a. func Perm(a []rune, f func([]rune)) { perm(a, f, 0) } // Permute the values at index i to len(a)-1. func perm(a []rune, f func([]rune), i int) { if i > len(a) { f(a) return } perm(a, f, i+1) for j := i + 1; j < len(a); j++ { a[i], a[j] = a[j], a[i] perm(a, f, i+1) a[i], a[j] = a[j], a[i] } } func main() { Perm([]rune("abc"), func(a []rune) { fmt.Println(string(a)) }) } ``` - 在没有临时变量的情况下交换两个变量的值 - ```go func main() { fmt.Println(swap()) } func swap() []int { a, b := 15, 10 b, a = a, b return []int{a, b} } ``` - 颠倒slice的顺序 - ```go func reverse(sw []int) { for a, b := 0, len(sw)-1; a < b; a, b = a+1, b-1 { sw[a], sw[b] = sw[b], sw[a] } } func main() { x := []int{3, 2, 1} reverse(x) fmt.Println(x) } ``` - 解释Golang中并发(**concurrent**)和并行(**parallelism**)的区别。 - 并发是指你的程序可以同时处理多个任务,而并行是指你的程序可以使用多个处理器同时执行多个任务。因此,并行性可以是实现并发性属性的一种手段,但它只是你可用的众多手段之一。Golang中并发的关键工具是goroutines和channel。goroutines是并发的轻量级线程,而通道则允许goroutines在执行过程中相互通信。 - 使用goroutines和通道实现并发合并排序方案。 - ※代码参考附录 - 实现SumOfSquares函数,该函数接收一个整数c,并返回1和c之间的所有平方之和,你需要使用select语句、goroutines和通道。例如,输入5将返回55,因为1^2 + 2^2 + 3^2 + 4^2 + 5^2 = 55$。 - ※代码参考附录 ### 每天学点软技能 #### 如何聪明地记笔记--彻底改变你的笔记和写作的10个原则。 原文:[How To Take Smart Notes: 10 Principles to Revolutionize Your Note-Taking and Writing](https://fortelabs.co/blog/how-to-take-smart-notes/) - 原则一:写作不是思维的结果,而是思维发生的媒介(**Medium**) - 如果你想长期学习和记住某件事,你必须把它写下来。如果你想理解一个想法,你必须把它转化为自己的语言。 - > If you want to learn and remember something long-term, you have to write it down. If you want to understand an idea, you have to translate it into your own words. - 原则2:把写作当作唯一重要的事情来做(**Only thing matters**) - 研究的目的是产生可供审查和检验的公共知识。要做到这一点,就必须把它写下来。一旦写下来,作者的意思就不重要了--只有写在纸上的实际文字才重要。 在学术界和科学界,几乎所有的研究都是以最终发表为目的的,Ahrens指出,"**在学术界没有私人知识这回事。一个不为人知的想法就像你从未拥有过的想法一样好**"。 - 原则3:没有人可以从空白开始 - 在你还不知道如何拟定一个好问题之前,你就必须沉浸在研究之中。而阅读一个主题与另一个主题的决定也不是凭空出现的。它通常来自于现有的兴趣或理解。事实上,每一项知识性的工作都是从先前的构想开始的。 这就是创作过程的核心张力。在你选择你要写的东西之前,你必须进行研究。理想情况下,你应该在很早之前就开始研究,这样你一旦决定了一个主题,就有几周几月甚至几年的丰富素材可以利用。这就是为什么一个外部系统来记录你的研究是如此关键。 - 原则4:我们的工具和技术只有在工作流程中才有价值 - 仅仅因为写作不是一个线性的过程,并不意味着我们应该胡乱地去做。我们需要一个工作流程--一个可重复的收集、组织和分享想法的过程。 写作常常被教导为一系列的 "技巧和窍门"--集思广益,制定大纲,使用三段式结构,重复要点,使用生动的例子,设置计时器。每一个单独的技巧也许都有意义,但如果没有从整体的角度来考虑它们是如何结合在一起的,它们就会增加更多的工作。 - 原则5:标准化(**Standardization**)有助于发挥创造力 - 这意味着当需要写作的时候,他们首先要进行一项庞大的工程,收集和整理这些散落的笔记。笔记就像装想法的集装箱。与其为你阅读的每一个资料发明一种新的笔记方式,不如每次都使用一种完全标准化和可预测的格式。不管笔记包含什么内容,它们与哪个主题有关,或者它们是通过什么媒介到达的,你都要以完全相同的方式对待每一个笔记。通过规范和简化我们笔记的格式和处理笔记的步骤,真正的工作就可以走到前面:思考、反思、写作、讨论、测试和分享。这是增加价值的工作,现在我们有时间更有效地进行这项工作。 - 原则6:只有当我们接触到高质量的反馈(**Feedback**)时,我们的工作才会变得更好 - 工作流程类似于化学反应。它可以自给自足,成为一种良性循环,在这种循环中,理解一个文本的积极经验激励我们进行下一个任务,这有助于我们更好地完成我们正在做的工作,这反过来又使我们更有可能享受我们的工作,等等。 - 原则7:同时进行多个项目(**Simultaneous**)的工作 - 我们会遇到源源不断的新想法,但其中只有极小部分在任何特定时刻对我们有用和相关。既然要想知道一本书包含哪些见解,唯一的方法就是阅读它,那么你不妨高效地阅读和记录。多花一点时间来记录你所遇到的最好的想法--无论你是否知道它们最终将如何被使用--都会大大增加你在未来 "偶然发现 "它们的机会。 - 原则8:按**上下文**(context)而不是按主题来组织你的笔记 - 经典的错误是把它们整理成越来越具体的主题和副主题。这让它看起来不那么复杂,但很快就会变得不堪重负。笔记堆积得越多,副主题就越小越窄,限制了你看到它们之间有意义的联系的能力。在这种方法下,一个人收集的笔记越多,它们的可访问性和实用性就越差。 - 原则9:永远选择最有趣的路径 - 阿伦斯指出,在大多数情况下,学生失败不是因为能力不足,而是因为他们失去了与学习内容的个人联系。 "当即使是高智商的学生学习失败时,最常见的原因是他们不再看到他们应该学习的东西的意义(参见Balduf,2009年),无法与他们的个人目标建立联系(Glynn等人,2009年),或者缺乏自主控制他们自己的学习和按自己的方式学习的能力(Reeve和Jan,2006年;Reeve,2009年)。 卢曼从不强迫自己做任何事情,只做自己容易想到的事情。"当我被困在一个时刻,我离开它,做别的事情。" 就像武术一样,如果遇到阻力或反对的力量,你不应该推倒它,而应该把它转向另一个富有成效的目标。 - 原则10:保存矛盾(**Contradictory**)的想法 - 我们保存什么的唯一标准是,它是否与现有的观点相联系,是否能增加讨论的内容。当我们专注于开放的联系时,不确定或矛盾的数据突然变得非常有价值。它往往会提出新的问题,并开辟新的探究之路。 ##### 聪明记笔记的8个步骤 - 临时笔记 - 文献笔记 - 永久性笔记 - 现在将您的新的永久笔记添加到工作区域(slip-box)中 - 从工作区域中自下而上地开发您的主题、问题和研究项目 - 在工作区域内决定一个主题,写出一个主题 - 把你的笔记变成草稿 - 编辑和校对您的手稿 ### 附录:snippets - [Charts.css](https://news.ycombinator.com/item?id=26494819) ```bash # Demo: https://jsfiddle.net/wcfez6oq/ ( echo "" echo "Size of Charts.css releases" for version in $(curl -sS https://github.com/ChartsCSS/charts.css/releases | grep -o releases/tag/[0-9.]* | cut -d/ -f3 | tac); do url=https://cdn.jsdelivr.net/npm/charts.css@$version/dist/charts.min.css size=$(($(curl -sS "$url" | wc -c)/1024)) echo "v$version${size}KiB" done echo "" ) > size-chart.html ``` - Go 并发排序 ```go package main import "fmt" func Merge(left, right [] int) [] int{ merged := make([] int, 0, len(left) + len(right)) for len(left) > 0 || len(right) > 0{ if len(left) == 0 { return append(merged,right...) }else if len(right) == 0 { return append(merged,left...) }else if left[0] < right[0] { merged = append(merged, left[0]) left = left[1:] }else{ merged = append(merged, right [0]) right = right[1:] } } return merged } func MergeSort(data [] int) [] int { if len(data) <= 1 { return data } done := make(chan bool) mid := len(data)/2 var left [] int go func(){ left = MergeSort(data[:mid]) done <- true }() right := MergeSort(data[mid:]) <-done return Merge(left,right) } func main(){ data := [] int{9,4,3,6,1,2,10,5,7,8} fmt.Printf("%v\n%v\n", data, MergeSort(data)) } ``` - Go SumOfSquares实现 ```go package main import "fmt" func SumOfSquares(c, quit chan int) { y := 1 for { select { case c <- (y*y): y++ case <-quit: return } } } func main() { mychannel := make(chan int) quitchannel:= make(chan int) sum:= 0 go func() { for i := 1; i <= 5; i++ { sum += <-mychannel } fmt.Println(sum) quitchannel <- 0 }() SumOfSquares(mychannel, quitchannel) } ``` ### 一些收获 - **The Code is the Design** - 工匠精神的两个部分:知识与实践。There are tow parts to learning craftemanship: knowledge and work. **Your must gain the knowledege of principles, patterns, pactices, and heuristics that a craftsman knows**, and you must also grind that knowledge into your fingers, eyes, and gut by working hard and practicing. -- Clean Code - "Some books are to be tasted, others to be swallowed, and some few to be chewed and digested" - Francis Bacon | [The Art of Reading More Effectively and Efficiently](https://aliabdaal.com/read-more-effectively/)