Go语言教程之边写边学:标准库:strings(6)

了解标准库是一个非常好的学习语言的方法。接下里的一些章节我们将详细研究标准库中的类型,方法,结合实际应用案例进行有趣的编程。

字符串处理是比较基础的库,我们从简单的库开始入门。

本节我们将继续用实例代码研究以下函数的用法。


func Trim(s, cutset string) string
Trim返回字符串s的一个片段,其中删除了片段集中包含的所有前导和尾部Unicode代码点。
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Print(strings.Trim("¡¡¡Hello, Gophers!!!", "!¡")) // Hello, Gophers
}

func TrimFunc(s string, f func(rune) bool) string
TrimFunc返回字符串s的一个片段,其中删除了满足f(c)的所有前导和尾部Unicode代码点。
package main

import (
	"fmt"
	"strings"
	"unicode"
)

func main() {
	fmt.Print(strings.TrimFunc("¡¡¡Hello, Gophers!!!", func(r rune) bool {
		return !unicode.IsLetter(r) && !unicode.IsNumber(r)
	}))// Hello, Gophers
}

func TrimLeft(s, cutset string) string
仅删除前导部分的指定字符。
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Print(strings.TrimLeft("¡¡¡Hello, Gophers!!!", "!¡")) // Hello, Gophers!!!
}

func TrimLeftFunc(s string, f func(rune) bool) string
仅删除满足f(c)的所有前导部分的指定字符。
package main

import (
	"fmt"
	"strings"
	"unicode"
)

func main() {
	fmt.Print(strings.TrimLeftFunc("¡¡¡Hello, Gophers!!!", func(r rune) bool {
		return !unicode.IsLetter(r) && !unicode.IsNumber(r)
	})) // Hello, Gophers!!!
}

func TrimPrefix(s, prefix string) string
删除前导部分的字符串,它与left系列函数不同之处是,需要匹配整个prefix字符串。
package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(strings.TrimPrefix("¡¡¡Hello, Gophers!!!", "¡")) // ¡¡Hello, Gophers!!!
    fmt.Println(strings.TrimPrefix("¡¡¡Hello, Gophers!!!", "¡¡¡Hello, ")) // Gophers!!!
    fmt.Println(strings.TrimPrefix("¡¡¡Hello, Gophers!!!", "¡¡¡Howdy, ")) // ¡¡¡Hello, Gophers!!!
}

func TrimRight(s, cutset string) string
TrimRight返回字符串s的一个片段,去掉片段集中包含的所有尾部Unicode代码点。
若要删除后缀,请改用TrimSuffix。
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Print(strings.TrimRight("¡¡¡Hello, Gophers!!!", "!¡")) // ¡¡¡Hello, Gophers
}

func TrimRightFunc(s string, f func(rune) bool) string
TrimRightFunc返回字符串s的一个片段,去掉所有满足f(c)的尾随Unicode代码点。
package main

import (
	"fmt"
	"strings"
	"unicode"
)

func main() {
	fmt.Print(strings.TrimRightFunc("¡¡¡Hello, Gophers!!!", func(r rune) bool {
		return !unicode.IsLetter(r) && !unicode.IsNumber(r)
	}))
}

func TrimSpace(s string) string
TrimSpace返回字符串s的一个片段,去掉所有前导和尾随空白字符。
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.TrimSpace(" \t\n Hello, Gophers \n\t\r\n")) // Hello, Gophers
}

func TrimSuffix(s, suffix string) string
删除结尾部分的字符串,它与right系列函数不同之处是,需要匹配整个prefix字符串。
package main

import (
	"fmt"
	"strings"
)

func main() {
	var s = "¡¡¡Hello, Gophers!!!"
	s = strings.TrimSuffix(s, ", Gophers!!!")
	s = strings.TrimSuffix(s, ", Marmots!!!")
	fmt.Print(s) // ¡¡¡Hello
}
Go语言教程之边写边学:标准库:strings(5)

了解标准库是一个非常好的学习语言的方法。接下里的一些章节我们将详细研究标准库中的类型,方法,结合实际应用案例进行有趣的编程。

字符串处理是比较基础的库,我们从简单的库开始入门。

本节我们将继续用实例代码研究以下函数的用法。


func ToLower(s string) string
转换为小写
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.ToLower("Gopher")) // gopher
}

func ToLowerSpecial(c unicode.SpecialCase, s string) string
ToLowerSpecial返回字符串s的副本,其中所有Unicode字母都使用c指定的大小写映射映射到其小写。
package main

import (
	"fmt"
	"strings"
	"unicode"
)

func main() {
	fmt.Println(strings.ToLowerSpecial(unicode.TurkishCase, "Önnek İş")) // önnek iş
}

func ToTitle(s string) string
ToTitle返回字符串s的副本,其中所有Unicode字母映射到其Unicode标题大小写。
package main

import (
	"fmt"
	"strings"
)

func main() {
	// Compare this example to the Title example.
	fmt.Println(strings.ToTitle("her royal highness")) // HER ROYAL HIGHNESS
	fmt.Println(strings.ToTitle("loud noises")) // LOUD NOISES
	fmt.Println(strings.ToTitle("хлеб")) // ХЛЕБ
}

func ToTitleSpecial(c unicode.SpecialCase, s string) string
package main

import (
	"fmt"
	"strings"
	"unicode"
)

func main() {
	fmt.Println(strings.ToTitleSpecial(unicode.TurkishCase, "dünyanın ilk borsa yapısı Aizonai kabul edilir")) 
        // DÜNYANIN İLK BORSA YAPISI AİZONAİ KABUL EDİLİR
}

func ToUpper(s string) string
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.ToUpper("Gopher"))
}

func ToUpperSpecial(c unicode.SpecialCase, s string) string
package main

import (
	"fmt"
	"strings"
	"unicode"
)

func main() {
	fmt.Println(strings.ToUpperSpecial(unicode.TurkishCase, "örnek iş")) // ÖRNEK İŞ
}

func ToValidUTF8(s, replacement string) string
ToValidUTF8返回字符串s的副本,每次运行无效的UTF-8字节序列时都会被替换字符串替换,替换字符串可能为空。
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Printf("%s\n", strings.ToValidUTF8("abc", "\uFFFD")) // abc
	fmt.Printf("%s\n", strings.ToValidUTF8("a\xffb\xC0\xAFc\xff", "")) // abc
	fmt.Printf("%s\n", strings.ToValidUTF8("\xed\xa0\x80", "abc")) // abc
}
Go语言教程之边写边学:标准库:strings(4)

了解标准库是一个非常好的学习语言的方法。接下里的一些章节我们将详细研究标准库中的类型,方法,结合实际应用案例进行有趣的编程。

字符串处理是比较基础的库,我们从简单的库开始入门。

本节我们将继续用实例代码研究以下函数的用法。


func Join(elems []string, sep string) string
以sep为连接符号,拼接elems数组,最终输出字符串。
package main

import (
	"fmt"
	"strings"
)

func main() {
	s := []string{"foo", "bar", "baz"}
	fmt.Println(strings.Join(s, ", ")) // foo, bar, baz
}

func Map(mapping func(rune) rune, s string) string
Map返回字符串s的副本,其中所有字符都根据映射函数进行了修改。如果映射返回负值,则该字符将从字符串中删除,不进行替换。
import (
	"fmt"
	"strings"
)

func main() {
	rot13 := func(r rune) rune {
		switch {
		case r >= 'A' && r <= 'Z':
			return 'A' + (r-'A'+13)%26
		case r >= 'a' && r <= 'z':
			return 'a' + (r-'a'+13)%26
		}
		return r
	}
	fmt.Println(strings.Map(rot13, "'Twas brillig and the slithy gopher...")) // 'Gjnf oevyyvt naq gur fyvgul tbcure...
}

func Repeat(s string, count int) string
Repeat返回一个由字符串s的计数副本组成的新字符串。如果计数为负数或(len(s)*count)的结果溢出,程序会panic。
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println("ba" + strings.Repeat("na", 2)) // banana
}

func Replace(s, old, new string, n int) string
Replace返回字符串s的副本,其中前n个不重叠的旧实例被新实例替换。如果old为空,它将在字符串的开头和每个UTF-8序列之后进行匹配,从而为k-rune字符串生成最多k+1个替换。如果n<0,则对替换的数量没有限制。
package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(strings.Replace("oink oink oink", "", "###", 1))
    fmt.Println(strings.Replace("oink oink oink", "", "###", 2))
    fmt.Println(strings.Replace("oink oink oink", "", "###", -1))
    fmt.Println(strings.Replace("oink oink oink", "k", "ky", 2))
    fmt.Println(strings.Replace("oink oink oink", "oink", "moo", -1))
}

输出:
###oink oink oink
###o###ink oink oink
###o###i###n###k### ###o###i###n###k### ###o###i###n###k###
oinky oinky oink
moo moo moo

func ReplaceAll(s, old, new string) string
ReplaceAll返回字符串s的一个副本,其中所有不重叠的旧实例都被新实例替换。如果old为空,它将在字符串的开头和每个UTF-8序列之后进行匹配,从而为k-rune字符串生成最多k+1个替换。
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.ReplaceAll("oink oink oink", "oink", "moo")) // moo moo moo
}

func Split(s, sep string) []string
将切片s拆分为由sep分隔的所有子字符串,并在这些分隔符之间返回子字符串的切片。
如果s不包含sep并且sep不为空,则Split返回一个长度为1的切片,该切片的唯一元素是s。
如果sep为空,则Split会在每个UTF-8序列之后进行拆分。如果s和sep都为空,Split将返回一个空切片。
它相当于计数为-1的SplitN。
package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Printf("%q\n", strings.Split("a,b,c", ","))
    fmt.Printf("%q\n", strings.Split("a man a plan a canal panama", "a "))
    fmt.Printf("%q\n", strings.Split(" xyz ", ""))
    fmt.Printf("%q\n", strings.Split("", ""))
    fmt.Printf("%q\n", strings.Split("", "Bernardo O'Higgins"))
}

输出:

["a" "b" "c"]
["" "man " "plan " "canal panama"]
[" " "x" "y" "z" " "]
[]
[""]

func SplitAfter(s, sep string) []string
与split的区别是,返回的每个字符串包含sep字符。
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Printf("%q\n", strings.SplitAfter("a,b,c", ",")) // ["a," "b," "c"]
}


func SplitAfterN(s, sep string, n int) []string
计数决定要返回的子字符串数:
n>0:最多n个子串;最后一个子字符串将是未拆分的余数。
n=0:结果为零(零个子字符串)
n<0:所有子字符串
package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Printf("%q\n", strings.SplitAfterN("a,b,c", ",", 2)) // ["a," "b,c"]
    fmt.Printf("%q\n", strings.SplitAfterN("a,b,c", ",", 0)) // []
    fmt.Printf("%q\n", strings.SplitAfterN("a,b,c", ",", 5)) // ["a," "b," "c"]
    fmt.Printf("%q\n", strings.SplitAfterN("a,b,c", ",", -1)) // ["a," "b," "c"]
}

func SplitN(s, sep string, n int) []string
计数决定要返回的子字符串数:
n>0:最多n个子串;最后一个子字符串将是未拆分的余数。
n=0:结果为零(零个子字符串)
n<0:所有子字符串
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Printf("%q\n", strings.SplitN("a,b,c", ",", 2)) // ["a" "b,c"]
	z := strings.SplitN("a,b,c", ",", 0)
	fmt.Printf("%q (nil = %v)\n", z, z == nil) // [] (nil = true)
}
Go语言教程之边写边学:标准库:strings(3)

了解标准库是一个非常好的学习语言的方法。接下里的一些章节我们将详细研究标准库中的类型,方法,结合实际应用案例进行有趣的编程。

字符串处理是比较基础的库,我们从简单的库开始入门。

本节我们将继续用实例代码研究以下函数的用法。


func Index(s, substr string) int
返回substr在s中首次出现的位置,不存在时返回-1
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.Index("chicken", "ken")) // 4
	fmt.Println(strings.Index("chicken", "dmr")) // -1
}

func IndexAny(s, chars string) int
返回chars中任意一个首次出现在s的字母位置
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.IndexAny("chicken", "aeiouy")) // 2
	fmt.Println(strings.IndexAny("crwth", "aeiouy")) // -1
}

func IndexByte(s string, c byte) int
返回c出现在s中首次出现的位置,不存在时-1
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.IndexByte("golang", 'g')) // 0
	fmt.Println(strings.IndexByte("gophers", 'h')) // 3
	fmt.Println(strings.IndexByte("golang", 'x')) // -1
}

func IndexFunc(s string, f func(rune) bool) int
返回s中首次满足函数f的字母位置,不存在则-1
package main

import (
	"fmt"
	"strings"
	"unicode"
)

func main() {
	f := func(c rune) bool {
		return unicode.Is(unicode.Han, c)
	}
	fmt.Println(strings.IndexFunc("Hello, 世界", f)) // 7
	fmt.Println(strings.IndexFunc("Hello, world", f)) // -1
}

func IndexRune(s string, r rune) int
返回r在s中首次出现的位置,不存在则-1
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.IndexRune("chicken", 'k')) // 4
	fmt.Println(strings.IndexRune("chicken", 'd')) // -1
}

func LastIndex(s, substr string) int
substr在s中最后一次出现的位置,不存在则-1
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.Index("go gopher", "go")) // 0
	fmt.Println(strings.LastIndex("go gopher", "go")) // 3
	fmt.Println(strings.LastIndex("go gopher", "rodent")) // -1
}


func LastIndexAny(s, chars string) int
返回chars中任意一个最后出现在s的字母位置,不存在则-1
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.LastIndexAny("go gopher", "go")) // 4
	fmt.Println(strings.LastIndexAny("go gopher", "rodent")) // 8
	fmt.Println(strings.LastIndexAny("go gopher", "fail")) // -1
}


func LastIndexByte(s string, c byte) int
返回c之后出现在s的字母位置,不存在则-1
package main

import (
	"fmt"
	"strings"
)

func main() {
	fmt.Println(strings.LastIndexByte("Hello, world", 'l')) // 10
	fmt.Println(strings.LastIndexByte("Hello, world", 'o')) // 8
	fmt.Println(strings.LastIndexByte("Hello, world", 'x')) // -1
}

func LastIndexFunc(s string, f func(rune) bool) int
返回s中最后满足函数f的字母位置
package main

import (
	"fmt"
	"strings"
	"unicode"
)

func main() {
	fmt.Println(strings.LastIndexFunc("go 123", unicode.IsNumber)) // 5
	fmt.Println(strings.LastIndexFunc("123 go", unicode.IsNumber)) // 2
	fmt.Println(strings.LastIndexFunc("go", unicode.IsNumber)) // -1
}
Go语言教程之边写边学:标准库:strings(2)

了解标准库是一个非常好的学习语言的方法。接下里的一些章节我们将详细研究标准库中的类型,方法,结合实际应用案例进行有趣的编程。

字符串处理是比较基础的库,我们从简单的库开始入门。

本节我们将继续用实例代码研究以下函数的用法。

func Cut(s, sep string) (before, after string, found bool)
func CutPrefix(s, prefix string) (after string, found bool)
func CutSuffix(s, suffix string) (before string, found bool)
func EqualFold(s, t string) bool
func Fields(s string) []string
func FieldsFunc(s string, f func(rune) bool) []string
func HasPrefix(s, prefix string) bool
func HasSuffix(s, suffix string) bool
package main

import (
    "fmt"
    "strings"
    "unicode"
)

func main() {
    m := "hello this is strings."

    // cut用sep参数分割原字符串,返回3个参数,切割后左边部分,切割后右边部分,是否存在sep,不存在就不切割
    show := func(s, sep string) {
        before, after, found := strings.Cut(s, sep)
        fmt.Printf("Cut(%q, %q) = %q, %q, %v\n", s, sep, before, after, found)
    }
    show(m, "this")
    show(m, "is")
    show(m, "wow")

    // cutprefix用于去掉前缀,如果原字符串以sep开头就去掉这一部分,返回剩余部分,以及是否存在布尔值
    show2 := func(s, sep string) {
        after, found := strings.CutPrefix(s, sep)
        fmt.Printf("CutPrefix(%q, %q) = %q, %v\n", s, sep, after, found)
    }

    show2(m, "hello")
    show2(m, "this")
    show2(m, "wow")

    // cutsuffix用于去掉后缀,如果原字符串以sep结尾就去掉这一部分,返回剩余部分,以及是否存在布尔值
    show3 := func(s, sep string) {
        after, found := strings.CutSuffix(s, sep)
        fmt.Printf("CutSuffix(%q, %q) = %q, %v\n", s, sep, after, found)
    }

    show3(m, "strings")
    show3(m, "strings.")
    show3(m, "wow")

    // equalFold是否在utf8编码下,不区分大小写相等
    fmt.Println("Go equalFold go?", strings.EqualFold("Go", "go"))

    // fields用空白字符分割字符串,包括空格,多个空格,\t,\r,\n
    fmt.Println("Fields are 1: ", strings.Fields("  foo bar  baz   "))
    fmt.Println("Fields are 2: ", strings.Fields("  foo bar\t baz   "))
    fmt.Println("Fields are 3: ", strings.Fields("  foo bar\r\nbaz   "))

    // fieldsFunc根据提供的函数分割字符串,下面的f函数判断当c不是字母也不是数字的时候返回true,也就是在此处分割
    f := func(c rune) bool {
        return !unicode.IsLetter(c) && !unicode.IsNumber(c)
    }
    fmt.Println("Fields are 4: ", strings.FieldsFunc("  foo1;bar2,baz3...", f))

    // hasPrefix, 区分大小写
    fmt.Println(strings.HasPrefix(m, "Hello"))

    // hasSuffix, 区分大小写
    fmt.Println(strings.HasSuffix(m, "strings."))
}

输出:

Cut("hello this is strings.", "this") = "hello ", " is strings.", true
Cut("hello this is strings.", "is") = "hello th", " is strings.", true
Cut("hello this is strings.", "wow") = "hello this is strings.", "", false
CutPrefix("hello this is strings.", "hello") = " this is strings.", true
CutPrefix("hello this is strings.", "this") = "hello this is strings.", false
CutPrefix("hello this is strings.", "wow") = "hello this is strings.", false
CutSuffix("hello this is strings.", "strings") = "hello this is strings.", false
CutSuffix("hello this is strings.", "strings.") = "hello this is ", true
CutSuffix("hello this is strings.", "wow") = "hello this is strings.", false
Go equalFold go? true
Fields are 1:  [foo bar baz]
Fields are 2:  [foo bar baz]
Fields are 3:  [foo bar baz]
Fields are 4:  [foo1 bar2 baz3]
false
false
Go语言教程之边写边学:标准库:strings(1)

了解标准库是一个非常好的学习语言的方法。接下里的一些列章节我们将详细研究标准库中的类型,方法,结合实际应用案例进行有趣的编程。

字符串处理是比较基础的库,我们从简单的库开始入门。

先看一下strings相关的类型和方法,大概分为通用方法部分和Builder,Reader,Replacer类型。

func Clone(s string) string
func Compare(a, b string) int
func Contains(s, substr string) bool
func ContainsAny(s, chars string) bool
func ContainsFunc(s string, f func(rune) bool) bool
func ContainsRune(s string, r rune) bool
func Count(s, substr string) int
func Cut(s, sep string) (before, after string, found bool)
func CutPrefix(s, prefix string) (after string, found bool)
func CutSuffix(s, suffix string) (before string, found bool)
func EqualFold(s, t string) bool
func Fields(s string) []string
func FieldsFunc(s string, f func(rune) bool) []string
func HasPrefix(s, prefix string) bool
func HasSuffix(s, suffix string) bool
func Index(s, substr string) int
func IndexAny(s, chars string) int
func IndexByte(s string, c byte) int
func IndexFunc(s string, f func(rune) bool) int
func IndexRune(s string, r rune) int
func Join(elems []string, sep string) string
func LastIndex(s, substr string) int
func LastIndexAny(s, chars string) int
func LastIndexByte(s string, c byte) int
func LastIndexFunc(s string, f func(rune) bool) int
func Map(mapping func(rune) rune, s string) string
func Repeat(s string, count int) string
func Replace(s, old, new string, n int) string
func ReplaceAll(s, old, new string) string
func Split(s, sep string) []string
func SplitAfter(s, sep string) []string
func SplitAfterN(s, sep string, n int) []string
func SplitN(s, sep string, n int) []string
func Title(s string) stringDEPRECATED
func ToLower(s string) string
func ToLowerSpecial(c unicode.SpecialCase, s string) string
func ToTitle(s string) string
func ToTitleSpecial(c unicode.SpecialCase, s string) string
func ToUpper(s string) string
func ToUpperSpecial(c unicode.SpecialCase, s string) string
func ToValidUTF8(s, replacement string) string
func Trim(s, cutset string) string
func TrimFunc(s string, f func(rune) bool) string
func TrimLeft(s, cutset string) string
func TrimLeftFunc(s string, f func(rune) bool) string
func TrimPrefix(s, prefix string) string
func TrimRight(s, cutset string) string
func TrimRightFunc(s string, f func(rune) bool) string
func TrimSpace(s string) string
func TrimSuffix(s, suffix string) string
type Builder
func (b *Builder) Cap() int
func (b *Builder) Grow(n int)
func (b *Builder) Len() int
func (b *Builder) Reset()
func (b *Builder) String() string
func (b *Builder) Write(p []byte) (int, error)
func (b *Builder) WriteByte(c byte) error
func (b *Builder) WriteRune(r rune) (int, error)
func (b *Builder) WriteString(s string) (int, error)
type Reader
func NewReader(s string) *Reader
func (r *Reader) Len() int
func (r *Reader) Read(b []byte) (n int, err error)
func (r *Reader) ReadAt(b []byte, off int64) (n int, err error)
func (r *Reader) ReadByte() (byte, error)
func (r *Reader) ReadRune() (ch rune, size int, err error)
func (r *Reader) Reset(s string)
func (r *Reader) Seek(offset int64, whence int) (int64, error)
func (r *Reader) Size() int64
func (r *Reader) UnreadByte() error
func (r *Reader) UnreadRune() error
func (r *Reader) WriteTo(w io.Writer) (n int64, err error)
type Replacer
func NewReplacer(oldnew ...string) *Replacer
func (r *Replacer) Replace(s string) string
func (r *Replacer) WriteString(w io.Writer, s string) (n int, err error)

本节我们将用一些实例代码研究以下7个函数的用法。
func Clone(s string) string
func Compare(a, b string) int
func Contains(s, substr string) bool
func ContainsAny(s, chars string) bool
func ContainsFunc(s string, f func(rune) bool) bool
func ContainsRune(s string, r rune) bool
func Count(s, substr string) int

package main

import (
    "fmt"
    "strings"
    "unsafe"
)

func main() {
    m := "hello this is strings."
    c := strings.Clone(m)
    // 判断相同指针,clone会创建新副本,因此这里返回false
    fmt.Println(unsafe.StringData(c) == unsafe.StringData(m))
    // 比较,返回0则相等
    fmt.Println(strings.Compare(c, m))
    // 是否包含hello字符串
    fmt.Println(strings.Contains(c, "hello"))
    // 是否含有xyzh中的任意一个字母
    fmt.Println(strings.ContainsAny(c, "xyzh"))
    // 是否有z字母
    fmt.Println(strings.ContainsFunc(c, func(a rune) bool {
        return a == 'z'
    }))
    // 是否有a字母
    fmt.Println(strings.ContainsRune(c, 97))
    // 字母i出现几次
    fmt.Println(strings.Count(c, "i"))
}

输出:
false
0
true
true
false
false
3
Go语言教程之边写边学:基础练习:切片排序、反转、搜索功能

切片排序或搜索功能允许您以各种方式与切片进行交互和操作。Golang排序函数是核心的一部分。使用此功能无需安装,只需导入"sort"包即可。借助排序功能,您可以搜索任何重要的Golang排序函数列表如下:

Ints函数按升序对整数切片进行排序。

func Ints(intSlice []int)

示例代码:

package main

import (
	"fmt"
	"sort"
)

func main() {
	intSlice := []int{10, 5, 25, 351, 14, 9} // unsorted
	fmt.Println("Slice of integer BEFORE sort:",intSlice)	
	sort.Ints(intSlice)
	fmt.Println("Slice of integer AFTER  sort:",intSlice)	
}

输出:

Slice of integer BEFORE sort: [10 5 25 351 14 9]
Slice of integer AFTER  sort: [5 9 10 14 25 351]

 

Strings函数按字典升序对字符串切片进行排序。

func Strings(strSlice []string)

示例代码:

package main

import (
	"fmt"
	"sort"
)

func main() {
	strSlice := []string{"Jamaica","Estonia","Indonesia","Hong Kong"} // unsorted
	fmt.Println("Slice of string BEFORE sort:",strSlice)	
	sort.Strings(strSlice)
	fmt.Println("Slice of string AFTER  sort:",strSlice)

	fmt.Println("\n-----------------------------------\n")

	strSlice = []string{"JAMAICA","Estonia","indonesia","hong Kong"} // unsorted
	fmt.Println("Slice of string BEFORE sort:",strSlice)	
	sort.Strings(strSlice)
	fmt.Println("Slice of string AFTER  sort:",strSlice)
}

输出:

Slice of string BEFORE sort: [Jamaica Estonia Indonesia Hong Kong]
Slice of string AFTER  sort: [Estonia Hong Kong Indonesia Jamaica]

-----------------------------------

Slice of string BEFORE sort: [JAMAICA Estonia indonesia hong Kong]
Slice of string AFTER  sort: [Estonia JAMAICA hong Kong indonesia]

 

Float64s函数按升序对float64的切片进行排序。

func Float64s(fltSlice []string)

示例代码:

package main

import (
	"fmt"
	"sort"
)

func main() {
	fltSlice := []float64{18787677.878716, 565435.321, 7888.545, 8787677.8716, 987654.252} // unsorted
	fmt.Println("Slice BEFORE sort: ",fltSlice)
	
	sort.Float64s(fltSlice)
	
	fmt.Println("Slice AFTER sort: ",fltSlice)
}

输出:

Slice BEFORE sort:  [1.8787677878716e+07 565435.321 7888.545 8.7876778716e+06 987654.252]
Slice AFTER sort:  [7888.545 565435.321 987654.252 8.7876778716e+06 1.8787677878716e+07]

 

IntsAreSorted函数测试整数切片是否按升序排序。如果按升序找到数字切片,则返回true,否则返回false。

func IntsAreSorted(a []string) bool

示例代码:

package main
 
import (
    "fmt"
    "sort"
)
 
func main() {
    intSlice := []int{10, 5, 25, 351, 14, 9}	// unsorted
	fmt.Println(sort.IntsAreSorted(intSlice))	// false
	
	intSlice = []int{5, 9, 14, 351, 614, 999}	// sorted
	fmt.Println(sort.IntsAreSorted(intSlice))	// true
}

输出:

false
true

 

StringsAreSorted函数测试字符串切片是否按升序排序。如果按升序找到字符串切片,则返回true,否则返回false。

func StringsAreSorted(strSlice []string) bool

示例代码:

package main
 
import (
    "fmt"
    "sort"
)
 
func main() {
    strSlice := []string{"Jamaica","Estonia","Indonesia","Hong Kong"} // unsorted
    fmt.Println(sort.StringsAreSorted(strSlice))	// false
	
    strSlice = []string{"JAMAICA","Estonia","indonesia","hong Kong"} // unsorted
    fmt.Println(sort.StringsAreSorted(strSlice))	// false
	
	strSlice = []string{"estonia","hong Kong","indonesia","jamaica"} // sorted
    fmt.Println(sort.StringsAreSorted(strSlice))	// true
}

输出:

false
false
true

 

Float64sAreSorted函数测试float64s的切片是否按升序排序。如果按升序找到float64的切片,则返回true,否则返回false。

func Float64sAreSorted(fltSlice []float64) bool

示例代码:

package main

import (
	"fmt"
	"sort"
)

func main() {
	fltSlice := []float64{18787677.878716, 565435.321, 7888.545, 8787677.8716, 987654.252} // unsorted
	fmt.Println(sort.Float64sAreSorted(fltSlice))	// false
	
	fltSlice = []float64{565435.321, 887888.545, 8787677.8716, 91187654.252} // sorted
	fmt.Println(sort.Float64sAreSorted(fltSlice))	// true
}

输出:

false
true

 

SearchInts函数在int的排序切片中搜索x的位置,并返回Search指定的索引。如果切片仅按排序顺序排列,则此函数有效。如果在intSlice中找到x,则返回intSlice的索引位置,否则返回x适合排序切片的索引位置。以下示例显示了SearchInts() 函数的用法:

func SearchInts(intSlice []int, x int) int

示例代码:

package main

import (
	"fmt"
	"sort"
)

func main() {
	// integer slice in unsort order
	intSlice := []int{55, 22, 18, 9, 12, 82, 28, 36, 45, 65}
	x := 18
	pos := sort.SearchInts(intSlice,x)
	fmt.Printf("Found %d at index %d in %v\n", x, pos, intSlice)
		
	// slice need to be sort in ascending order before to use SearchInts
	sort.Ints(intSlice)	// slice sorted
	pos = sort.SearchInts(intSlice,x)
	fmt.Printf("Found %d at index %d in %v\n", x, pos, intSlice)
	
	x = 54
	pos = sort.SearchInts(intSlice,x)
	fmt.Printf("Found %d at index %d in %v\n", x, pos, intSlice)
	
	x = 99
	pos = sort.SearchInts(intSlice,x)
	fmt.Printf("Found %d at index %d in %v\n", x, pos, intSlice)
	
	x = -5
	pos = sort.SearchInts(intSlice,x)
	fmt.Printf("Found %d at index %d in %v\n", x, pos, intSlice)
}

输出:

Found 18 at index 0 in [55 22 18 9 12 82 28 36 45 65]
Found 18 at index 2 in [9 12 18 22 28 36 45 55 65 82]
Found 54 at index 7 in [9 12 18 22 28 36 45 55 65 82]
Found 99 at index 10 in [9 12 18 22 28 36 45 55 65 82]
Found -5 at index 0 in [9 12 18 22 28 36 45 55 65 82]

 

SearchStrings函数在排序的字符串切片中搜索x的位置,并返回Search指定的索引。如果切片仅按排序顺序排列,则此函数有效。如果在strSlice中找到x,则返回strSlice的索引位置,否则返回索引位置,其中x适合排序切片。以下示例显示了SearchStrings() 函数的用法:

func SearchStrings(strSlice []string, x string) int

示例代码:

package main

import (
	"fmt"
	"sort"
)

func main() {
	// string slice in unsorted order
	strSlice := []string{"Texas","Washington","Montana","Alaska","Indiana","Ohio","Nevada"}
	x := "Montana"
	pos := sort.SearchStrings(strSlice,x)	
	fmt.Printf("Found %s at index %d in %v\n", x, pos, strSlice)
	
	// slice need to be sort in ascending order before to use SearchStrings
	sort.Strings(strSlice)	// slice sorted
	pos = sort.SearchStrings(strSlice,x)
	fmt.Printf("Found %s at index %d in %v\n", x, pos, strSlice)
	
	x = "Missouri"
	pos = sort.SearchStrings(strSlice,x)
	fmt.Printf("Found %s at index %d in %v\n", x, pos, strSlice)
	
	x = "Utah"
	pos = sort.SearchStrings(strSlice,x)
	fmt.Printf("Found %s at index %d in %v\n", x, pos, strSlice)
	
	x = "Ohio"
	pos = sort.SearchStrings(strSlice,x)
	fmt.Printf("Found %s at index %d in %v\n", x, pos, strSlice)
	
	x = "OHIO"
	pos = sort.SearchStrings(strSlice,x)
	fmt.Printf("Found %s at index %d in %v\n", x, pos, strSlice)
	
	x = "ohio"
	pos = sort.SearchStrings(strSlice,x)
	fmt.Printf("Found %s at index %d in %v\n", x, pos, strSlice)
}

输出:

Found Montana at index 5 in [Texas Washington Montana Alaska Indiana Ohio Nevada]
Found Montana at index 2 in [Alaska Indiana Montana Nevada Ohio Texas Washington]
Found Missouri at index 2 in [Alaska Indiana Montana Nevada Ohio Texas Washington]
Found Utah at index 6 in [Alaska Indiana Montana Nevada Ohio Texas Washington]
Found Ohio at index 4 in [Alaska Indiana Montana Nevada Ohio Texas Washington]
Found OHIO at index 4 in [Alaska Indiana Montana Nevada Ohio Texas Washington]
Found ohio at index 7 in [Alaska Indiana Montana Nevada Ohio Texas Washington]

 

SearchFloat64s函数在float64的排序切片中搜索x的位置,并返回Search指定的索引。如果切片仅按排序顺序排列,则此函数有效。如果在fltSlice中找到x,则返回fltSlice的索引位置,否则返回x适合排序切片的索引位置。以下示例显示了SearchFloat64s() 函数的用法:

func SearchFloat64s(fltSlice []float64, x float64) 

示例代码:

package main

import (
	"fmt"
	"sort"
)

func main() {
	// string slice in unsorted order
	fltSlice := []float64{962.25, 514.251, 141.214, 96.142, 85.14}
	x := 141.214
	pos := sort.SearchFloat64s(fltSlice,x)	
	fmt.Printf("Found %f at index %d in %v\n", x, pos, fltSlice)
	
	// slice need to be sort in ascending order before to use SearchFloat64s
	sort.Float64s(fltSlice)	// slice sorted
	pos = sort.SearchFloat64s(fltSlice,x)
	fmt.Printf("Found %f at index %d in %v\n", x, pos, fltSlice)
	
	x = 8989.251
	pos = sort.SearchFloat64s(fltSlice,x)
	fmt.Printf("Found %f at index %d in %v\n", x, pos, fltSlice)
	
	x = 10.251
	pos = sort.SearchFloat64s(fltSlice,x)
	fmt.Printf("Found %f at index %d in %v\n", x, pos, fltSlice)
	
	x = 411.251
	pos = sort.SearchFloat64s(fltSlice,x)
	fmt.Printf("Found %f at index %d in %v\n", x, pos, fltSlice)

	x = -411.251
	pos = sort.SearchFloat64s(fltSlice,x)
	fmt.Printf("Found %f at index %d in %v\n", x, pos, fltSlice)
}

输出:

Found 141.214000 at index 0 in [962.25 514.251 141.214 96.142 85.14]
Found 141.214000 at index 2 in [85.14 96.142 141.214 514.251 962.25]
Found 8989.251000 at index 5 in [85.14 96.142 141.214 514.251 962.25]
Found 10.251000 at index 0 in [85.14 96.142 141.214 514.251 962.25]
Found 411.251000 at index 3 in [85.14 96.142 141.214 514.251 962.25]
Found -411.251000 at index 0 in [85.14 96.142 141.214 514.251 962.25]

 

Search函数在string/float/int的排序切片中搜索x的位置,并返回Search指定的索引。如果在数据中找到x,则返回数据的索引位置,否则返回索引位置,其中x适合排序切片。此功能适用于升序和降序切片,而以上3个搜索功能仅适用于升序。以下示例显示了Search() 函数的用法:

sort.Search(len(data), func(i int) bool { return data[i] >= x })

示例代码:

package main
 
import (
    "fmt"
    "sort"
)
 
func main() {
	
	fmt.Println("\n######## SearchInts not works in descending order  ######## ")    
	intSlice := []int{55, 54, 53, 52, 51, 50, 48, 36, 15, 5}	// sorted slice in descending
    x := 36
    pos := sort.SearchInts(intSlice,x)
    fmt.Printf("Found %d at index %d in %v\n", x, pos, intSlice)

	fmt.Println("\n######## Search works in descending order  ########")	
	i := sort.Search(len(intSlice), func(i int) bool { return intSlice[i] <= x })
	fmt.Printf("Found %d at index %d in %v\n", x, i, intSlice)
	
	fmt.Println("\n\n######## SearchStrings not works in descending order  ######## ")		
	// sorted slice in descending
	strSlice := []string{"Washington","Texas","Ohio","Nevada","Montana","Indiana","Alaska"}	
    y := "Montana"	
    posstr := sort.SearchStrings(strSlice,y)
    fmt.Printf("Found %s at index %d in %v\n", y, posstr, strSlice)
	
	fmt.Println("\n######## Search works in descending order  ########")
	j := sort.Search(len(strSlice), func(j int) bool {return strSlice[j] <= y})
	fmt.Printf("Found %s at index %d in %v\n", y, j, strSlice)

	fmt.Println("\n######## Search works in ascending order  ########")		
    fltSlice := []float64{10.10, 20.10, 30.15, 40.15, 58.95} // string slice in float64
    z := 40.15
    k := sort.Search(len(fltSlice), func(k int) bool {return fltSlice[k] >= z})
	fmt.Printf("Found %f at index %d in %v\n", z, k, fltSlice)	
}

输出:

######## SearchInts not works in descending order  ########
Found 36 at index 0 in [55 54 53 52 51 50 48 36 15 5]

######## Search works in descending order  ########
Found 36 at index 7 in [55 54 53 52 51 50 48 36 15 5]


######## SearchStrings not works in descending order  ########
Found Montana at index 0 in [Washington Texas Ohio Nevada Montana Indiana Alaska]

######## Search works in descending order  ########
Found Montana at index 4 in [Washington Texas Ohio Nevada Montana Indiana Alaska]

######## Search works in ascending order  ########
Found 40.150000 at index 3 in [10.1 20.1 30.15 40.15 58.95]

 

Sort函数按升序和降序对数据接口进行排序。它首先调用数据。Len用于确定n,O(n*log(n)) 调用数据。更少和数据。交换。以下示例显示了Sort() 函数的用法:

func Sort(data Interface)

示例代码:

package main

import (
	"fmt"
	"sort"
)

type Mobile struct {
	Brand string
	Price int
}


// ByPrice implements sort.Interface for []Mobile based on
// the Price field.
type ByPrice []Mobile
func (a ByPrice) Len() int           { return len(a) }
func (a ByPrice) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByPrice) Less(i, j int) bool { return a[i].Price < a[j].Price }

// ByBrand implements sort.Interface for []Mobile based on
// the Brand field.
type ByBrand []Mobile
func (a ByBrand) Len() int           { return len(a) }
func (a ByBrand) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByBrand) Less(i, j int) bool { return a[i].Brand > a[j].Brand }

func main() {
	mobile := []Mobile{
		{"Sony", 952},
		{"Nokia", 468},
		{"Apple", 1219},
		{"Samsung", 1045},
	}
	fmt.Println("\n######## Before Sort #############\n")
	for _, v := range mobile {
		fmt.Println(v.Brand, v.Price)
	}
	
	fmt.Println("\n\n######## Sort By Price [ascending] ###########\n")
	sort.Sort(ByPrice(mobile))
	for _, v := range mobile {
		fmt.Println(v.Brand, v.Price)
	}	
	
	fmt.Println("\n\n######## Sort By Brand [descending] ###########\n")
	sort.Sort(ByBrand(mobile))
	for _, v := range mobile {
		fmt.Println(v.Brand, v.Price)
	}
}

输出:

######## Before Sort #############

Sony 952
Nokia 468
Apple 1219
Samsung 1045


######## Sort By Price [ascending] ###########

Nokia 468
Sony 952
Samsung 1045
Apple 1219


######## Sort By Brand [descending] ###########

Sony 952
Samsung 1045
Nokia 468
Apple 1219

 

IsSorted函数报告数据排序依据是返回true还是false。以下示例显示了IsSorted() 函数的用法:

func IsSorted(data Interface) bool

示例代码:

package main

import (
	"fmt"
	"sort"
)

type Mobile struct {
	Brand string
	Price int
}


// ByPrice implements sort.Interface for []Mobile based on
// the Price field.
type ByPrice []Mobile
func (a ByPrice) Len() int           { return len(a) }
func (a ByPrice) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByPrice) Less(i, j int) bool { return a[i].Price < a[j].Price }

func main() {
	mobile1 := []Mobile{
		{"Sony", 952},
		{"Nokia", 468},
		{"Apple", 1219},
		{"Samsung", 1045},
	}	
	fmt.Println("\nFound mobile1 price is sorted :", sort.IsSorted(ByPrice(mobile1)))	// false
	
	mobile2 := []Mobile{
		{"Sony", 452},
		{"Nokia", 768},
		{"Apple", 919},
		{"Samsung", 1045},
	}	
	fmt.Println("\nFound mobile2 price is sorted :", sort.IsSorted(ByPrice(mobile2)))	// true
}

输出:

Found mobile1 price is sorted : false

Found mobile2 price is sorted : true

 

Slice函数根据提供的less函数对提供的切片进行排序。如果提供的接口不是切片,则该函数会崩溃。以下示例显示了Slice() 函数的用法:

func Slice(slice interface{}, less func(i, j int) bool)

示例代码:

package main

import (
	"fmt"
	"sort"
)

func main() {
	mobile := []struct {
		Brand string
		Price  int
	}{
		{"Nokia", 700},
		{"Samsung", 505},
		{"Apple", 924},
		{"Sony", 655},
	}
	sort.Slice(mobile, func(i, j int) bool { return mobile[i].Brand < mobile[j].Brand })	
	fmt.Println("\n\n######## Sort By Brand [ascending] ###########\n")
    for _, v := range mobile {
        fmt.Println(v.Brand, v.Price)
    }
	
	sort.Slice(mobile, func(i, j int) bool { return mobile[i].Brand > mobile[j].Brand })
	fmt.Println("\n\n######## Sort By Brand [descending] ###########\n")
    for _, v := range mobile {
        fmt.Println(v.Brand, v.Price)
    }
	
	sort.Slice(mobile, func(i, j int) bool { return mobile[i].Price < mobile[j].Price })
	fmt.Println("\n\n######## Sort By Price [ascending] ###########\n")
    for _, v := range mobile {
        fmt.Println(v.Brand, v.Price)
    }
	
	
	mobile = []struct {
		Brand string
		Price  int
	}{
		{"MI", 900},
		{"OPPO", 305},
		{"iPhone", 924},
		{"sony", 655},
	}
	
	sort.Slice(mobile, func(i, j int) bool { return mobile[i].Brand < mobile[j].Brand })	
	fmt.Println("\n\n######## Sort By Brand [ascending] ###########\n")
    for _, v := range mobile {
        fmt.Println(v.Brand, v.Price)
    }
	
}

输出:

######## Sort By Brand [ascending] ###########

Apple 924
Nokia 700
Samsung 505
Sony 655


######## Sort By Brand [descending] ###########

Sony 655
Samsung 505
Nokia 700
Apple 924


######## Sort By Price [ascending] ###########

Samsung 505
Sony 655
Nokia 700
Apple 924


######## Sort By Brand [ascending] ###########

MI 900
OPPO 305
iPhone 924
sony 655

 

此SliceIsSorted函数测试切片是否已排序。如果数据已排序,则返回true或false。以下示例显示了SliceIsSorted() 函数的用法:

func SliceIsSorted(slice interface{}, less func(i, j int) bool) bool

示例代码:

package main

import (
	"fmt"
	"sort"
)

func main() {
	mobile := []struct {
		Brand string
		Price  int
	}{
		{"Nokia", 700},
		{"Samsung", 505},
		{"Apple", 924},
		{"Sony", 655},
	}
	result := sort.SliceIsSorted(mobile, func(i, j int) bool { return mobile[i].Price < mobile[j].Price })
	fmt.Println("Found price sorted:", result) // false
    
	mobile = []struct {
		Brand string
		Price  int
	}{
		{"Nokia", 700},
		{"Samsung", 805},
		{"Apple", 924},
		{"Sony", 955},
	}
	result = sort.SliceIsSorted(mobile, func(i, j int) bool { return mobile[i].Price < mobile[j].Price })
	fmt.Println("Found price sorted:", result) // true
	
	mobile = []struct {
		Brand string
		Price  int
	}{
		{"iPhone", 900},
		{"MI", 805},
		{"OPPO", 724},
		{"Sony", 655},
	}
	result = sort.SliceIsSorted(mobile, func(i, j int) bool { return mobile[i].Brand < mobile[j].Brand })
	fmt.Println("Found brand sorted:", result) // false
}

输出:

Found price sorted: false
Found price sorted: true
Found brand sorted: false

 

IntSlice将Interface的方法附加到 []int,并按递增顺序排序。Len曾经找到切片的长度。Search返回将SearchInts应用于接收器和x的结果。排序 用于对切片进行排序。 以下示例显示了IntSlice() 函数的用法:

type IntSlice []int

示例代码:

package main

import (
	"fmt"
	"sort"
)

func main() {	
	s := []int{9, 22, 54, 33, -10, 40} // unsorted
	sort.Sort(sort.IntSlice(s))
	fmt.Println(s)	// sorted
	fmt.Println("Length of Slice: ", sort.IntSlice.Len(s))	// 6
	fmt.Println("40 found in Slice at position: ", sort.IntSlice(s).Search(40))		//	4
	fmt.Println("82 found in Slice at position: ", sort.IntSlice(s).Search(82))		//	6
	fmt.Println("6 found in Slice at position: ", sort.IntSlice(s).Search(6))		//	0
}

输出:

[-10 9 22 33 40 54]
Length of Slice:  6
40 found in Slice at position:  4
82 found in Slice at position:  6
6 found in Slice at position:  1

 

StringSlice将Interface的方法附加到 []string,并按递增顺序排序。Len曾经找到切片的长度。Search返回将SearchStrings应用于接收方和x的结果。排序 用于对切片进行排序。以下示例显示了StringSlice函数的用法:

type StringSlice []string

示例代码:

package main

import (
	"fmt"
	"sort"
)

func main() {	
	s := []string{"Washington","Texas","Ohio","Nevada","Montana","Indiana","Alaska"} // unsorted
	sort.Sort(sort.StringSlice(s))
	fmt.Println(s)	// sorted
	fmt.Println("Length of Slice: ", sort.StringSlice.Len(s))	// 7
	fmt.Println("Texas found in Slice at position: ", sort.StringSlice(s).Search("Texas"))		//	5
	fmt.Println("Montana found in Slice at position: ", sort.StringSlice(s).Search("Montana"))	//	2
	fmt.Println("Utah found in Slice at position: ", sort.StringSlice(s).Search("Utah"))		//	6
	
	fmt.Println("OHIO found in Slice at position: ", sort.StringSlice(s).Search("OHIO"))		//	4
	fmt.Println("Ohio found in Slice at position: ", sort.StringSlice(s).Search("Ohio"))		//	4
	fmt.Println("ohio found in Slice at position: ", sort.StringSlice(s).Search("ohio"))		//	7
}

输出:

[Alaska Indiana Montana Nevada Ohio Texas Washington]
Length of Slice:  7
Texas found in Slice at position:  5
Montana found in Slice at position:  2
Utah found in Slice at position:  6
OHIO found in Slice at position:  4
Ohio found in Slice at position:  4
ohio found in Slice at position:  7

 

Float64Slice将Interface的方法附加到 []float64,并按递增顺序排序。Len曾经找到切片的长度。Search返回将SearchFloat64s应用于接收器和x的结果。排序 用于对切片进行排序。以下示例显示了Float64Slice函数的用法:

type Float64Slice []float64

示例代码:

package main

import (
	"fmt"
	"sort"
)

func main() {	
	s := []float64{85.201, 14.74, 965.25, 125.32, 63.14} // unsorted
	sort.Sort(sort.Float64Slice(s))
	fmt.Println(s)	// sorted
	fmt.Println("Length of Slice: ", sort.Float64Slice.Len(s))	// 5
	fmt.Println("123.32 found in Slice at position: ", sort.Float64Slice(s).Search(125.32))		//	3
	fmt.Println("999.15 found in Slice at position: ", sort.Float64Slice(s).Search(999.15))		//	5
	fmt.Println("12.14 found in Slice at position: ", sort.Float64Slice(s).Search(12.14))		//	0	
}

输出:

[14.74 63.14 85.201 125.32 965.25]
Length of Slice:  5
123.32 found in Slice at position:  3
999.15 found in Slice at position:  5
12.14 found in Slice at position:  0

 

Reverse函数以相反的顺序返回切片。以下示例显示了Reverse() 函数的用法:

func Reverse(data Interface) Interface

示例代码:

package main

import (
	"fmt"
	"sort"
)

func main() {
	a := []int{15, 4, 33, 52, 551, 90, 8, 16, 15, 105}    // unsorted
	sort.Sort(sort.Reverse(sort.IntSlice(a)))
	fmt.Println("\n",a)
	
	a = []int{-15, -4, -33, -52, -551, -90, -8, -16, -15, -105}     // unsorted
	sort.Sort(sort.Reverse(sort.IntSlice(a)))
	fmt.Println("\n",a)
	
	
	b := []string{"Montana","Alaska","Indiana","Nevada","Washington","Ohio","Texas"}   // unsorted
	sort.Sort(sort.Reverse(sort.StringSlice(b)))
	fmt.Println("\n",b)
	
	b = []string{"ALASKA","indiana","OHIO","Nevada","Washington","TEXAS","Montana"}  // unsorted
	sort.Sort(sort.Reverse(sort.StringSlice(b)))
	fmt.Println("\n",b)
	
	c := []float64{90.10, 80.10, 160.15, 40.15, 8.95} //	unsorted
	sort.Sort(sort.Reverse(sort.Float64Slice(c)))
	fmt.Println("\n",c)
	
	c = []float64{-90.10, -80.10, -160.15, -40.15, -8.95} // unsorted
	sort.Sort(sort.Reverse(sort.Float64Slice(c)))
	fmt.Println("\n",c)
}

输出:

 [551 105 90 52 33 16 15 15 8 4]
 [-4 -8 -15 -15 -16 -33 -52 -90 -105 -551]
 [Washington Texas Ohio Nevada Montana Indiana Alaska]
 [indiana Washington TEXAS OHIO Nevada Montana ALASKA]
 [160.15 90.1 80.1 40.15 8.95]
 [-8.95 -40.15 -80.1 -90.1 -160.15]
Go语言教程之边写边学:标准库:Context包

上下文包最佳实践

在Go中使用上下文包有几个最佳实践:

  • 使用context.WithCancel,context.WithTimeout或context.WithDeadline创建带有超时或取消信号的上下文。
  • 始终将上下文作为第一个参数传递给可能需要很长时间才能完成的函数,例如网络请求或数据库查询。
  • 使用context.Value存储和检索与上下文关联的值,例如用户ID或请求ID。
  • 使用context.WithValue基于现有上下文创建新上下文,并将其他值与其关联。
  • 检查上下文的Done通道,查看它是否已被取消。
  • 在整个应用程序中使用上下文包来传播请求范围的值和取消信号,而不是使用全局变量或手动信号。
  • 避免使用context.Background(),因为它没有超时或取消信号,而是使用context.TODO() 表示上下文稍后将被调用方替换。
  • 不要将上下文存储在结构中,而是将它们作为参数传递给函数。
  • 始终检查上下文感知函数的错误返回值,以查看上下文是否被取消或超时。

 

Go中的上下文包用于跨API边界传递请求范围的值、取消信号和截止时间。它可用于存储元数据、取消信号、超时和其他请求范围的值。上下文包提供了一种取消长时间运行的操作以及跨API边界存储元数据的方法。它通常与http包一起使用,以管理HTTP请求的请求范围值和取消信号。

它允许您在多个函数调用和goroutine之间传播请求范围的值,从而更轻松地管理应用程序中的信息流。

context.Context是使用context.With*函数创建,例如context.WithValuecontext.WithCancelcontext.WithTimeout。这些函数返回新的上下文,携带指定值或信号的上下文值。

context.Context可以作为参数传递给需要访问请求范围值或侦听取消信号的函数和方法。然后,这些函数可以使用context.Value和context.Done访问上下文中存储的值和信号的done方法。

在需要取消长时间运行的操作或跨多个goroutine传播请求范围的值的情况下,上下文包特别有用。它通常用于服务器端编程和其他并发方案。

应始终将上下文作为第一个参数传递给执行可能被取消的工作的任何函数。

例如,HTTP服务器可以使用上下文在客户端断开连接时取消请求的工作,数据库包可以使用上下文来实现可取消的查询,等等。

context包定义了 Context 类型,该类型是一个Go接口,具有四个方法,分别名为Deadline()、Done()、Err() 和Value():

type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() 
    Err() 
    Value(key) 
}

上下文接口定义的方法

方法描述
Value(key)返回对应的值
Done()此方法返回可用于接收取消通知的频道
Deadline()此方法返回time.Time, 表示请求的截止日期,如果没有指定截止日期,则布尔值为false。
Err()此方法返回一个错误,指示完成通道接收信号的原因。上下文包定义了两个可用于比较错误的变量:Canceled表示请求已取消,DeadlineExeeded表示截止日期已过。

用于创建上下文值的上下文包函数

方法描述
Background()此方法返回默认上下文,从中派生其他上下文。
WithCancel(ctx)此方法返回一个上下文和一个取消函数。
WithDeadline(ctx, time)此方法返回一个带有截止日期的上下文,该截止日期用time.Time表示值。
WithTimeout(ctx, duration)此方法返回一个带有截止日期的上下文,该截止日期用time.Time表示值。
WithValue(ctx, key, val)此方法返回一个包含指定键值对的上下文。

 

context.WithCancel

下面是一个示例,说明context.WithCancel可以在Go中使用:

package main

    import (
        "context"
        "fmt"
        "time"
    )
    
    func doWork(ctx context.Context) {
        for {
            select {
            case <-ctx.Done():
                fmt.Println("Work done!")
                return
            default:
                fmt.Println("Working...")
            }
        }
    }
    
    func main() {
        ctx, cancel := context.WithCancel(context.Background())
        defer cancel() // 推迟执行cancel
    
        go doWork(ctx)
    
        // Wait for a while before canceling the context
        select {
        	case <-ctx.Done():
        	case <-time.After(time.Second * 3):
            	cancel()
        }
    }

在此示例中,我们使用context创建一个新的上下文 ctx.WithCancel(context.background())中。context.Background() 函数返回一个空的context。context.WithCancel 返回一个新的上下文和一个取消函数。我们推迟取消函数,以便在主函数退出时调用它。在 doWork 函数中,它将检查上下文是否已完成,如果是,则返回该函数。

在main函数中,我们正在运行一个goroutine,并通过传递上下文来完成其中的工作。等待3秒后,main函数会通过调用cancel函数来取消上下文,这将使上下文的Done通道关闭。因此,doWork函数将从Done通道接收,打印 "Work done!" 并返回。

 

context.WithTimeout

在Go中,您可以使用context.WithTimeout函数创建一个新上下文,该上下文在指定的超时时间过后被取消。该函数采用两个参数:现有上下文和超时持续时间。

下面是如何使用上下文的示例WithTimeout创建在5秒后取消的上下文:

package main

    import (
        "context"
        "fmt"
        "time"
    )
    
    func main() {
        ctx := context.Background()
        ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
        defer cancel()
    
        // Do some work
        select {
        case <-ctx.Done():
            fmt.Println("Work completed")
        case <-time.After(10 * time.Second):
            fmt.Println("Work took longer than 10 seconds")
        }
    }

在此示例中,上下文是通过调用context.WithTimeout与后台上下文5秒的超时创建。该函数返回一个新上下文和一个用于取消上下文的函数。cancel函数在defer语句中调用,以确保在函数返回时取消上下文。select语句用于等待上下文完成或超时结束。

您还可以使用ctx检查上下文是否已完成。Done() 通道,您可以在select语句或循环中使用此通道来检查上下文是否完成,如果完成则意味着上下文已过期。

 

context.WithDeadline

在Go中,context.WithDeadline 函数创建具有关联截止时间的新上下文。截止日期是一个特定的时间点,在此时间点之后,上下文将被视为"死亡",任何相关工作都将被取消。该函数接受两个参数:现有上下文和截止时间。它返回一个新的上下文,该上下文将在指定的截止时间取消。

下面是一个示例:

package main

    import (
        "context"
        "fmt"
        "time"
    )
    
    func main() {
        ctx := context.Background()
        deadline := time.Now().Add(time.Second * 5)
        ctx, cancel := context.WithDeadline(ctx, deadline)
        defer cancel()
    
        select {
        case <-time.After(time.Second * 10):
            fmt.Println("overslept")
        case <-ctx.Done():
            fmt.Println(ctx.Err())
        }
    }

在此示例中,将创建一个背景上下文,然后设置未来5秒的截止时间。WithDeadline 函数用于基于背景上下文创建具有指定截止时间的新上下文。select语句用于等待上下文被取消或等待10秒过去。如果在10秒之前取消上下文,它将打印错误消息上下文截止时间超过,否则将打印"overslept"

 

使用Context的SQL查询超时

要在Golang中使用超时的SQL查询,您可以使用上下文包来设置查询执行的截止时间。首先,使用上下文创建具有超时的context.WithTimeout函数。然后,将上下文作为第一个参数传递给查询执行函数(例如db.QueryContext() 或db.ExecContext())。

下面是如何为SELECT查询设置1秒超时的示例:

package main

    import (
      "context"
      "database/sql"
      "fmt"
      "time"
    )
    
    func main() {
      // Open a connection to the database
      db, _ := sql.Open("driverName", "dataSourceName")
    
      // Create a context with a timeout of 1 second
      ctx, cancel := context.WithTimeout(context.Background(), time.Second)
      defer cancel()
    
      // Execute the query with the context
      rows, err := db.QueryContext(ctx, "SELECT * FROM table")
      if err != nil {
        fmt.Println(err)
      }
      defer rows.Close()
    
      // Handle the query results
      // ...
    }

 

使用上下文超时读取文件

在Go中,可以使用上下文包来设置读取文件的超时时间。下面是一个示例:

package main

    import (
        "context"
        "fmt"
        "io/ioutil"
        "time"
    )
    
    func main() {
        ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
        defer cancel()
    
        data, err := ioutil.ReadFile("example.txt", ctx)
        if err != nil {
            fmt.Println("Error:", err)
            return
        }
    
        fmt.Println(string(data))
    }

在此示例中,我们首先使用context创建一个超时为2秒的context.WithTimeout。然后,我们将此上下文传递给ioutil。ReadFile读取文件"example.txt"的内容。如果读取文件的时间超过2秒,则上下文的Done通道将关闭,并且ioutil.ReadFile返回错误。

 

将上下文用于HTTP

在Go中,您可以使用上下文包来设置HTTP请求的超时。下面是一个示例:

package main

    import (
        "context"
        "fmt"
        "io/ioutil"
        "net/http"
        "time"
    )
    
    func main() {
        ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
        defer cancel()
    
        req, err := http.NewRequest("GET", "https://example.com", nil)
        if err != nil {
            fmt.Println("Error:", err)
            return
        }
        req = req.WithContext(ctx)
    
        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
            fmt.Println("Error:", err)
            return
        }
        defer resp.Body.Close()
    
        body, err := ioutil.ReadAll(resp.Body)
        if err != nil {
            fmt.Println("Error:", err)
            return
        }
    
        fmt.Println(string(body))
    }

在此示例中,我们首先使用context创建一个超时为2秒的context.WithTimeout。然后,我们使用req.WithContext(ctx) 将此上下文附加到HTTP请求中。当我们使用http.Client.Do方法发出请求时,如果在收到响应之前关闭了上下文的Done通道,它将自动取消请求。

您还可以使用客户端库(如golang.org/x/net/context/ctxhttp)发出带有上下文的http请求,该库具有Get和Post方法,该方法将上下文作为第一个参数并返回响应和错误。

package main

  import (
      "context"
      "fmt"
      "io/ioutil"
      "net/http"
      "time"
  
      "golang.org/x/net/context/ctxhttp"
  )
  
  func main() {
      ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
      defer cancel()
  
      resp, err := ctxhttp.Get(ctx, nil, "https://example.com")
      if err != nil {
          fmt.Println("Error:", err)
          return
      }
      defer resp.Body.Close()
  
      body, err := ioutil.ReadAll(resp.Body)
      if err != nil {
          fmt.Println("Error:", err)
          return
      }
  
      fmt.Println(string(body))
  }

此示例使用ctxhttp.Get方法向"https://example.com"发出GET请求,超时为2秒。

请务必注意,在这两种情况下,如果上下文关闭了Done通道,则请求将被取消,但不会关闭连接。应用程序负责关闭连接。

 

使用Context作为键值存储

在Go中,您可以使用上下文包来存储可以与请求或一段代码一起传递的键值数据对。这允许您将其他信息与请求或代码段相关联,而不必将其作为显式参数传递。下面是一个示例:

package main

    import (
        "context"
        "fmt"
    )
    
    func main() {
        ctx := context.WithValue(context.Background(), "user_id", "12345")
        // use the context in a function
        processRequest(ctx)
    }
    
    func processRequest(ctx context.Context) {
        userID := ctx.Value("user_id").(string)
        fmt.Println("User ID:", userID)
    }

在此示例中,我们首先使用context创建一个上下文。WithValue方法。我们传递上下文。Background() 作为父上下文,以及方法的键值对 "user_id" 和 "12345"。然后,我们将此上下文传递给processRequest函数。在函数中,我们使用Value方法从上下文中检索"user_id"值,并将其打印出来。

请务必注意,上下文值仅用于传输进程和API边界的请求范围数据,而不用于将可选参数传递给函数。如果需要将可选参数传递给函数,最好使用结构或函数选项模式。

此外,上下文值不是线程安全的,如果您处于并发环境中,请使用sync.Map或同等产品。

  • 当前日期:
  • 北京时间:
  • 时间戳:
  • 今年的第:18周
  • 我的 IP:3.137.154.13
农历
五行
冲煞
彭祖
方位
吉神
凶神
极简任务管理 help
+ 0 0 0
Task Idea Collect