这是我参与「第三届青训营 -后端场」笔记创作活动的第5篇笔记。
基础知识(四)
RESTFul
通过以下三个方面进行定义:
- 直观简洁的资源地址 URL
- 传输的资源: JSON XML
- 对资源的操作: PUT GET DELETE POST
Stringer
type Stringer interface {
String() string
}
Stringer 是一个可以用字符串描述自己的类型。fmt 包(还有很多包)都通过此接口来打印值。
error
使用 error 值来表示错误状态。
与 fmt.Stringer 类似,error 类型是一个内建接口:
type error interface {
Error() string
}
通常函数会返回一个 error 值,调用的它的代码应当判断这个错误是否等于 nil 来进行错误处理。
type ErrNegativeSqrt float64
func Sqrt(x float64) ( float64 , error ) {
if x < 0 {
return 0 ,ErrNegativeSqrt(x)
}
var z float64 = 1.0
for y := 0.0 ; z != y; {
y = z
z -= ( z * z - x )/( 2 * x )
fmt.Println(z)
}
return z ,nil
}
func(v ErrNegativeSqrt)Error() string{
return fmt.Sprintf(" %f 的值只能为非负值 ",v )
}
func main() {
fmt.Println(Sqrt(2))
fmt.Println(Sqrt(-2))
}
Reader
io 包指定了 io.Reader 接口,它表示从数据流的末尾进行读取。
Go 标准库包含了该接口的许多实现,包括文件、网络连接、压缩和加密等等。
io.Reader 接口有一个 Read 方法:
func (T) Read(b []byte) (n int, err error)
Read 用数据填充给定的字节切片并返回填充的字节数和错误值。在遇到数据流的结尾时,它会返回一个 io.EOF 错误。
示例代码创建了一个 strings.Reader 并以每次 8 字节的速度读取它的输出。
GO协程
由 Go 运行时管理的轻量级线程。
go f(x, y, z)
会启动一个新的 Go协程并执行
f, x, y 和 z 的求值发生在当前的 Go 程中,而 f 的执行发生在新的 Go 程中。
Go 程在相同的地址空间中运行,因此在访问共享的内存时必须进行同步。sync 包提供了这种能力,不过在 Go 中并不经常用到,因为还有其它的办法
信道
信道是带有类型的管道,你可以通过它用信道操作符 <- 来发送或者接收值。
ch <- v // 将 v 发送至信道 ch。
v := <-ch // 从 ch 接收值并赋予 v。
(“箭头”就是数据流的方向。)
ch := make(chan int)
默认情况下,发送和接收操作在另一端准备好之前都会阻塞。这使得 Go 程可以在没有显式的锁或竞态变量的情况下进行同步。
信道可以是 带缓冲的。将缓冲长度作为第二个参数提供给 make 来初始化一个带缓冲的信道:
仅当信道的缓冲区填满后,向其发送数据时才会阻塞。当缓冲区为空时,接受方会阻塞。
发送者可通过 close 关闭一个信道来表示没有需要发送的值了。接收者可以通过为接收表达式分配第二个参数来测试信道是否被关闭:若没有值可以接收且信道已被关闭,那么在执行完
v, ok := <-ch
之后 ok 会被设置为 false。
只有发送者才能关闭信道,而接收者不能。向一个已经关闭的信道发送数据会引发程序恐慌(panic)。
与文件不同,通常情况下无需关闭它们
只有在必须告诉接收者不再有需要发送的值时才有必要关闭,例如终止一个 range 循环。
select 语句使一个 Go 程可以等待多个通信操作。
select 会阻塞到某个分支可以继续执行为止,这时就会执行该分支。当多个分支都准备好时会随机选择一个执行。
当 select 中的其它分支都没有准备好时,default 分支就会执行。
为了在尝试发送或者接收时不发生阻塞,可使用 default 分支:
sync.Mutex
如果我们并不需要通信呢?比如说,若我们只是想保证每次只有一个 Go 程能够访问一个共享的变量,从而避免冲突?
我们通常使用 互斥锁(Mutex) 这一数据结构来提供这种机制。
标准库中提供了 sync.Mutex 互斥锁类型及其两个方法:
LockUnlock
我们可以通过在代码前调用 Lock 方法,在代码后调用 Unlock 方法来保证一段代码的
也可以用 defer 语句来保证互斥锁一定会被解锁。参见 Value 方法。