Go语言基础Part III | 青训营笔记

149 阅读5分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第3篇笔记.

第三部分 错误处理与strings包操作

3.1 错误处理(error)

Go 语言通过内置的错误接口提供了非常简单的错误处理机制。

error类型是一个接口类型,这是它的定义:

type error interface {
    Error() string
}

我们可以在编码中通过实现 error 接口类型来生成错误信息。

函数通常在最后的返回值中返回错误信息。使用errors.New 可返回一个错误信息:

func Sqrt(f float64) (float64, error) {
    if f < 0 {
        return 0, errors.New("math: square root of negative number")
    }
    // 实现
}

在下面的例子中,我们在调用Sqrt的时候传递的一个负数,然后就得到了non-nil的error对象,将此对象与nil比较,结果为true,所以fmt.Println(fmt包在处理error时会调用Error方法)被调用,以输出错误,请看下面调用的示例代码:

result, err:= Sqrt(-1)

if err != nil {
   fmt.Println(err)
}

需要注意的一点是,error.New()函数每次都会返回一个不同的错误值,即使文本是相同的; 所以不能拿error类型直接进行比较

package main

import (
   "errors"
   "fmt"
)

type user struct {
   name     string
   password string
}

func findUser(users []user, name string) (v *user, err error) {
   for _, u := range users {
      if u.name == name {
         return &u, nil
      }
   }
   // New returns an error that formats as the given text.
   // 即便文本相同,每次调用errors.New()函数都会返回一个不同的错误值。因此不能直接拿error类型做比较。
   // exp : err1, err2 := errors.New("not found"), errors.New("not found")
   // fmt.Println(err1 == err2)   // false
   return nil, errors.New("not found")
}

func main() {
   u, err := findUser([]user{{"wang", "1024"}}, "wang")
   if err != nil {
      fmt.Println(err)
      return
   }
   fmt.Println(u.name) // wang

   if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
      fmt.Println(err) // not found
      return
   } else {
      fmt.Println(u.name)
   }
}

3.2 strings包函数

package main

import (
   "fmt"
   "strings"
)

func main() {
   a := "hello"
   // strings包
   fmt.Println(strings.Contains(a, "ll"))                // 是否包含: true
   fmt.Println(strings.Count(a, "l"))                    // 包含几个: 2
   fmt.Println(strings.HasPrefix(a, "he"))               // 是否有该前缀: true
   fmt.Println(strings.HasSuffix(a, "llo"))              // 是否有该后缀: true
   fmt.Println(strings.Index(a, "ll"))                   // 最早出现的索引: 2
   fmt.Println(strings.Join([]string{"he", "llo"}, "-")) // 用分隔符sep连接成字符串: he-llo
   fmt.Println(strings.Repeat(a, 2))                     // 重复: hellohello
   fmt.Println(strings.Replace(a, "e", "E", -1))         // 替换: hEllo
   fmt.Println(strings.Split("a-b-c", "-"))              // 字符串分割成数组: [a b c]
   fmt.Println(strings.ToLower(a))                       // 小写: hello
   fmt.Println(strings.ToUpper(a))                       // 大写: HELLO
   fmt.Println(len(a))                                   // 长度: 5
   b := "你好"
   fmt.Println(len(b)) // 6
}

Go的string包具有几个可用于字符串数据类型的功能 。 这些功能使我们可以轻松地修改和操作字符串。 我们可以将函数视为对代码元素执行的操作。 内置函数是用Go编程语言定义的函数,可供我们随时使用。

字符串搜索功能 (String Search Functions)

strings包具有许多有助于确定字符串是否包含特定字符序列的功能。

FunctionUse
strings.HasPrefixSearches the string from the beginning
strings.HasSuffixSearches the string from the end
strings.ContainsSearches anywhere in the string
strings.CountCounts how many times the string appears

strings.HasPrefixstrings.HasSuffix允许您检查字符串是否以一组特定字符开头或结尾。 例如,检查字符串"Sammy Shark"Sammy开头并以Shark结尾:

   ss := "Sammy Shark"
   fmt.Println(strings.HasPrefix(ss, "Sammy"))  // true
   fmt.Println(strings.HasSuffix(ss, "Shark"))  // true

您将使用strings.Contains函数来检查"Sammy Shark"包含序列Sh :

   fmt.Println(strings.Contains(ss, "Sh")) // true

最后,看看字母S在短语Sammy Shark出现了多少次:

   fmt.Println(strings.Count(ss, "S")) // 2

注意,这里的函数都区分大小写

字符串操作的功能 (Functions for String Manipulation)

strings.Join , strings.Splitstrings.ReplaceAll函数是在Go中处理字符串的其他几种方法。

strings.Join函数用于将字符串的切片组合为新的单个字符串。

   fmt.Println(strings.Join([]string{"sharks", "crustaceans", "plankton"}, ","))
   // output : sharks,crustaceans,plankton

如果要在新字符串中的字符串值之间添加逗号和空格,则可以简单地在逗号后用空格重写表达式: strings.Join([]string{"sharks", "crustaceans", "plankton"}, ", ") (此处有空格)。

就像我们可以将字符串连接在一起,我们同样也可以拆分字符串。 为此,我们可以使用strings.Split函数并在空格处进行分割:

   balloon := "Sammy has a balloon."
   s := strings.Split(balloon, " ")
   fmt.Println(s) // [Sammy has a balloon] 这里变成了字符串切片,[]string

输出是字符串的切片。 由于使用了strings.Println ,因此很难通过查看来判断输出是什么。 要查看它确实是字符串的切片,请使用带有%q动词的fmt.Printf函数对字符串加引号:

   fmt.Printf("%q", s)
   // Output : ["Sammy" "has" "a" "balloon."]

strings.ReplaceAll函数可以采用原始字符串,并返回更新后的字符串并进行替换。

假设Sammy拥有的气球丢了。 由于Sammy不再具有此气球,因此我们将新字符串中的子字符串"has"从原始字符串balloon更改为"had" :

   fmt.Println(strings.ReplaceAll(balloon, "has", "had"))
   // Output: Sammy had a balloon.

在括号内,第一个是balloon ,用于存储原始字符串的变量。 第二个子字符串"has"是我们要替换的东西,第三个子字符串"had"是我们要替换第二个子字符串的东西。 将其合并到程序中后,输出将如上所示

使字符串大写和小写 (Making Strings Uppercase and Lowercase)

函数strings.ToUpperstrings.ToLower将返回一个字符串,其中原始字符串的所有字母都转换为大写或小写字母。 因为字符串是不可变的数据类型,所以返回的字符串将是新的字符串。 字符串中任何非字母的字符都不会更改。

要将字符串"Sammy Shark"转换为全部大写,可以使用strings.ToUpper函数:

   ss := "Sammy Shark"
   fmt.Println(strings.ToUpper(ss))  // SAMMY SHARK
   fmt.Println(strings.ToLower(ss))  // sammy shark

strings.ToUpperstrings.ToLower函数通过使大小写一致来strings.ToLower评估和比较字符串的过程。 例如,如果用户将其姓名全写为小写,则仍然可以通过将其姓名与全大写字母进行比较来确定他们的姓名是否在我们的数据库中。

确定字符串长度 (Determining String Length)

内置函数len()返回字符串中的字符数。 当您需要强制使用最小或最大密码长度,或将较大的字符串截断为特定的限制以用作缩写时,此功能很有用。

为了演示此功能,我们将找到一个长句子字符串的长度:

import (
	"fmt"
	"strings"
)

func main() {
        openSource := "Sammy contributes to open source."
        fmt.Println(len(openSource))   // 33
}

我们将变量openSource设置为等于字符串"Sammy contributes to open source." 然后使用len(openSource)将该变量传递给len()函数。 最后,我们将该函数传递给fmt.Println()函数,以便我们可以在屏幕上看到程序的输出。

请记住, len()函数将计算由双引号引起的任何字符,包括字母,数字,空格字符和符号。