阿振sc

Results 101 issues of 阿振sc

# Go经典入门26:组合取代继承 `Go` 不支持继承,但它支持组合(`Composition`)。组合一般定义为“合并在一起”。汽车就是一个关于组合的例子:一辆汽车由车轮、引擎和其他各种部件组合在一起。 ## 通过嵌套结构体进行组合 在 `Go` 中,通过在结构体内嵌套结构体,可以实现组合。 组合的典型例子就是博客帖子。每一个博客的帖子都有标题、内容和作者信息。使用组合可以很好地表示它们。通过学习本教程后面的内容,我们会知道如何实现组合。 我们首先创建一个 `author` 结构体。 ```go package main import ( "fmt" ) type author struct { firstName string lastName string bio string...

# Go经典入门25:结构体取代类 ## Go 支持面向对象吗? `Go` 并不是完全面向对象的编程语言。`Go` 官网的回答了 `Go` 是否是面向对象语言,摘录如下。 > 可以说是,也可以说不是。虽然 Go 有类型和方法,支持面向对象的编程风格,但却没有类型的层次结构。Go 中的“接口”概念提供了一种不同的方法,我们认为它易于使用,也更为普遍。Go 也可以将结构体嵌套使用,这与子类化(Subclassing)类似,但并不完全相同。此外,Go 提供的特性比 C++ 或 Java 更为通用:子类可以由任何类型的数据来定义,甚至是内建类型(如简单的“未装箱的”整型)。这在结构体(类)中没有受到限制。 在接下来的教程里,我们会讨论如何使用 `Go` 来实现面向对象编程概念。与其它面向对象语言(如 `Java`)相比,`Go` 有很多完全不同的特性。 ## 使用结构体,而非类 `Go` 不支持类,而是提供了结构体。结构体中可以添加方法。这样可以将数据和操作数据的方法绑定在一起,实现与类相似的效果。...

# Go经典入门24:Mutex 今天我们学习 `Mutex` 以及怎样通过 `Mutex` 和信道来处理竞态条件(`Race Condition`)。 ## 临界区 在学习 `Mutex` 之前,我们需要理解并发编程中临界区(`Critical Section`)的概念。当程序并发地运行时,多个 `Go` 协程不应该同时访问那些修改共享资源的代码。这些修改共享资源的代码称为临界区。例如,假设我们有一段代码,将一个变量 `x` 自增 1。 ```go x = x + 1 ``` 如果只有一个 `Go` 协程访问上面的代码段,那都没有任何问题。 但当有多个协程并发运行时,代码却会出错,让我们看看究竟是为什么吧。简单起见,假设在一行代码的前面,我们已经运行了两个...

# Go经典入门23:Select ## 什么是 select? `select` 语句用于在多个发送/接收信道操作中进行选择。`select` 语句会一直阻塞,直到发送/接收操作准备就绪。如果有多个信道操作准备完毕,`select` 会随机地选取其中之一执行。该语法与 `switch` 类似,所不同的是,这里的每个 `case` 语句都是信道操作。我们好好看一些代码来加深理解吧。 ```go package main import ( "fmt" "time" ) func server1(ch chan string) { time.Sleep(6 * time.Second) ch

# Go经典入门22:缓冲信道和工作池 ## 什么是缓冲信道? 在上一教程里,我们讨论的主要是无缓冲信道。我们在 `Channel` 的教程里详细讨论了,无缓冲信道的发送和接收过程是阻塞的。 我们还可以创建一个有缓冲(`Buffer`)的信道。只在缓冲已满的情况,才会阻塞向缓冲信道(`Buffered Channel`)发送数据。同样,只有在缓冲为空的时候,才会阻塞从缓冲信道接收数据。 通过向 `make` 函数再传递一个表示容量的参数(指定缓冲的大小),可以创建缓冲信道。 ```go ch := make(chan type, capacity) ``` 要让一个信道有缓冲,上面语法中的 `capacity` 应该大于 0。无缓冲信道的容量默认为 0,因此我们在上一教程创建信道时,省略了容量参数。 我们开始编写代码,创建一个缓冲信道。 示例一 ```go package main import...

# Go经典入门21:Channel 前面我们探讨了如何使用 `Go` 协程(`Goroutine`)来实现并发。接下来我们学习信道(`Channel`),看看如何通过信道来实现 `Go` 协程间的通信。 ## 什么是信道? 信道可以想像成 `Go` 协程之间通信的管道。如同管道中的水会从一端流到另一端,通过使用信道,数据也可以从一端发送,在另一端接收。 ## 信道的声明 所有信道都关联了一个类型。信道只能运输这种类型的数据,而运输其他类型的数据都是非法的。 `chan T` 表示 `T` 类型的信道。 信道的零值为 `nil`。信道的零值没有什么用,应该像对 `map` 和切片所做的那样,用 make` 来定义信道。 下面编写代码,声明一个信道。 ```go package main...

# RESTful接口规范概要 ## 协议 使用 http/https 协议 ## 版本 将 `API` 的版本号放入 `URL`,如 https://github.com/kaindy7633/v1/ ## HTTP动词 - `GET`(`SELECT`):从服务器取出资源(一项或多项)。 - `POST`(`CREATE`):在服务器新建一个资源。 - `PUT`(`UPDATE`):在服务器更新资源(客户端提供改变后的完整资源)。 - `PATCH`(`UPDATE`):在服务器更新资源(客户端提供改变的属性)。 - `DELETE`(`DELETE`):从服务器删除资源。 ## 路径 每个网址代表一种资源(`resource`),所以网址中不能有动词,只能有名词 -...

# Go 经典入门 20:Go 协程 在前面的教程里,我们探讨了并发,以及并发与并行的区别。本教程则会介绍在 `Go` 语言里,如何使用 `Go` 协程(`Goroutine`)来实现并发。 ## Go 协程是什么? `Go` 协程是与其他函数或方法一起并发运行的函数或方法。`Go` 协程可以看作是轻量级线程。与线程相比,创建一个 `Go` 协程的成本很小。因此在 `Go` 应用中,常常会看到有数以千计的 `Go` 协程并发地运行。 ## Go 协程相比于线程的优势 相比线程而言,`Go` 协程的成本极低。堆栈大小只有若干 kb,并且可以根据应用的需求进行增减。而线程必须指定堆栈的大小,其堆栈是固定不变的。 `Go` 协程会复用(`Multiplex`)数量更少的...

# Go 经典入门 19:并发 `Go` 是并发式语言,而不是并行式语言。在讨论 `Go` 如何处理并发之前,我们必须理解何为并发,以及并发与并行的区别。 ## 并发是什么? 并发是指立即处理多个任务的能力。一个例子就能很好地说明这一点。 我们可以想象一个人正在跑步。假如在他晨跑时,鞋带突然松了。于是他停下来,系一下鞋带,接下来继续跑。这个例子就是典型的并发。这个人能够一下搞定跑步和系鞋带两件事,即立即处理多个任务。 ## 并行是什么?并行和并发有何区别? 并行是指同时处理多个任务。这听起来和并发差不多,但其实完全不同。 我们同样用这个跑步的例子来帮助理解。假如这个人在慢跑时,还在用他的 `iPod` 听着音乐。在这里,他是在跑步的同时听音乐,也就是同时处理多个任务。这称之为并行。 ## 从技术上看并发和并行 通过现实中的例子,我们已经明白了什么是并发,以及并发与并行的区别。作为一名极客,我们接下来从技术的角度来考察并发和并行。:) 假如我们正在编写一个 web 浏览器。这个 `web` 浏览器有各种组件。其中两个分别是 `web` 页面的渲染区和从网上下载文件的下载器。假设我们已经构建好了浏览器代码,各个组件也都可以相互独立地运行(通过像 `Java` 里的线程,或者通过即将介绍的...

# Go经典入门18:接口(二) ## 实现接口:指针接受者与值接受者 在接口(一)上的所有示例中,我们都是使用值接受者(`Value Receiver`)来实现接口的。我们同样可以使用指针接受者(`Pointer Receiver`)来实现接口。只不过在用指针接受者实现接口时,还有一些细节需要注意。我们通过下面的代码来理解吧。 ```go package main import "fmt" type Describer interface { Describe() } type Person struct { name string age int } func (p Person)...