整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

GCTT 出品Go 中不定长度集合

GCTT 出品Go 中不定长度集合

发于:https://studygolang.com/articles/14132

如果你在使用像 C# 或 Java 这样的编程语言后来到 go,你发现的第一件事就是没有像 List和 Dictionary 这样的传统集合类型。 这真让我困惑了好几个月。 我找到了一个名为container/list 的软件包,并且几乎用它做所有的东西。

我脑后一直有一个声音在唠叨。语言设计者不应该不直接支持对未知长度的集合管理的功能。每个人都在讨论切片是如何在语言中被广泛使用,但我只是在有明确定义的容量或者它们通过函数返回时我才使用切片,这有点不对劲!!

因此,我在本月早些时候写了一篇文章,揭开了切片的盖子,希望能找到一些我不知道的魔法。我现在知道切片是如何工作的,但最终我仍然需要一个不断进行长度增长的数组。我在学校学过,使用链表更有效率,是存储大量数据更好的方法。特别是当你需要的集合长度未知时。这对我来说很有意义。

当我思考使用一个空切片时,我头脑中有一张非常错误的图片:

slice-copy

我一直在想 go 是如何创建大量新的切片值和底层数组做大量内存分配,并且不断进行复制值。然后垃圾回收器会因为所有这些小变量被创建和销毁而过度工作。

我无法想象需要做数千次这种操作。其实有更好的方法或更效率的方式我没有意识到。

在研究并提出了很多问题之后,我得出的结论是,在大多数实际情况下,使用切片比使用链表更好。这就是为什么语言设计者花时间使切片尽可能高效工作,并且没有引入集合类型的原因。

我们可以连续几天讨论各种边界情况和性能问题,但 go 希望我们使用切片。因此切片应该是我们的首选,除非代码告诉我们存在问题。掌握切片就像学国际象棋游戏,易于学习但需要一辈子才能成为大师。因为底层数组可以共享,所以在使用中需要注意一些问题。

在继续阅读之前,你最好看一下我的另一篇文章 Understanding Slices in Go Programming。

本文的其余部分将解释如何使用切片处理未知容量的问题以及切片的运行机制。

以下是使用空切片来管理未知长度集合的示例:

 1package main
 2
 3import (
 4 "fmt"
 5 "math/rand"
 6 "time"
 7)
 8
 9type Record struct {
10 ID int
11 Name string
12 Color string
13}
14
15func main() {
16 // Let’s keep things unknown
17 random :=rand.New(rand.NewSource(time.Now().Unix()))
18
19 // Create a large slice pretending we retrieved data
20 // from a database
21 data :=make([]Record, 1000)
22
23 // Create the data set
24 for record :=0; record < 1000; record++ {
25 pick :=random.Intn(10)
26 color :="Red"
27
28 if pick==2 {
29 color="Blue"
30 }
31
32 data[record]=Record{
33 ID: record,
34 Name: fmt.Sprintf("Rec: %d", record),
35 Color: color,
36 }
37 }
38
39 // Split the records by color
40 var red []Record
41 var blue []Record
42
43 for _, record :=range data {
44 if record.Color=="Red" {
45 red=append(red, record)
46 } else {
47 blue=append(blue, record)
48 }
49 }
50
51 // Display the counts
52 fmt.Printf("Red[%d] Blue[%d]\n", len(red), len(blue))
53}

当我们运行这个程序时,由于随机数生成器,我们将得到不同长度的红色和蓝色切片。我们无法提前知道红色或蓝色切片的容量需要,这对我来说是一种典型的情况。

让我们分解出代码中更重要的部分:

这两行代码创建了空切片。

1var red []Record
2var blue []Record

一个空切片长度和容量都是0,并且不存在底层数组。我们可以使用内置的 append 函数向切片中增加数据。

1red=append(red, record)
2blue=append(blue, record)

append 函数功能非常酷,为我们做了很多东西。

Kevin Gillette 在我的小组讨论中进行了说明:

(https://groups.google.com/forum/#!topic/golang-nuts/nXYuMX55b6c)

在 go 语音规范中规定,前几千个元素在容量增长的时候每次都将容量翻倍,然后以~1.25的速率进行容量增长。

我不是学者,但我看到使用波浪号(~)相当多。有些人也许不知道这是什么意思,这里表示大约。因此,append 函数会增加底层数组的容量并为未来的增长预留空间。最终 append 函数将大约以1.25或25%的系数进行容量增长。

让我们证明 append 函数增长容量并高效运行:

 1package main
 2
 3import (
 4 "fmt"
 5 "reflect"
 6 "unsafe"
 7)
 8
 9func main() {
10 var data []string
11
12 for record :=0; record < 1050; record++ {
13 data=append(data, fmt.Sprintf("Rec: %d", record))
14
15 if record < 10 || record==256 || record==512 || record==1024 {
16 sliceHeader :=(*reflect.SliceHeader)((unsafe.Pointer(&data)))
17
18 fmt.Printf("Index[%d] Len[%d] Cap[%d]\n",
19 record,
20 sliceHeader.Len,
21 sliceHeader.Cap)
22 }
23 }
24}

输出结果:

 1Index[0] Len[1] Cap[1]
 2Index[1] Len[2] Cap[2]
 3Index[2] Len[3] Cap[4] - Ran Out Of Room, Double Capacity
 4Index[3] Len[4] Cap[4]
 5Index[4] Len[5] Cap[8] - Ran Out Of Room, Double Capacity
 6Index[5] Len[6] Cap[8]
 7Index[6] Len[7] Cap[8]
 8Index[7] Len[8] Cap[8]
 9Index[8] Len[9] Cap[16] - Ran Out Of Room, Double Capacity
10Index[9] Len[10] Cap[16]
11Index[256] Len[257] Cap[512] - Ran Out Of Room, Double Capacity
12Index[512] Len[513] Cap[1024] - Ran Out Of Room, Double Capacity
13Index[1024] Len[1025] Cap[1280] - Ran Out Of Room, Grow by a factor of 1.25

如果我们观察容量值,我们可以看到 Kevin 是绝对正确的。容量正如他所说的那样在增长。在前1千的元素中,容量增加了一倍。然后容量以1.25或25%的系数增长。这意味着以这种方式使用切片将满足我们在大多数情况下所需的性能,并且内存不会成为问题。

最初我认为会为每次调用 append 时都会创建一个新的切片值,但事实并非如此。当我们调用append 时,在栈中复制了 red 副本。然后当 append 返回时,会再进行一次复制操作,但使用的我们已有的内存。

1red=append(red, record)


在这种情况下,垃圾收集器没有工作,所以我们根本没有性能或内存问题。我的 C# 和引用类型的思想再次打击了我。

请坐好,因为下一个版本中的切片会有变化。

Dominik Honnef 创建了一个博客,用简明的英文(谢谢)解释了 Go tip 中正在编写的内容。这些是下一版本中的内容。这是他博客的和博客中关于切片部分的链接。这是一篇很棒博客,推荐阅读。

http://dominik.honnef.co/go-tip/

http://dominik.honnef.co/go-tip/2013-08-23/#slicing

你可以用切片做很多的事情,甚至可以写一整本关于这个主题的书。就像我之前说的那样,切片就像国际象棋一样,易于学习但需要一辈子才能成为大师。如果您来自其他语言,如 C# 和 Java,那么请拥抱切片并使用它。这正是 go 中正确的方式。


via:https://www.ardanlabs.com/blog/2013/08/collections-of-unknown-length-in-go.html

作者:William Kennedy

译者:Alan

校对:polaris1119

本文由 GCTT 原创编译,Go 中文网 荣誉推出

爱好坚持,以收藏说事,学棋斋主是认真的!

#中国象棋#

棋家王首成

王首成,男,1970年7月6日出生黑龙江,象棋图书作家。痴迷江湖排局,曾对江湖排局投入了十余年的研究工作,尤其对“征西”局有着深入细致的研讨。2005年在哈尔滨市,结识了慕名已久的著名的象棋排局家李中健老师,从此步入排局界。2010年开始出版了十几部象棋排局书籍。

本人收藏了王先生的两部作品《街头棋摊揭秘》、《江湖排局新作》和电子版《百花齐放象棋谱》。


《百花齐放象棋谱》


电子版《百花齐放象棋谱》

江湖棋局的江湖

江湖棋局也是有江湖的。比如几大名谱棋局就是异同互见的,可惜少有人梳捋其来龙去脉。在现代随着江湖棋摊发展、棋家的创新、在古谱的基础上,不断出现了更多的新作,他们和古谱的源流、随时间的变迁,棋家的努力等等,值得爱好者关注和学习研究。

王首成先生的《街头棋摊揭秘》、《江湖排局新作》,正是这方面研究的成果集成,真是“首成”,也说不定,我不敢妄断!

江湖排局源出江湖,是经过多少江湖艺人精心提炼的结晶。江湖棋摊是江湖艺人每天设局谋生之处,随着社会的发展进步,江湖棋摊也随之进行了日新月异的改革和创新。复杂深奥、变幻莫测的江湖大局如七星聚会、野马操田等已少见,关键是每天所选用的江湖排局要有好而多的陷阱,才可以使挑战者在每一局棋上多下几局。

同时,一局棋局的同类局更多了,其中一个卒位置稍有差异,可能过程和结果,大相径庭。摊主复原棋局时你稍微没注意,可能就不是上一局面了。

这两本书,共收录新旧排局274局。在写法上分“江湖揭秘”、“棋局介绍”、“类局拾萃”、“名手介绍(江湖排局新作主要介绍了1949年前的国手)”四个部分。非常具有可读性和艺术性。


送炮成和局

赛事: 天天象棋网页(H5)版送炮成和局

日期: 2022-05-31


红方: 木狐斋主

黑方应该是有赢棋机会的,此着马7进5,大误,红方送炮妙手,结果和棋。

1. 马7进5 炮一平五

应该炮5进7?成马炮士象全对炮双高兵,显然黑好走。

2. 炮5进3 帅五进一


红方应对无误,结果破双士成和。经查,炮士象全也是赢不了双高兵的吧?请高手指教!

有指教,请留言,学习!

| 边策 安妮

出处 | 量子位

推荐 | 编程派公众号ID:codingpy)

GPT-2,一个来自OpenAI的逆天语言模型,现在能用来补全代码了。

一位来自加拿大的大四学霸,开发了一款”Deep TabNine“代码补全工具,实现了这一大胆的想法。

它支持23种编程语言、5种编辑器,使用简单,效果惊艳。

不少使用过的网友说:TabNine是他们用过的最好的代码补全工具,这是属于程序员的杀手级应用

在VS Code的扩展商店里,TabNine已经被下载1.3万次,获得全5星好评。

支持23种编程语言

Deep TabNine支持Java

Python

C++

Haskell

不同于各种其他代码补全插件,Deep TabNine是根据程序员过去的习惯自动补全,并在后面给出几种选项的概率。

如果有类似代码出现在之前的项目里,TabNine还会在补全候选框中直接给出地址,方便用户点击进去查阅。

除以上几种语言之外,Deep TabNine还支持JavaScriptCPHPGoC#RubyObjective-CRustSwiftTypeScriptOCamlScalaKotlinPerlSQLHTMLCSSBash

主流编程语言几乎都囊括在内。

支持5种编辑器

TabNine支持VS CodeSublime TextAtomEmacsVim五种代码编辑器。

对于使用VS Code和Sublime来说,安装TabNine非常方便,用自带的扩展包管理工具即可。

VS Code

VS Code用户按下Ctrl+P(Mac用户按下?+P),粘贴以下命令,然后按回车键完成安装。

ext install TabNine.tabnine-vscode

Sublime

Sublime用户安装分为两步:

1、按下Ctrl+Shift+P(Mac用户:?+Shift+P),选择Install Package Control;

2、再次按下Ctrl+Shift+P(Mac用户:?+Shift+P),选择Package Control:Install Package,然后选择TabNine来安装。

Vim

Vim使用Vundle插件管理器进行安装:

1、添加Plugin ‘zxqfl/tabnine-vim’.vimrc

2、输入:PluginInstall,按下回车完成安装。

其他编辑器的安装方法就不一一赘述了,有需要的用户可以参照文末的链接进行安装。

项目超过400kb需要购买许可证:个人用户49美元,商业用户99美元。

由于Deep TabNine用到机器学习补全代码,因此需要大量的算力(超过100亿次浮点运算),在笔记本上运行模型,无法获得低延迟的体验。

因此,软件开发者推出了TabNine Cloud云服务器,用云端GPU加速。付费用户不需要再加钱即可使用。

所以听起来很划算吧?

软件开发者自己就说,这个价格其实不贵,有了TabNine,一分钟就里能帮你节省一秒,咱们再算算程序员的时薪,每个小时能节约1.4美元,不到一年时间就能回本了。

如果你对效果不满意,TabNine开发者还提供30天退款保证。

怎么做到的?

TabNine是在GPT-2的基础上构建的,这是一种Transformer架构,原产自OpenAI,是个“逆天”语言模型。

GPT-2的参数高达15亿个,数据量比一代扩大了10倍,使用了包含800万个网页的数据集,共有40GB。

逆天之处就在于,GPT-2写起文章来毫无违和感,无需针对性训练就能横扫各种特定领域的语言建模任务,还具备阅读理解、问答、生成文章摘要、翻译等等能力。

就GPT-2而言,它的训练目标很简单:根据所有给定文本中前面的单词,预测下一个单词。虽然本来是解决NLP问题,看似与写代码没什么关联,但建模代码也算是用一种独有的方式在理解英文

比如,可以让模型用if/else语句否定单词:

项目主页显示,在大约经过GitHub中200万个文件训练后,TabNine具备了自动补全代码的能力。

在训练这个模型期间,模型学习了例如动态类型语言中的类型推断等复杂行为,用这样的训练方式预测token。

作者表示,TabNine可以很好利用传统代码补全工具难以获取的琐碎细节。

例如,假设app.get_user的返回类型是一个带有setter方法的对象,而app.get_users的返回类型是一个列表,两个名称之间只有细微的差别:

这个模型还能以自然语言编写的文档来推断函数名称、参数和返回类型:

Deep TabNine加入了之前用户强烈要求加入的功能:用预先存在的知识,解决在创建新项目时的代码补全问题。

例如,它知道当一个类扩展React.Component时,它的构造函数通常会调用一个名为props的参数,并且通常在其内部用this.state赋值:

Deep TabNine甚至可以做不可能的事情,并记住C++可变参数转发语法:

“杀手级应用”

TabNine问世后,不断收获好评,甚至还有程序员激动得爆粗口:

卧槽,这种软件多来点就好了。(Fuck yeah. This is the sort of software I want to see more often: TabNine )

有网友表示, 没有它都不知道该怎么面对写代码这件事了。

还有人称之为开发者应用中的第一个“杀手级应用程序”:

“令人印象深刻”、“感到神奇”“太酷了”……推特上的评价,颇有电视广告上“用了都说好”的画风。

在各大科技论坛上,也有网友提出了建议和改进的方向。

有用户反映,也有美中不足的地方,比如这个工具会干扰自动括号完成。

作者表示,TabNine还在不断更新完善中,正在改进这些bug。

大四学霸的第一桶金

想不到吧,这款好评如潮的代码工具,出自一名大四学生之手。

Jacob Jackson,加拿大人,目前在滑铁卢大学主修计算机科学与组合优化专业,辅修数学。大四在读,今年8月份毕业。

Jackson此前在Reddit上发帖称,这是自己在大学阶段开发的第一款商业软件产品。

别人的大学,别人的第一桶金~

但Jackson并非无名之辈,年少有为,曾在2014和2015连续两年获得IOI金牌

因此,大学一入学,便成为加拿大Michael and Ophelia Lazaridis Olympiad Scholarship奖学金的获得者,免除了8个学期学费书费和生活费。

除了自动补全代码的TabNine,Jackson还开发了很多有意思的应用,比如一个名为jellies的益智游戏,和使用蒙特卡罗树搜索的国际象棋引擎Sashimi等。

传送门

TabNine网站:https://tabnine.com/blog/deep

Jackson GitHub主页:https://github.com/zxqfl

Jackson简历:http://jacobj.ca/resume.html

题图:pexels,CC0 授权。