2013-11-27 8 views
32

http://golang.org/ref/spec#Comparison_operatorsGoは文字列比較をどのようにしますか?

特別な機能を持たない文字列比較をサポートしています。 Goランタイムは、文字列リテラルを比較するためにバックグラウンドで動作しますか?

+1

このような状況は、文字列がGo言語の組み込み型であるためです(Goの別の+1)。文字列がアドオン構造である言語では、特別な関数が必要です。 – miltonb

答えて

51

以下のアセンブリダンプでわかるように、ショートサーキットチェックの後、実行時(行17)の文字列比較がruntime.eqstring関数に委譲され、2つのオペランドが同じメモリ内文字列(行11 ):仕様が定義としてだけで演算子を使用し、比較が持つO(n)とすることを期待する:

$ 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  , 

あなたはコンパイラやランタイム上で作業している場合を除き、これはあまりにも多くのあなたには関係ないはず文字列の長さ。

+3

ブラックボックスの学習を通じて段階的に物事を理解するのが好きです。カーテン。ソースと一緒に解説いただきありがとうございます。 – Brenden

27

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

私はこの答えを選んでいませんでした。なぜなら、他の人は何が起こっているのかもっと有益な解説をしていますが、あなたの答えはありがとうございます:) – Brenden

関連する問題