GoLang字符串比较(一)

2020/09/17 golang 共 4001 字,约 12 分钟

pic

1. 写在前面

微信公众号:[double12gzh]

关注容器技术、关注Kubernetes。问题或建议,请公众号留言。

在GoLang的使用过程中,我们难免会遇到字符串比较的问题。不知道您有没有总结过,如何做字符串比较呢?在本文中我将向在家展示一下,如何进行字符串比较。 全文将按如下三个方面进行介绍:

  • 字符串比较的不同方式
  • 忽略大小的字符串比较
  • 不同方法的性能比较

2. 字符串比较基本方式

2.1 区分大小写

相信看到这个题目,您的第一直觉肯定是So easy,也相信您也能很快的写出如下的代码:

package main

import "fmt"

func main() {
    srcString := "This a string"
    destString := "this a string"

    if srcString == destString {
        fmt.Println("Equals")
    } else {
        fmt.Println("Not Equals")
    }
}

2.2 不区分大小写

2.2.1 使用strings.ToLower

package main

import (
    "fmt"
    "strings"
)

func main() {
    ...

    if strings.ToLower(srcString) == strings.ToLower(destString) {
        fmt.Println("Equals")
    } else {
        fmt.Println("Not Equals")
    }
}

2.2.2 使用strings.Compare

package main

import (
    "fmt"
    "strings"
)

func main() {
    ...
    if strings.Compare(strings.ToLower(srcString), strings.ToLower(destString)) == 0 {
        fmt.Println("Equals")
    } else {
        fmt.Println("Not Equals")
    }
}

这种方法比2.2.1中提到的方式更加优雅和高效,在工作中,如果涉及到不区分大小的字符串的比较时,我也经常会采用这样的方式。

3. 使用EqualFold

这种方式是不区分大小的。这种方法比2.2中提到的方法更高的高效。

package main

import (
    "fmt"
    "strings"
)

func main() {
    ...

    if strings.EqualFold(srcString, destString) == true {
        fmt.Println("Equals")
    } else {
        fmt.Println("Not Equals")
    }
}

4. 性能分析

我们前面只是简单的给出了结论,哪种方式是比较高效的。那样是不严谨的,那么,如何来实际测试一下,看一下,到底哪种方式更加的高效呢? 这一章节中,我们将会通过一个测试样本进行实际测试一下。

4.1 生成数据样本

在开始之前,我们需要所准备一个数据样本,样本的获取可以通过mockaroo来得到,也可以使用以下程序来生成:

package main

import (
	"crypto/rand"
	"fmt"
	"os"
)

func GenerateRandomString(n int) string {
	const CHARACTER = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	var bytes = make([]byte, n)

	if _, err := rand.Read(bytes); err != nil {
		panic(err)
	}

	for i, c := range bytes {
		bytes[i] = CHARACTER[c % byte(len(CHARACTER))]
	}

	return string(bytes)
}

func GenFile() {
	f, err := os.Create("mock_data.txt")

	if err != nil {
		panic(err)
	}

	defer f.Close()

	var tempStr string

	for i := 0; i < 200000; i++ {
		tempStr = fmt.Sprintf("%v\n", GenerateRandomString(16))
		if _, err2 := f.WriteString(tempStr); err2 != nil {
			panic(err2)
		}
	}

}

func main() {
	GenFile()
}

我们得到了一个200000行数据的数据样本:

jeffrey@hacker ~/Desktop/hello
$ cat mock_data.txt | wc -l
200000

4.2 测试读取耗时

为了测试读取文件的耗时,我们写了以下程序:

main.go

package main

import "main/utils/reader"

func main() {
	//gen.GenFile()
	reader.ReadFile("mock_data.txt")
}

reader.go

package reader

import (
	"bufio"
	"fmt"
	"os"
)

func ReadFile(fileName string) {
	f, err := os.Open(fileName)

	if err != nil {
		panic(err)
	}

	scan := bufio.NewScanner(f)
	scan.Split(bufio.ScanLines)

	for scan.Scan() {
		cmptString := scan.Text()
		fmt.Printf("%s\n", cmptString)
	}

	f.Close()
}

执行上面获取文件的代码,耗时如下:

...
IBg0Fg79uIwwX9aF
ZcLmE0v1eUqjb6yK
EH6ykTgMTiUBtg3c
aVPont9anIcYBxcW
nKj04D2QIwx1J3VA
bwDRBkuRuw6XDn2I
79rIt3yb8zp5EMRw

real    0m1.122s
user    0m0.000s
sys     0m0.015s

jeffrey@hacker ~/Desktop/hello

4.3 区分大小写时的耗时

4.3.1 采用==时的耗时

这里测试直接使用==来判断字符串是否相等时的耗时:

func BasicCompare(src, dest string) bool {
    if srcString == destString {
        return true
    } else {
        return false
    }
}

main.go

package main

import "main/utils/reader"

func main() {
	//gen.GenFile()
	reader.ReadFile("mock_data.txt")
}

reader.go

package reader

import (
	"bufio"
	"fmt"
	"os"
)

func ReadFile(fileName string) {
    srcString := "fuckSBWu"

	f, err := os.Open(fileName)

	if err != nil {
		panic(err)
	}

	scan := bufio.NewScanner(f)
	scan.Split(bufio.ScanLines)

	for scan.Scan() {
		if BasicCompare(scan.Text(), strcString) {
            fmt.Println("Equal")
        }
	}

	f.Close()
}

看一下执行时间:

jeffrey@hacker ~/Desktop/hello
$ time go run main.go

real    0m0.436s
user    0m0.000s
sys     0m0.015s

4.3.2 使用Compare时的耗时

func CompareCompare(src, dest string) bool {
	if strings.Compare(src, dest) == 0 {
		return true
	}
	return false
}
jeffrey@hacker ~/Desktop/hello
$ time go run main.go

real    0m0.395s
user    0m0.000s
sys     0m0.015s

4.3.3 结论

strings.Compare()略显快一些。

4.4 不区分大小写时的耗时

4.4.1 使用==时的耗时

func CaseInSensitiveBasicCompare(src, dest string) bool {
	if strings.ToLower(src) == strings.ToLower(dest) {
		return true
	} else {
		return false
	}
}
jeffrey@hacker ~/Desktop/hello
$ time go run main.go

real    0m0.423s
user    0m0.000s
sys     0m0.015s

4.4.2 使用Compare时的耗时

func CaseInSensitiveCompareCompare(src, dest string) bool {
	if strings.Compare(strings.ToLower(src), strings.ToLower(dest)) == 0 {
		return true
	} else {
		return false
	}
}
jeffrey@hacker ~/Desktop/hello
$ time go run main.go

real    0m0.426s
user    0m0.015s
sys     0m0.000s

4.4.3 使用EqualFold时的耗时

jeffrey@hacker ~/Desktop/hello
$ time go run main.go

real    0m0.394s
user    0m0.015s
sys     0m0.000s

5. 总结

EqualFold是最快的一种字符串比较的方式。本文测试方式并不是很地道,不是非常的严谨,关于如何更加准确的测试,我将在明天的文章中跟大家一起分享一下。

Search

    Table of Contents