Browse Category: Go

Go 标准库介绍一: strings

本文介绍Go 标准库 strings 常用导出函数,结构体及其方法。

strings 包实现了用于操作字符串的简单函数,包括 strings 导出函数和 Reader, Replacer 两个结构体。

1. strings 常用导出函数

判断字符串与子串关系

  • func EqualFold(s, t string) bool // 判断两个utf-8编码字符串,大小写不敏感
  • func HasPrefix(s, prefix string) bool // 判断s是否有前缀字符串prefix
  • func Contains(s, substr string) bool // 判断字符串s是否包含子串substr
  • func ContainsAny(s, chars string) bool // 判断字符串s是否包含字符串chars中的任一字符
  • func Count(s, sep string) int // 返回字符串s中有几个不重复的sep子串

获取字符串中子串位置

  • func Index(s, sep string) int // 子串sep在字符串s中第一次出现的位置,不存在则返回-1
  • func IndexByte(s string, c byte) int // 字符c在s中第一次出现的位置,不存在则返回-
  • func IndexAny(s, chars string) int // 字符串chars中的任一utf-8码值在s中第一次出现的位置,如果不存在或者chars为空字符串则返回-1
  • func IndexFunc(s string, f func(rune) bool) int // s中第一个满足函数f的位置i(该处的utf-8码值r满足f(r)==true),不存在则返回-1
  • func LastIndex(s, sep string) int // 子串sep在字符串s中最后一次出现的位置,不存在则返回-1

字符串中字符处理

  • func Title(s string) string // 返回s中每个单词的首字母都改为标题格式的字符串拷贝
  • func ToLower(s string) string // 返回将所有字母都转为对应的小写版本的拷贝
  • func ToUpper(s string) string // 返回将所有字母都转为对应的大写版本的拷贝
  • func Repeat(s string, count int) string // 返回count个s串联的字符串
  • func Replace(s, old, new string, n int) string // 返回将s中前n个不重叠old子串都替换为new的新字符串,如果n<0会替换所有old子串
  • func Map(mapping func(rune) rune, s string) string // 将s的每一个unicode码值r都替换为mapping(r),返回这些新码值组成的字符串拷贝。如果mapping返回一个负值,将会丢弃该码值而不会被替换

字符串前后端处理

  • func Trim(s string, cutset string) string // 返回将s前后端所有cutset包含的utf-8码值都去掉的字符串
  • func TrimSpace(s string) string // 返回将s前后端所有空白(unicode.IsSpace指定)都去掉的字符串
  • func TrimFunc(s string, f func(rune) bool) string // 返回将s前后端所有满足f的unicode码值都去掉的字符串

字符串分割与合并

  • func Fields(s string) []string // 返回将字符串按照空白(通过unicode.IsSpace判断,可以是一到多个连续的空白字符)分割的多个字符串
  • func Split(s, sep string) []string // 用去掉s中出现的sep的方式进行分割,会分割到结尾,并返回生成的所有片段组成的切片
  • func Join(a []string, sep string) string // 将一系列字符串连接为一个字符串,之间用sep来分隔

strings 导出函数示例

$GOPATH/src/github.com/ironxu/go_note/library/strings/strings.go 源码如下:

2. Reader 结构体

Reader 类型从一个字符串读取数据,实现了io.Reader, io.Seeker等接口。

  • func NewReader(s string) *Reader // 通过字符串 s 创建一个 Reader
  • func (r *Reader) Len() int // 返回 r 还没有读取部分的长度
  • func (r *Reader) Read(b []byte) (n int, err error) // 读取部分数据到 b 中,读取的长度取决于 b 的容量
  • func (r *Reader) ReadByte() (b byte, err error) // 从 r 中读取一字节数据

$GOPATH/src/github.com/ironxu/go_note/library/strings/reader.go 源码如下:

3. Replacer 结构体

Replacer 类型实现字符串替换的操作

  • func NewReplacer(oldnew ...string) *Replacer // 使用提供的多组old、new字符串对创建一个*Replacer
  • func (r *Replacer) Replace(s string) string // 返回s 所有替换完后的拷贝
  • func (r *Replacer) WriteString(w io.Writer, s string) (n int, err error) // 向w中写入s替换完后的拷贝

$GOPATH/src/github.com/ironxu/go_note/library/strings/replace.go 源码如下:

参考

可以关注我的微博了解更多信息: @刚刚小码农

Go 之旅五: 并发

本文是学习 A Tour of Go (中文参考 Go 之旅中文 ) 整理的笔记。介绍Go 语言线程,信道以及互斥锁的概念和使用方法。

1. Go 线程

$GOPATH/src/go_note/gotour/concurrency/goroutine/goroutine.go 源码如下

Go 线程(goroutine)是由Go 运行时管理的轻量级线程。

会启动一个新的 Go 线程程并执行

其中 fxyz 的求值在当前的 Go 线程中进行,而 f 的执行发生在新的 Go 线程中。

Go 程在相同的地址空间中运行,因此在访问共享的内存时必须进行同步,这可以通过使用sync 包或信道实现。

2. 信道

$GOPATH/src/go_note/gotour/concurrency/channel/channel.go 源码如下

信道是带有类型的管道,通过信道操作符 <- 来从信道发送或者接收值。

“箭头”就是数据流的方向。

信道在使用前必须创建:

默认情况下,发送和接收操作在另一端准备好之前都会阻塞。这使得 Go 程可以在没有显式的锁或竞态变量的情况下进行同步。

2.1 带缓冲的信道

信道可以是带缓冲的, 将缓冲长度作为第二个参数提供给 make 来初始化一个带缓冲的信道:

仅当信道的缓冲区填满后,向其发送数据时才会阻塞。当缓冲区为空时,接受方会阻塞。

2.2 range 和 close

发送者可通过 close 关闭一个信道来表示没有需要发送的值。接收者可以通过为接收表达式的第二个参数来测试信道是否被关闭:若没有值可以接收且信道已被关闭,该值为 false

循环 for i := range c 会不断从信道接收值,直到它被关闭。

注意: 只有发送者才能关闭信道,而接收者不能。向一个已经关闭的信道发送数据会引发程序错误。信道与文件不同,通常情况下无需关闭它们。只有在必须告诉接收者不再有值需要发送的时候才有必要关闭,如终止一个 range 循环。

3. select 语句

$GOPATH/src/go_note/gotour/concurrency/select/select.go 源码如下:

select 语句使一个 Go 线程可以等待多个通信操作。

select 会阻塞到某个分支可以继续执行为止,这时就会执行该分支。当多个分支都准备好时会随机选择一个执行。

select 中的其它分支都没有准备好时,default 分支就会执行。为了在尝试发送或者接收时不发生阻塞,可使用 default 分支

4. sync.Mutex

$GOPATH/src/go_note/gotour/concurrency/mutex/mutex.go 源码如下:

互斥(mutual exclusion),指一次只有一个 Go 线程能够访问一个共享的变量。一般使用互斥锁(Mutex)来提供这种机制。

Go 标准库中提供了 sync.Mutex 互斥锁类型及其两个方法:

通过在代码前调用 Lock() 方法,在代码后调用 Unlock() 方法来保证一段代码的互斥执行。另外可以用 defer 语句来保证互斥锁一定会被解锁。

参考

可以关注我的微博了解更多信息: @刚刚小码农

Go 之旅四: 方法与接口篇

本文是学习 A Tour of Go (中文参考 Go 之旅中文 ) 整理的笔记,介绍Go 语言方法,接口,类型的基本概念和使用。

1. 方法

$GOPATH/src/go_note/gotour/methods/method/method.go 源码如下:

Go 没有类。不过你可以为结构体类型定义方法。

方法是一类带特殊的 接收者 参数的函数,方法接收者位于方法 func 关键字和方法名之间。

1.1 非结构体类型声明方法

只能为在同一包内定义的类型添加方法, 而不能为其它包内定义的类型(包括 int 之类的内建类型)的接收者声明方法。即接收者的类型定义和方法声明必须在同一包内;不能为内建类型声明方法。

1.2 指针接收者

为指针接收者声明方法:对于某类型 T ,指针接收者的类型可以用 *T 表示。(T 不能是像 *int 这样的指针。)

指针接收者的方法可以修改接收者指向的值。 由于方法经常需要修改它的接收者,指针接收者比值接收者更常用。若使用值接收者,方法只会对原始值的副本进行操作。

1.3 方法与指针重定向(隐式转换)

以指针为接收者的方法被调用时,接收者既能为值又能为指针:

由于 Scale 方法有一个指针接收者,为方便起见,Go 会将语句 v.Scale(5) 解释为 (&v).Scale(5)

而以值为接收者的方法被调用时,接收者既能为值又能为指针:

这种情况下,方法调用 p.Abs() 会被解释为 (*p).Abs()。函数必须接受与定义相同的类型,不会隐式转换

1.4 选择值或指针作为接收者

使用指针接收者的原因有二:

  • 方法能够修改接收者指向的值。
  • 避免在每次调用方法时复制该值,若值的类型为大型结构体时,这样做会更加高效。

通常来说,所有给定类型的方法都应该有值或指针接收者,但并不应该二者混用。

2. 接口

$GOPATH/src/go_note/gotour/methods/interface/interface.go 源码如下:

接口类型 是由一组方法签名定义的集合, 接口类型的值可以保存任何实现了这些方法的值。

类型通过实现一个接口的所有方法来实现该接口, 既然无需专门显式声明,也就没有“implements“关键字。隐式接口将接口的实现与定义解耦,这样接口的实现可以出现在任何包中,无需提前定义。

2.1 接口值

在内部,接口值可以看做包含值和具体类型的元组:

接口值保存了一个具体底层类型的具体值,接口值调用方法时会调用具体类型的的同名方法。

2.2 底层值为 nil 的接口值

即便接口内的具体值为 nil,方法仍然会被 nil 接收者调用。保存了 nil 具体值的接口其自身并不为 nil

但是接口值nil时,由于此时接口值既不保存值也不保存具体类型,调用方法会产生运行时错误,因为接口的元组内并未包含能够指明该调用哪个具体类型的方法。

2.3 空接口

指定了零个方法的接口值被称为空接口:

因为每个类型都至少实现了零个方法,空接口可保存任何类型的值。

2.4 类型断言

类型断言提供了访问接口值底层具体值的方式。

该语句断言接口值 i 保存了具体类型 T ,并将其底层类型为 T 的值赋予变量 t 。如果 i 并未保存 T 类型的值,该语句就会触发一个错误。

为了判断一个接口值是否保存了一个特定的类型, 类型断言可返回两个值:其底层值和判断断言是否成功的布尔值。

i 保存了一个 T ,那么 t 将会是其底层值,而 ok 为 true 。否则, ok 将为 falset 将为 T 类型的零值,程序并不会产生错误。

2.5 类型选择

类型选择是一种按顺序从几个类型断言中选择分支的结构。

类型选择与一般的 switch 语句相似,不过类型选择中的 case 为类型(而非值),它们针对给定接口值所存储值的类型进行比较

类型选择中的声明与类型断言 i.(T) 的语法相同,只是具体类型 T 被替换成了关键字 type

此选择语句判断接口值 i 保存的值类型是 T 还是 S。 在 TS 的情况下,变量 v 会分别按 TS 类型取保存在 i 中的值。在默认(没有匹配)的情况下,变量 vi 的接口类型和值相同。

3. Stringer

$GOPATH/src/go_note/gotour/methods/stringer/stringer.go 源码如下:

fmt 包中定义的 Stringer 是最普遍的接口之一。

Stringer 是一个可以用字符串描述自己的类型。fmt 包(还有很多包)都通过此接口来打印值。

4. 错误

$GOPATH/src/go_note/gotour/methods/error/error.go 源码如下:

Go 程序使用 error 值来表示错误状态。与 fmt.Stringer 类似, error 类型是一个内建接口:

通常函数会返回一个 error 值,调用的它的代码应当判断这个错误是否等于 nil 来进行错误处理。

errornil 时表示成功;非 nilerror 表示失败。

5. Reader

$GOPATH/src/go_note/gotour/methods/reader/reader.go 源码如下:

Reader 接口表示读取数据。Go 标准库包含了该接口的许多实现,包括文件、网络连接、压缩和加密等等,示例代码是字符串的实现。

Reader 接口有一个 Read 方法:

Read 用数据填充给定的字节切片并返回填充的字节数和错误值。 在遇到数据的结尾时,它会返回一个 io.EOF 错误。

参考

可以关注我的微博了解更多信息: @刚刚小码农