add jupyter

main
tink 1 year ago
parent 958a0a20f1
commit 38ba8904e6

@ -13,3 +13,10 @@ html:
publish: publish:
ssh root@www.cyub.vip "cd ${HTML_OUTPUT}; git pull" ssh root@www.cyub.vip "cd ${HTML_OUTPUT}; git pull"
plugin:
pip install mkdocs-git-revision-date-localized-plugin # 显示文档编辑时间
pip install mkdocs-mermaid2-plugin # mermaid图表支持
pip install mkdocs-charts-plugin # image box
pip install mkdocs-print-site-plugin # print site
pip install mkdocs-jupyter # jupyter

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,610 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# 引入pyspark,并创建spark上下文\n",
"import findspark\n",
"findspark.init()\n",
"import pyspark\n",
"sc = pyspark.SparkContext()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. 创建RDD的第一种方式读外部数据比如本地磁盘文件"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"rdd = sc.textFile('./dataset/Goodbye_Object_Oriented_Programming.txt')"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"pyspark.rdd.RDD"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 查看rdd类型\n",
"type(rdd)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.1 RDD之转换Transformation"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 0 ns, sys: 0 ns, total: 0 ns\n",
"Wall time: 31 µs\n"
]
}
],
"source": [
"%%time\n",
"## map是转换操作的一种这时候只是形成DAG\n",
"rdd = rdd.map(lambda x: len(x))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.2 RDD之行动Action"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"13187\n",
"CPU times: user 12 ms, sys: 0 ns, total: 12 ms\n",
"Wall time: 1.58 s\n"
]
}
],
"source": [
"%%time\n",
"## reduce是行动操作的一种, 这个时候才真正的计算\n",
"charCount = rdd.reduce(lambda x, y: x+y)\n",
"\n",
"print(charCount)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 328 2260 13687 ./dataset/Goodbye_Object_Oriented_Programming.txt\r\n"
]
}
],
"source": [
"! wc ./dataset/Goodbye_Object_Oriented_Programming.txt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.3 示例:统计单词出现的次数"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['Ive been programming in Object Oriented languages for decades. The first OO language I used was C++ and then Smalltalk and finally .NET and Java.',\n",
" '']"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wordRdd = sc.textFile('./dataset/Goodbye_Object_Oriented_Programming.txt')\n",
"\n",
"# take操作就是一种Action, 返回前n数据\n",
"wordRdd.take(2) "
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# 将每一行文本打散\n",
"wordRdd = wordRdd.map(lambda line: line.split(' '))"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[['Ive',\n",
" 'been',\n",
" 'programming',\n",
" 'in',\n",
" 'Object',\n",
" 'Oriented',\n",
" 'languages',\n",
" 'for',\n",
" 'decades.',\n",
" 'The',\n",
" 'first',\n",
" 'OO',\n",
" 'language',\n",
" 'I',\n",
" 'used',\n",
" 'was',\n",
" 'C++',\n",
" 'and',\n",
" 'then',\n",
" 'Smalltalk',\n",
" 'and',\n",
" 'finally',\n",
" '.NET',\n",
" 'and',\n",
" 'Java.'],\n",
" ['']]"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wordRdd.take(2)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2493"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 扁平化处理\n",
"\n",
"wordRdd = wordRdd.flatMap(lambda x: x)\n",
"\n",
"# 查看有多少个单词\n",
"wordRdd.count()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['Ive', 'been']"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 查看前两条数据\n",
"wordRdd.take(2)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2260"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 过滤掉空格数据\n",
"wordRdd = wordRdd.filter(lambda x: x != '')\n",
"\n",
"# 查看有多少个单词\n",
"wordRdd.count()"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[('Ive', 1), ('been', 1)]"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 转换成key-value形式rdd 即 (key, value)\n",
"wordRdd = wordRdd.map(lambda word: (word, 1))\n",
"\n",
"wordRdd.take(2)"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[('face', 1),\n",
" ('was', 18),\n",
" ('Monkey', 2),\n",
" ('how', 4),\n",
" ('Just', 1),\n",
" ('for', 11),\n",
" ('Directories', 1),\n",
" ('could', 4),\n",
" ('gained', 1),\n",
" ('AGAIN', 1)]"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wordRdd = wordRdd.reduceByKey(lambda x, y: x+y)\n",
"\n",
"# 查看一下\n",
"wordRdd.take(10)\n",
"\n",
"# 查看全部\n",
"# wordRdd.collect()"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"# 使用pandas继续计算\n",
"import pandas as pd"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>word</th>\n",
" <th>count</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>face</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>was</td>\n",
" <td>18</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Monkey</td>\n",
" <td>2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>how</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Just</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>for</td>\n",
" <td>11</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>Directories</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>could</td>\n",
" <td>4</td>\n",
" </tr>\n",
" <tr>\n",
" <th>8</th>\n",
" <td>gained</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>AGAIN</td>\n",
" <td>1</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" word count\n",
"0 face 1\n",
"1 was 18\n",
"2 Monkey 2\n",
"3 how 4\n",
"4 Just 1\n",
"5 for 11\n",
"6 Directories 1\n",
"7 could 4\n",
"8 gained 1\n",
"9 AGAIN 1"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.DataFrame(wordRdd.collect())\n",
"\n",
"# 设置栏位名字\n",
"df.columns = ['word', 'count']\n",
"\n",
"\n",
"# 查看前10条数据\n",
"df.head(10)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>word</th>\n",
" <th>count</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>263</th>\n",
" <td>the</td>\n",
" <td>121</td>\n",
" </tr>\n",
" <tr>\n",
" <th>271</th>\n",
" <td>to</td>\n",
" <td>57</td>\n",
" </tr>\n",
" <tr>\n",
" <th>576</th>\n",
" <td>of</td>\n",
" <td>47</td>\n",
" </tr>\n",
" <tr>\n",
" <th>358</th>\n",
" <td>and</td>\n",
" <td>45</td>\n",
" </tr>\n",
" <tr>\n",
" <th>589</th>\n",
" <td>a</td>\n",
" <td>41</td>\n",
" </tr>\n",
" <tr>\n",
" <th>797</th>\n",
" <td>is</td>\n",
" <td>38</td>\n",
" </tr>\n",
" <tr>\n",
" <th>136</th>\n",
" <td>in</td>\n",
" <td>35</td>\n",
" </tr>\n",
" <tr>\n",
" <th>593</th>\n",
" <td>I</td>\n",
" <td>32</td>\n",
" </tr>\n",
" <tr>\n",
" <th>685</th>\n",
" <td>that</td>\n",
" <td>29</td>\n",
" </tr>\n",
" <tr>\n",
" <th>645</th>\n",
" <td>The</td>\n",
" <td>26</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" word count\n",
"263 the 121\n",
"271 to 57\n",
"576 of 47\n",
"358 and 45\n",
"589 a 41\n",
"797 is 38\n",
"136 in 35\n",
"593 I 32\n",
"685 that 29\n",
"645 The 26"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 查看出现次数最多的十个单词\n",
"df =df.sort_values(by='count', ascending=False)\n",
"\n",
"\n",
"df.head(10)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"# 停止spark上下文\n",
"sc.stop()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because one or more lines are too long

@ -256,6 +256,75 @@ channel收发遵循FIFO原则其底层是hchan结构指针创建通道使
- slice - slice
- channel - channel
### 为啥 channel 会有 close 这个操作, 在哪些场景下会用到这个操作 ?
在 Go 语言中channel 的 close 操作用于向 channel 的接收方明确地通知发送操作已经完成。关闭一个 channel 可以表达“没有更多的数据将被发送到这个 channel”这一信号。这是一种控制信号帮助接收方理解数据流的生命周期并且可以避免在 channel 上进行无限等待。
#### 使用 close 的场景
1. **通知多个接收者完成处理**
当使用一个 channel 来分发任务或数据给多个协程goroutines关闭 channel 是一种告知所有接收者没有更多数据要处理的有效方法。接收者可以通过检测 channel 是否已关闭来适时停止处理。
2. **控制循环退出**
在接收数据时,可以使用 for range 循环从 channel 接收数据。当 channel 被关闭,并且 channel 中已经没有待处理的数据时for range 循环会自动结束。这使得编码简洁,并且逻辑清晰。
3. **防止资源泄露**
如果不关闭不再使用的 channel可能会导致内存资源没有得到释放特别是在 channel 还保持着一些数据项的情况下。尽管 Go 的垃圾回收机制会回收未引用的对象,但显式关闭 channel 是一个好的实践,它可以清晰地表达程序设计者的意图。
4. **使用 select 的默认操作**
在使用 select 语句处理多个 channel 的时候,关闭一个 channel 可以用于触发其他 case 的执行。特别是在一些需要优雅退出的并发模式中,关闭 channel 可以促使 select 快速响应并处理结束逻辑。
#### 示例:数据处理和广播信号
假设有一个数据处理任务,需要将数据分批发送到多个处理协程,处理完成后再汇总结果。这里可以使用关闭 channel 的方式来告知所有处理协程,数据已经发送完毕:
```go
func processData(dataChunks [][]int) []int {
var results []int
resultChan := make(chan int)
dataChan := make(chan int, 100)
// 启动多个工作协程
for i := 0; i < 5; i++ {
go func() {
for data := range dataChan {
result := process(data) // 假设有一个处理函数
resultChan <- result
}
}()
}
// 发送数据
go func() {
for _, chunk := range dataChunks {
for _, data := range chunk {
dataChan <- data
}
}
close(dataChan)
}()
// 接收结果
go func() {
for i := 0; i < len(dataChunks); i++ {
result := <-resultChan
results = append(results, result)
}
close(resultChan)
}()
return results
}
```
在这个示例中,通过关闭 dataChan 来告知工作协程不会再有新的数据发送,这时协程可以结束从 channel 接收数据的操作。关闭 resultChan 则用来表示所有结果已经处理完毕,可以进行后续步骤。
总结来说,关闭一个 channel 是一种向接收方传递完成信号的方法,它在多协程协作的环境中尤为有用,有助于提高代码的可读性和安全性。
## Go如何避免内存的对象频繁分配和回收的问题 ## Go如何避免内存的对象频繁分配和回收的问题
可以考虑使用对象缓存池sync.Pool 可以考虑使用对象缓存池sync.Pool
@ -877,6 +946,101 @@ func As(err error, target interface{}) bool // 判断err是否为target类型
[一篇文章带你轻松搞懂Golang的error处理_Golang_脚本之家](https://www.jb51.net/article/254917.htm) [一篇文章带你轻松搞懂Golang的error处理_Golang_脚本之家](https://www.jb51.net/article/254917.htm)
## Go错误处理机制为啥不采用Java的try-catch的异常机制
Go 语言选择不使用 Java 中的异常机制而是采用返回错误error的方式处理异常情况这主要是基于几个设计目标和考虑
- **简明性和可预测性**:在 Go 语言中,错误被视为常见的、可预料的结果,而不是异常情况。通过显式地返回错误,程序员被迫处理错误,这可以使得错误处理更加显式和清晰,减少了忽视错误处理的可能性。
- **控制流简单化**:使用异常机制时,代码的执行流可以因为异常的抛出而在任何点被中断,这使得程序的控制流变得复杂和难以跟踪。相反,通过返回错误,错误处理和正常逻辑清晰地分离,控制流更加直观。
- **性能考虑**:异常处理机制通常涉及栈解 unwinding 过程这在性能上可能带来开销。Go 语言通过简单的值返回避免了这种开销。
- **交叉语言调用简化**Go 语言在设计时考虑到了与 C 语言的互操作性。在 C 语言中没有异常机制使用错误码是常见做法。Go 的错误处理方式与之兼容,简化了跨语言调用的复杂性。
关于是否是一个好的设计,这取决于具体的使用场景和个人偏好。这种设计强化了错误处理的重要性,并鼓励开发者更加关注程序可能出现的错误情况,从而可能增强程序的健壮性。但是,这也可能导致代码中充满大量的错误处理逻辑,有时可能显得冗余。
Java 的异常机制有其优点,特别是在错误需要跨多个调用层级传播时,异常提供了一种非常便捷的方式。然而,它也有一些常见的问题:
- **异常被忽略**Java 中的异常可以被捕获后不做任何处理,这可能隐藏程序中的错误。
- **代码复杂性**:异常的抛出和捕获可能使得程序逻辑变得难以理解和维护,特别是当异常可以在多个层级被抛出和捕获时。
- **性能问题**:异常处理可能引入性能损耗,特别是在异常频繁抛出的场景中。
总体来说Go 的错误处理方式倾向于更加显式和可控,而 Java 的异常机制则提供了一种灵活但有时可能不够清晰的错误处理策略。选择哪种方式更好,很大程度上取决于特定项目的需求和开发团队的偏好。
## Go为什么采用组合机制而不是使用继承机制
Go 语言没有传统意义上的类和继承机制,这是其设计哲学中的一部分,旨在简化语言和避免常见的面向对象编程的一些复杂性和问题。下面是 Go 语言这样设计的一些原因及其替代方式:
### 为什么 Go 没有传统的继承?
- **简化语言设计**Go 的设计哲学是保持语言的简洁和高效。继承是一个强大但复杂的功能,可以导致多种编程问题,如复杂的依赖关系和难以预测的行为。
- **避免继承带来的问题**
- **脆弱的基类问题**:基类的改变可能影响到大量的派生类。
- **深层继承结构导致的复杂性**:随着继承链的增长,理解和维护代码变得更加困难。
- **多重继承的复杂性**:如 C++ 中的多重继承可能导致菱形继承问题,增加了语言和编译器的复杂性。
### Go 如何实现多态?
尽管 Go 没有继承,它通过接口来支持多态性。在 Go 中,接口是一组方法签名的集合,任何类型只要实现了这些方法,就被认为实现了该接口。这种方式与继承不同,更加灵活和简洁:
- **接口隐式实现**:类型不需要声明它实现了哪个接口,这降低了代码之间的耦合。
- **组合优于继承**Go 通过组合(有时候通过嵌入结构体)来实现代码的复用,这比继承更加直接和清晰。
### Embedded Struct 算不算继承?
Embedded struct嵌入结构体在 Go 中被用作实现类似继承的功能,但它更准确地被描述为组合。通过嵌入一个结构体,一个新的结构体可以直接访问嵌入结构体的方法和字段,这提供了一种方式来复用代码:
- **不是真正的继承**:虽然看起来类似,嵌入结构体并不提供传统意义上的多态。
- **代码复用和扩展**:它允许一种灵活的方式来扩展功能,而无需继承的复杂性。
### 传统继承的问题
- **过度耦合**:子类和父类之间的关系过于紧密,改动父类可能会影响所有子类。
- **隐藏的复杂性**:继承可以导致代码的行为不透明,增加理解和调试的难度。
- **难以正确使用**:正确地设计和维护一个继承体系需要大量的设计经验和技术洞察力。
Go 的设计选择鼓励开发者采用更简单、更易于理解和维护的编程范式。通过接口和组合Go 提供了一种强大的工具集来建构灵活且可维护的代码结构,避免了许多传统面向对象编程中常见的陷阱。
### Go 中 channel 跟 Java 中 BlockingQueue 又有啥区别 ?
Go 的 channel 和 Java 的 BlockingQueue 都是用于不同线程或协程间的通信机制,但它们的设计哲学和使用场景有所不同。这两种机制都用于解决并发编程中的同步问题,但具体的实现和适用的场景有差异。
### Channel 与 BlockingQueue 的区别
1. 设计哲学:
- Go 的 ChannelChannel 是 Go 语言中的一等公民用于在协程goroutines之间进行通信。它遵循“通过通信来共享内存而不是通过共享内存来通信”的哲学。
- Java 的 BlockingQueue是 Java 并发包中的一部分,主要用于线程间的通信,尤其在生产者-消费者模型中。它依赖于共享内存和锁来实现线程安全。
2. 功能实现:
- Channel 支持多种模式,如无缓冲、有缓冲通道,可以非常灵活地控制协程间的数据流和同步。
- BlockingQueue 是一个接口Java 提供了多种实现(如 ArrayBlockingQueue, LinkedBlockingQueue主要通过阻塞操作来实现生产者和消费者之间的同步。
3. 用途和应用场景:
- Channel 通常用于协程间的信号传递和数据交换,特别是在需要控制并发操作顺序时。
- BlockingQueue 通常用于处理较大的数据流或者在多线程环境下缓存数据。
### 共享内存并发 vs. Channel 并发
#### 共享内存并发
- 适用场景:适合复杂的数据结构共享,或者当有多个线程需要访问和修改同一数据时。在多核处理器上,这种方式可以有效利用缓存一致性协议。
- 优点:可以实现细粒度的控制,对于某些高性能计算场景可以更直接地管理内存。
- 缺点:容易产生竞态条件,编程模型更加复杂,需要精确地控制锁和同步。
#### Channel 并发
- 适用场景:适合事件驱动或消息驱动的应用,如网络服务或并行数据处理。在这些场景中,通信模式清晰,各部分之间的解耦更彻底。
- 优点:简化了并发和同步的管理,代码通常更易于理解和维护。
- 缺点:在极端的高性能需求下,可能会因为消息传递的开销而不如直接的内存访问高效。
#### 选择建议
- 如果问题适合通过明确的消息传递进行模块化设计,或者当系统的可维护性和清晰的并发模型比原始性能更重要时,使用 Channel。
- 如果需要最大限度地控制性能,并且可以管理更复杂的同步策略和竞态风险,使用共享内存可能更合适。
在实际开发中选择合适的并发策略依赖于具体问题、性能需求和团队的熟悉度。对于维护性和开发效率有较高要求的项目Channel 往往是一个更易于管理的选择。
## 资料 ## 资料
[【Golang开发面经】蔚来两轮技术面](https://zhuanlan.zhihu.com/p/574580955) [【Golang开发面经】蔚来两轮技术面](https://zhuanlan.zhihu.com/p/574580955)

@ -36,8 +36,14 @@ nav:
- 镜像: container/image.md - 镜像: container/image.md
- cgroup: container/cgroup.md - cgroup: container/cgroup.md
- namespace: container/namespace.md - namespace: container/namespace.md
- 语言: - 开发语言:
- Go: language/Go.md - Go: language/Go.md
- Jupyter:
- Go-Frameworks-Github-Fork-Stats: jupyter/Go-Frameworks-Github-Fork-Stats.ipynb
- Pandas完全指南: jupyter/Pandas完全指南.ipynb
- Spark上手示例:
- jupyter/Spark上手示例1RDD操作.ipynb
- jupyter/Spark上手示例2DataFrame操作.ipynb
- QA: - QA:
- redis: qa/redis.md - redis: qa/redis.md
- mysql: qa/mysql.md - mysql: qa/mysql.md
@ -48,7 +54,7 @@ nav:
- 消息队列: qa/queue.md - 消息队列: qa/queue.md
- IO: qa/io.md - IO: qa/io.md
- protobuf: qa/protobuf.md - protobuf: qa/protobuf.md
- go: qa/go.md - go: qa/go.md
- 分布式: qa/dist.md - 分布式: qa/dist.md
- Elasticsearch: qa/es.md - Elasticsearch: qa/es.md
- docker: qa/docker.md - docker: qa/docker.md
@ -118,7 +124,12 @@ theme:
plugins: plugins:
- search: - search:
separator: '[\s\u200b\-]' separator: '[\s\u200b\-_,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'
- git-revision-date-localized:
type: iso_date
- glightbox
- mkdocs-jupyter
- print-site
# Additional configuration # Additional configuration
extra: extra:

Loading…
Cancel
Save