Giter VIP home page Giter VIP logo

learngo's Introduction

##all practice in 《入门GO》
#predict outcome
1. testmain.go
2. count_characters.go  创建一个用于统计字节和字符(rune)的程序,并对字符串 asSASA ddd dsjkdsjs dk 进行分析,然后再分析 asSASA ddd dsjkdsjsこん dk,最后解释两者不同的原因(提示:使用 unicode/utf8 包
3. string_conversion2.go 尝试改写 string_conversion2.go 中的代码,要求使用 := 方法来对 err 进行赋值,哪些地方可以被修改?
4. season.go 写一个 Season 函数,要求接受一个代表月份的数字,然后返回所代表月份所在季节的名称(不用考虑月份的日期)
5. for_loop.go  使用 for 结构创建一个简单的循环。要求循环 15 次然后使用 fmt 包来打印计数器的值。
                使用 goto 语句重写循环,要求不能使用 for 关键字。
6. for_character.go 创建一个程序,要求能够打印类似下面的结果(直到每行 25 个字符时为止):G
                                                         GG
                                                         GGG
                                                         GGGG
                                                         GGGGG
                                                         GGGGGG
                                                         使用 2 层嵌套 for 循环。
                                                         使用一层 for 循环以及字符串截断
7. bitwise_complement.go 使用按位补码从 0 到 10,使用位表达式 %b 来格式化输出
8. fizzbuzz.go 写一个从 1 打印到 100 的程序,但是每当遇到 3 的倍数时,不打印相应的数字,但打印一次 "Fizz"。遇到 5 的倍数时,打印 Buzz 而不是相应的数字。对于同时为 3 和 5 的倍数的数,打印 FizzBuzz(提示:使用 switch 语句)。
9. rectangle_stars.go 使用 * 符号打印宽为 20,高为 10 的矩形
10. mult_returnval.go  编写一个函数,接收两个整数,然后返回它们的和、积与差。编写两个版本,一个是非命名返回值,一个是命名返回值
11. error_returnval.go 编写一个名字为 MySqrt 的函数,计算一个 float64 类型浮点数的平方根,如果参数是一个负数的话将返回一个错误。编写两个版本,一个是非命名返回值,一个是命名返回值
12. varargs.go 写一个函数,该函数接受一个变长参数并对每个元素进行换行打印
13. fibonacci.go 重写本节中生成斐波那契数列的程序并返回两个命名返回值(详见第 6.2 节),即数列中的位置和对应的值,例如 5 与 4,89 与 10
14. recursive.go 使用递归函数从 10 打印到 1
15. jiecheng.go 实现一个输出前 30 个整数的阶乘的程序 (使用了 math/big.Int 的Mul)
16. string_changeAscii.go 包 strings 中的 Map 函数和 strings.IndexFunc() 一样都是非常好的使用例子。请学习它的源代码并基于该函数书写一个程序,要求将指定文本内的所有非 ASCII 字符替换成 ? 或空格。您需要怎么做才能删除这些字符呢
17. clojure.go 6.8闭包练习在 main 函数中写一个用于打印 Hello World 字符串的匿名函数并赋值给变量 fv,然后调用该函数并打印变量 fv 的类型
18. fibonacci2.go 不使用递归但使用闭包改写第 6.6 节中的斐波那契数列程序
19. factory_clojure.go 工厂函数(factory pattern in GO)
20. calculate_func_time.go 计算函数执行时间
chapter 7
21. array_value.go: 证明当数组赋值时,发生了数组内存拷贝
22. for_array.go: 写一个循环并用下标给数组赋值(从 0 到 15)并且将数组打印在屏幕上
23. fobinacci_funcarray.go: 为练习 7.3 写一个新的版本,主函数调用一个使用序列个数作为参数的函数,该函数返回一个大小为序列个数的 Fibonacci 切片
24. slice_len_cap.go 给定 s := make([]byte, 5),len(s) 和 cap(s) 分别是多少?s = s[2:4],len(s) 和 cap(s) 又分别是多少
25. slice_case1.go 假设 s1 := []byte{'p', 'o', 'e', 'm'} 且 s2 := s1[2:],s2 的值是多少?如果我们执行 s2[1] = 't',s1 和 s2 现在的值又分别是多少
26. slice_append.go 给定切片 sl,将一个 []byte 数组追加到 sl 后面。写一个函数 Append(slice, data []byte) []byte,该函数在 sl 不能存储更多数据的时候自动扩容
27. slice_buffer.go 把一个缓存 buf 分片成两个 切片:第一个是前 n 个 bytes,后一个是剩余的,用一行代码实现
28. slice_double.go 假设我们有如下数组:items := [...]int{10, 20, 30, 40, 50}
                a) 如果我们写了如下的 for 循环,那么执行完 for 循环后的 items 的值是多少?如果你不确定的话可以测试一下:)
                   for _, item := range items {
                         	item *= 2
                   }
                b) 如果 a) 无法正常工作,写一个 for 循环让值可以 double。
29. slice_sum.go 通过使用省略号操作符 ... 来实现累加方法
30. sum_array.go
    a) 写一个 Sum 函数,传入参数为一个 32 位 float 数组成的数组 arrF,返回该数组的所有数字和。
    如果把数组修改为切片的话代码要做怎样的修改?如果用切片形式方法实现不同长度数组的的和呢?
    b) 写一个 SumAndAverage 方法,返回两个 int 和 float32 类型的未命名变量的和与平均值。
31. min_max.go 写一个 minSlice 方法,传入一个 int 的切片并且返回最小值,再写一个 maxSlice 方法返回最大值。
32. slice_enlarge.go 给定 slice s[]int 和一个 int 类型的因子,扩展 s 使其长度为 len(s) * factor
33. slice_filter.go 用顺序函数过滤容器:s 是前 10 个整型的切片。构造一个函数 Filter,第一个参数是 s,第二个参数是一个 fn func(int) bool,返回满足函数 fn 的元素切片。通过 fn 测试方法测试当整型值是偶数时的情况。
34. slice_insert.go 写一个函数 InsertStringSlice 将切片插入到另一个切片的指定位置, 关键是make扩展, copy 返回了完成后的index
35. slice_remove.go 写一个函数 RemoveStringSlice 将从 start 到 end 索引的元素从切片 中移除, 关键是make改变大小, copy 返回了完成后的index
36. split_string.go 编写一个函数,要求其接受两个参数,原始字符串 str 和分割索引 i,然后返回两个分割后的字符串
37. 假设有字符串 str,那么 str[len(str)/2:] + str[:len(str)/2] 的结果是什么? len/2位置扭转
38. tort_string.go 编写一个程序,要求能够反转字符串,即将 “Google” 转换成 “elgooG”(提示:使用 []byte 类型的切片)。
    如果您使用两个切片来实现反转,请再尝试使用一个切片(提示:使用交换法)。
    如果您想要反转 Unicode 编码的字符串,请使用 []int32 类型的切片。
    关键是slice的交换,runes[i], runes[n-1-i] = runes[n-1-i], runes[i]
39. slice_unique.go 编写一个程序,要求能够遍历一个数组的字符,并将当前字符和前一个字符不相同的字符拷贝至另一个数组。
40. slice_bubblesort.go 编写一个程序,使用冒泡排序的方法排序一个包含整数的切片(算法的定义可参考 维基百科)。
41. slice_map.go 在函数式编程语言中,一个 map-function 是指能够接受一个函数原型和一个列表,并使用列表中的值依次执行函数原型,公式为:map ( F(), (e1,e2, . . . ,en) ) = ( F(e1), F(e2), ... F(en) )。
    编写一个函数 mapFunc 要求接受以下 2 个参数:
    一个将整数乘以 10 的函数
    一个整数列表
    最后返回保存运行结果的整数列表。

Map chapter 8
42. map_week.go 创建一个 map 来保存每周 7 天的名字,将它们打印出来并且测试是否存在 Tuesday 和 Hollyday
43. map_drink.go 构造一个将英文饮料名映射为法语(或者任意你的母语)的集合;先打印所有的饮料,然后打印原名和翻译后的名字。接下来按照英文名排序后再打印出来

package chapter 9
44. dlinked_list.go 使用 container/list 包实现一个双向链表,将 101、102 和 103 放入其中并打印出来
45. int_size.go 通过使用 unsafe 包中的方法来测试你电脑上一个整型变量占用多少个字节
46. main_greetings.go 创建一个程序 main_greetings.go 能够和用户说 "Good Day" 或者 "Good Night"。不同的问候应该放到 greetings 包中
    在同一个包中创建一个 ISAM 函数返回一个布尔值用来判断当前时间是 AM 还是 PM,同样创建 IsAfternoon 和 IsEvening 函数。
    使用 main_greetings 作出合适的问候(提示:使用 time 包)。
47. 创建一个程序 main_oddven.go 判断前 100 个整数是不是偶数,包内同时包含测试的功能

struct chapter 10
48. vcard.go定义结构体 Address 和 VCard,后者包含一个人的名字、地址编号、出生日期和图像,试着选择正确的数据类型。构建一个自己的 vcard 并打印它的内容。
49. 修改 persionext1.go,使它的参数 upPerson 不是一个指针,解释下二者的区别, 值传递,拷贝,不能修改原值
50. point.go 使用坐标 X、Y 定义一个二维 Point 结构体。同样地,对一个三维点使用它的极坐标定义一个 Polar 结构体。实现一个 Abs() 方法来计算一个 Point 表示的向量的长度,实现一个 Scale 方法,它将点的坐标乘以一个尺度因子(提示:使用 math 包里的 Sqrt 函数)(function Scale that multiplies the coordinates of a point with a scale factor)
51. rectangle.go 定义一个 Rectangle 结构体,它的长和宽是 int 类型,并定义方法 Area() 和 Primeter(),然后进行测试
52. anonymous_struct.go 创建一个结构体,它有一个具名的 float 字段,2 个匿名字段,类型分别是 int 和 string。通过结构体字面量新建一个结构体实例并打印它的内容
53. employee_salary.go 定义结构体 employee,它有一个 salary 字段,给这个结构体定义一个方法 giveRaise 来按照指定的百分比增加薪水。
54. inheritance_car.go, 创建一个上面 Car 和 Engine 可运行的例子,并且给 Car 类型一个 wheelCount 字段和一个 numberOfWheels() 方法。
    创建一个 Mercedes 类型,它内嵌 Car,并新建 Mercedes 的一个实例,然后调用它的方法, 然后仅在 Mercedes 类型上创建方法 sayHiToMerkel() 并调用它。
55. point_methods.go 从 point.go 开始(第 10.1 节的练习):使用方法来实现 Abs() 和 Scale()函数,Point 作为方法的接收者类型。也为 Point3 和 Polar 实现 Abs() 方法。完成了 point.go 中同样的事情,只是这次通过方法
56.  inherit_methods.go 定义一个结构体类型 Base,它包含一个字段 id,方法 Id() 返回 id,方法 SetId() 修改 id。结构体类型 Person 包含 Base,及 FirstName 和 LastName 字段。结构体类型 Employee 包含一个 Person 和 salary 字段
57. magic.go 预测输出, 多态, 方法重载的使用
58. celsius.go 为 float64 定义一个别名类型 Celsius,并给它定义 String(),它输出一个十进制数和 °C 表示的温度值。关键: strconv.FormatFloat(float64(c), 'f', 1, 32)
59. days.go 为 int 定义一个别名类型 Day,定义一个字符串数组它包含一周七天的名字,为类型 Day 定义 String() 方法,它输出星期几的名字。使用 iota 定义一个枚举常量用于表示一周的中每天(MO、TU...)
60.  stack_arr.go/stack_struct.go 实现栈(stack)数据结构:
     它的格子包含数据,比如整数 i、j、k 和 l 等等,格子从底部(索引 0)至顶部(索引 n)来索引。这个例子中假定 n=3,那么一共有 4 个格子。
     一个新栈中所有格子的值都是 0。
     push 将一个新值放到栈的最顶部一个非空(非零)的格子中。
     pop 获取栈的最顶部一个非空(非零)的格子的值。现在可以理解为什么栈是一个后进先出(LIFO)的结构了吧。
     为栈定义一 Stack 类型,并为它定义一个 Push 和 Pop 方法,再为它定义 String() 方法(用于调试)它输出栈的内容,比如:[0:i] [1:j] [2:k] [3:l]。
     1)stack_arr.go:使用长度为 4 的 int 数组作为底层数据结构。
     2)stack_struct.go:使用包含一个索引和一个 int 数组的结构体作为底层数据结构,索引表示第一个空闲的位置。 3)使用常量 LIMIT 代替上面表示元素个数的 4 重新实现上面的 1)和 2),使它们更具有一般性。
61.从练习 10.16 开始(它基于结构体实现了一个栈结构),为栈的实现(stack_struct.go)创建一个单独的包 stack,并从 main 包 main.stack.go 中调用它
interface chapter 11
62. simple_interface.go 定义一个接口 Simpler,它有一个 Get() 方法和一个 Set(),Get()返回一个整型值,Set() 有一个整型参数。创建一个结构体类型 Simple 实现这个接口。
    接着定一个函数,它有一个 Simpler 类型的参数,调用参数的 Get() 和 Set() 方法。在 main 函数里调用这个函数,看看它是否可以正确运行
63. simple_interface2.go, 接着练习 11.1 中的内容,创建第二个类型 RSimple,它也实现了接口 Simpler,写一个函数 fi,使它可以区分 Simple 和 RSimple 类型的变量, 直接改在simple_interface.go上
64. simple_interface3.go, 继续 练习11.2,在它中添加一个 gI 函数,它不再接受 Simpler 类型的参数,而是接受一个空接口参数。然后通过类型断言判断参数是否是 Simpler 类型。最后在 main 使用 gI 取代 fI 函数并调用它。确保你的代码足够安全, 直接改在simple_interface.go上
65. min_interface.go/minmain.go, 模仿stack,实现min_interface得到数组的最小值接口(int, string array), 创建main来测试
66. map_function_interface.go 在练习 7.13 中我们定义了一个 map 函数来使用 int 切片 (map_function.go),
    通过空接口和类型断言,现在我们可以写一个可以应用于许多类型的 泛型 的 map 函数,为 int 和 string 构建一个把 int 值加倍和连接字符串值的 map 函数 mapFunc
67. map_function_interface_var.go, 稍微改变练习 11.9,允许 mapFunc 接收不定数量的 items
68. main_stack.go—stack/stack_general.go 在练习 10.10 和 10.11 中我们开发了一些栈结构类型。但是它们被限制为某种固定的内建类型。现在用一个元素类型是 interface{}(空接口)的切片开发一个通用的栈类型
    实现下面的栈方法:
    Len() int
    IsEmpty() bool
    Push(x interface{})
    Pop() (x interface{}, error)
    Pop() 改变栈并返回最顶部的元素;Top() 只返回最顶部元素。
    在主程序中构建一个充满不同类型元素的栈,然后弹出并打印所有元素的值。

chapter 12 read/write
69. word_letter_count.go, 编写一个程序,从键盘读取输入。当用户输入 'S' 的时候表示输入结束,这时程序输出 3 个数字:
    i) 输入的字符的个数,包括空格,但不包括 '\r' 和 '\n'
    ii) 输入的单词的个数
    iii) 输入的行数
70. calculator.go 编写一个简单的逆波兰式计算器,它接受用户输入的整型数(最大值 999999)和运算符 +、-、*、/。
    输入的格式为:number1 ENTER number2 ENTER operator ENTER --> 显示结果
    当用户输入字符 'q' 时,程序结束。请使用您在练习11.3中开发的 stack 包
71. wiki_part1.go, 程序中的数据结构如下,是一个包含以下字段的结构:
    type Page struct {
        Title string
        Body  []byte
    }
    请给这个结构编写一个 save 方法,将 Title 作为文件名、Body作为文件内容,写入到文本文件中。
    再编写一个 load 函数,接收的参数是字符串 title,该函数读取出与 title 对应的文本文件。请使用 *Page 做为参数,因为这个结构可能相当巨大,我们不想在内存中拷贝它。请使用 ioutil 包里的函数(参考章节12.2.1)。
72. hash_md5.go 利用crypto/md5包来校验md5

charpter 13 错误处理
73. panic_defer_convint.go 写一个 ConvertInt64ToInt 函数把 int64 值转换为 int 值,如果发生错误(提示:参见 4.5.2.1 节)就 panic。然后在函数 IntFromInt64 中调用这个函数并 recover,返回一个整数和一个错误。请测试这个函数!

charpter 14 goroutine channel
74. channel_block3.go:写一个通道证明它的阻塞性,开启一个协程接收通道的数据,持续 15 秒,然后给通道放入一个值。在不同的阶段打印消息并观察输出
75. gosum.go:用这种习惯用法写一个程序,开启一个协程来计算2个整数的合并等待计算结果并打印出来
76. producer_consumer.go:用这种习惯用法写一个程序,有两个协程,第一个提供数字 0,10,20,...90 并将他们放入通道,第二个协程从通道中读取并打印。main() 等待两个协程完成后再结束
77. channel_buffer.go:给 channel_block3.go 的通道增加缓冲并观察输出有何不同
78. random_bitgen.go 做一个随机位生成器,程序可以提供无限的随机 0 或者 1 的序列

charpter 15 网络
79. webhello2.go 编写一个网页服务器监听端口9999,有如下处理函数:
当请求http://localhost:9999/hello/Name时,响应:hello Name(Name需是一个合法的姓,比如Chris或者Madeleine)
当请求http://localhost:9999/shouthello/Name时,响应:hello NAME
关键在于 *http.Request 对象关于 PATH的获取, req.URL.Path[len("/hello/"):]
80. hello_server.go创建一个空结构hello并使它实现http.Handler。运行并测试。




#use case
1. type.go   类型别名
2. char.go   Unicode 字符
3. presuffix.go 判断string的前缀后缀
4. index_in_string.go  索引string
5. count_substring.go 统计子字符串
6. repeat_string.go 重复字符串创建
7. string_splitjoin.go 字符串split,join
8. string_conversion.go  字符串转其他类型
9. time.go 时间处理
10. string_pointer.go 字符串指针
11. ifelse.go if/else的简单例子
12. switch.go switch 例子1
13. switch2.go switch 例子2
14. for.go for循环例子
15. for_range.go for-range例子
16. goto.go goto/label例子
17. side_effect.go 改变外部变量(函数内部)副作用
18. defer.go defer例子
19. package_test.go 测试使用自建package (pack1/pack1.go)
20. fibonacci_memory.go 使用slice/array来提升性能,在fibonacci函数中
21. pointer_array.go 关于array的值传递和引用传递的例子
22. multidim_array.go 多维数组例子
23. array_sum.go 传递数组给函数, 不常见,多用slice,而不是数组指针
24. array_slice.go 数组和slice的例子
25. make_slice.go make创建slice
26. reslicing.go 切片重组
27.  copy_append_slice.go, 切片复制和追加
28. make_map.go , 创建map
29. map_testelement.go map 元素设置,修改,获取,删除
30. map_forrange2.go map类型的slice使用
31. map_sort.go 对map进行排序,关键是使用sort包
32. pattern.go regexp 包使用, 其中的compile, ReplaceAllString, ReplaceAllStringFunc等方法
33. big.go big包使用, NewInt, NewRat, Mul, Add等方法
34. person.go struct的定义,创建,初始化的例子
35. struct_tag.go struct 可以自带tag,例子, 标签的内容不可以在一般的编程中使用,只有包 reflect 能获取它, 就可以通过 Field 来索引结构体的字段,然后就可以使用 Tag 属性
36. structs_anonymous_fields.go struct 可以包含一个或多个 匿名(或内嵌)字段,即这些字段没有显式的名字,只有字段的类型是必须的,此时类型就是字段的名字。匿名字段本身可以是一个结构体类型,即 结构体可以包含内嵌结构体
37. method.go struct 的方法例子
38. method_on_time.go 在外部包的struct上直接定义方法是不行的,必须先别名到自己的包中
39. method3.go 内嵌struct, 定义的方法能直接被外层类型调用
40. embed_func1.go 类型中嵌入功能, 聚合(或组合), 内嵌
41. method_string.go String方法实现, printf中 %v, %T, %#v 的使用
42. interfaces.go 接口例子
43. valuable.go 多态,多个struct实现一个接口
44. type_interfaces.go 类型断言例子 var.(T) , 与if结合
45. sort.go/sortmain.go 一个完整的例子sort包的sort实现了sort interface, 并实现了IntArray和StringArray类型的定义,实现sort接口, sortmain中测试了ints和strings, 并定义了day/dayArray类型,实现sort接口
46. empty_interface.go 空接口例子, 空接口作用!, 类似Object, 各种适配
47. emptyint_switch.go, 空接口和type-switch结合的例子, 联合lamba用法
48. reflect1.go, reflect包的例子, TypeOf, Kind, Float, Interface等方法
49. reflect2.go, reflect包的例子, Method利用等
50. readinput1.go 从控制台输入例子, 从键盘和标准输入 os.Stdin 读取输入,最简单的办法是使用 fmt 包提供的 Scan 和 Sscan 开头的函数
51. readinput2.go 带换存的读取, 使用 bufio 包提供的缓冲读取(buffered reader)来读取数据
52.  fileinput.go 读取文件的例子, 使用os.Open, close file等, 然后利用bufio 按行读取, error == io.EOF
53. read_write_file1.go, 读取文件到一个string中, ioutil包, 到[]byte
54. read_file2.go, 按列读取, fmt包的FScan方法,
55. gzipped.go, 压缩文件读取例子, compress/gzip包使用, 逻辑还是获取到reader, 然后ReadString('\n')
56. fileoutput.go 写文件的例子, 逻辑打开文件(模式), bufio的writer可以写, flush, 然后close
57. filecopy.go 文件copy的例子, 利用io包Copy方法
58. os_args.go 命令行参数的例子, 读取os.Args
59. echo.go 模拟echo的功能, 利用flag包, flag 包有一个扩展功能用来解析命令行选项。但是通常被用来替换基本常量
60. cat2.go 利用os.file Read 方法, 和 slice byte 来读取
61. json.go json的处理, 利用encoding/json包, 主要Marshal和Unmarshal方法
62. xml.go xml的处理, 利用encoding/xml包
63. gob1.go gob是go特有的序列化和反序列化, encoding/gob包, 也是io.Writer接口, NewEncoder()方法创建Encoder来Encode(), 反之NewDecoder创建Decoder
64. hash_sha1.go 加密 sha1和md5, 利用crypto/sha1包
65. errors.go 定义错误,  errors.New("Not found error")
66. panic.go 使用panic 例子
67. panic_recover.go 从panic 恢复, defer func() {if e := recover(); e != nil {}} ()
68. goroutine_select.go goroutine的例子, 用select来处理chan
69. goroutine2.go 通过chan来对goroutine进行通信
70. channel_block.go chan的阻塞功能例子
71. timer_goroutine.go goroutine和计时器的组合, 里面包含多个timer和goroutine的组合模式, 超时, 先到先得等
72. server.go 一个简单的server, 利用net包, net.Listen, listener.Accept, 获取连接net.Conn, conn.Read, 这个步骤跟java是类似的
73. client.go 一个简单的client,net包, net.Dial 获取conn, 然后 write
74. simple_tcp_server_v1.go 一个完整的tcp server例子, 包含读取命令行参数(flag), server(net.ResolveTCPAddr, net.ListenTCP), listener.Accept, 用到了panic
75. hello_world_webserver.go 一个简单的http web server, net/http包, http.ListenAndServe, http.HandleFunc
76. poll_url.go 访问, 读取页面, http.Head , Get 等

learngo's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.