【问题标题】:How does Go do string comparison?Go 如何进行字符串比较?
【发布时间】:2013-12-12 12:49:45
【问题描述】:

http://golang.org/ref/spec#Comparison_operators

Go 支持字符串比较,没有任何特殊功能。 Go 运行时是否在幕后工作以比较字符串文字?

【问题讨论】:

  • 这种情况是因为 string 是 Go 语言的内置类型(Go 的另一个 +1)。对于字符串是附加结构的语言,需要特殊函数。

标签: go


【解决方案1】:

runtime/string.goc(go1.3):

func eqstring(s1 String, s2 String) (v bool) {
    if(s1.len != s2.len) {
        v = false;
        return;
    }
    if(s1.str == s2.str) {
        v = true;
        return;
    }
    v = runtime·memeq(s1.str, s2.str, s1.len);
}

int32
runtime·strcmp(byte *s1, byte *s2)
{
    uintptr i;
    byte c1, c2;

    for(i=0;; i++) {
        c1 = s1[i];
        c2 = s2[i];
        if(c1 < c2)
            return -1;
        if(c1 > c2)
            return +1;
        if(c1 == 0)
            return 0;
    }
}

注意runtime· 分隔符是 Unicode 中点,而不是句点。

【讨论】:

    【解决方案2】:

    正如您在以下程序集转储中所见,字符串比较在短路检查后从运行时(第 17 行)委托给 runtime.eqstring 函数,以查看两个操作数是否是相同的内存中字符串(第 17 行) 11):

    $ cat foo.go
    package main
    
    func main() {
            a := "hello"
            b := "world"
            _ = a == b
    }
    
    $ go tool 6g -S foo.go
    --- prog list "main" ---
    0000 (foo.go:3) TEXT    main+0(SB),$40-0
    0001 (foo.go:3) LOCALS  ,$0
    0002 (foo.go:4) LEAQ    go.string."hello"+0(SB),BX
    0003 (foo.go:4) MOVQ    (BX),SI
    0004 (foo.go:4) MOVQ    8(BX),CX
    0005 (foo.go:5) LEAQ    go.string."world"+0(SB),BX
    0006 (foo.go:5) MOVQ    (BX),DX
    0007 (foo.go:5) MOVQ    8(BX),AX
    0008 (foo.go:6) JMP     ,11
    0009 (foo.go:6) MOVQ    $1,AX
    0010 (foo.go:6) JMP     ,23
    0011 (foo.go:6) CMPQ    CX,AX
    0012 (foo.go:6) JNE     ,22
    0013 (foo.go:6) MOVQ    SI,(SP)
    0014 (foo.go:6) MOVQ    CX,8(SP)
    0015 (foo.go:6) MOVQ    DX,16(SP)
    0016 (foo.go:6) MOVQ    AX,24(SP)
    0017 (foo.go:6) CALL    ,runtime.eqstring+0(SB)
    0018 (foo.go:6) MOVBQZX 32(SP),BX
    0019 (foo.go:6) CMPB    BX,$0
    0020 (foo.go:6) JEQ     ,22
    0021 (foo.go:6) JMP     ,9
    0022 (foo.go:6) MOVQ    $0,AX
    0023 (foo.go:7) RET     ,
    
    --- prog list "init" ---
    0024 (foo.go:7) TEXT    init+0(SB),$0-0
    0025 (foo.go:7) MOVBQZX initdone·+0(SB),AX
    0026 (foo.go:7) LOCALS  ,$0
    0027 (foo.go:7) CMPB    AX,$0
    0028 (foo.go:7) JEQ     ,34
    0029 (foo.go:7) CMPB    AX,$2
    0030 (foo.go:7) JNE     ,32
    0031 (foo.go:7) RET     ,
    0032 (foo.go:7) CALL    ,runtime.throwinit+0(SB)
    0033 (foo.go:7) UNDEF   ,
    0034 (foo.go:7) MOVB    $2,initdone·+0(SB)
    0035 (foo.go:7) RET     ,
    

    除非您正在使用编译器或运行时,否则这不应该让您太担心:只需使用规范定义的运算符,并期望与字符串长度的比较为 O(n)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-11
      • 2022-08-14
      • 1970-01-01
      • 1970-01-01
      • 2021-03-29
      • 2018-07-11
      相关资源
      最近更新 更多