2016-10-12 7 views
1

文字列の型エイリアスの使用string.join機能Golang:私は、文字列 <p></p>のようなタイプのSpecialScopes列</p> <p>の型の別名を持っていると私はstrings.Joinを使用して、このタイプの配列に参加したい

func MergeScopes(scopes ...SpecialScopes) SpecialScopes { 
    return strings.Join(scopes, ",") 
} 

しかし、上記と私はエラー

cannot use scopes (type []SpecialScopes) as type []string in argument to strings.Join 
cannot use strings.Join(scopes, ",") (type string) as type SpecialScopes in return argument 

を取得するには、ミリアンペアする方法がありますke golangは、SpecialScopesは文字列の別の名前であり、その上で結合関数を実行することを認識していますか? これを行う最も効率的な方法は何ですか?私が見る1つの方法は、配列のすべての要素を文字列にキャストし、結合してからSpecialScopesにキャストして値を返します。

更新1: 値をキャストする実装があります。これを行うより速い方法のための任意の提案?

func MergeScopes(scopes ...SpecialScopes) SpecialScopes { 
    var s []string 
    for _, scope := range scopes { 
     s = append(s, string(scope)) 
    } 

    return SpecialScopes(strings.Join(s, ",")) 
} 
+1

提起として答えは質問のために右であり、それは安全ではない使用していないので、それらを私はYandryのでいいと思うが、大局的、Iこの操作の速度については心配しません。これはあなたのアプリがほとんどの時間を費やす場所ではない可能性があります。この関数内でも、結合文字列を作成するallocは、サンプルコード中の中間の[[]文字列を作成するコストを犠牲にするかもしれません。 – twotwotwo

答えて

2

これは、ほとんどの場合、安全でない方法を使用しないと最も速い方法です。

func MergeScopes(scopes ...SpecialScopes) SpecialScopes { 
    if len(scopes) == 0 { 
     return "" 
    } 
    var (
     sep = []byte(", ") 
     // preallocate for len(sep) + assume at least 1 character 
     out = make([]byte, 0, (1+len(sep))*len(scopes)) 
    ) 
    for _, s := range scopes { 
     out = append(out, s...) 
     out = append(out, sep...) 
    } 
    return SpecialScopes(out[:len(out)-len(sep)]) 
} 

ベンチマークコード:https://play.golang.org/p/DrB8nM-6ws

━➤ go test -benchmem -bench=. -v -benchtime=2s 
testing: warning: no tests to run 
BenchmarkUnsafe-8  30000000    109 ns/op    32 B/op   2 allocs/op 
BenchmarkBuffer-8  20000000    255 ns/op    128 B/op   2 allocs/op 
BenchmarkCopy-8   10000000    233 ns/op    112 B/op   3 allocs/op 
BenchmarkConcat-8  30000000    112 ns/op    32 B/op   2 allocs/op 
+1

ありがとう!分析と比較は本当に助けになりました – Sakib

2

ここunsafeパッケージを使用してソリューションです:

func MergeScopes(scopes ...SpecialScopes) SpecialScopes { 
    specialScopes := *(*[]string)((unsafe.Pointer(&scopes))) 
    s := strings.Join(specialScopes, ",") 
    return *(*SpecialScopes)((unsafe.Pointer(&s))) 
} 

https://play.golang.org/p/-wsHY2eCdc

+1

不正確ではありませんが、安全でない人を指し示すことは怠っています。私たちが '[]文字列を構築するためのパフォーマンスコストを食べることを悪化させた場合(あるいは、行のコードコストそれはヤンドリーの方法です)。たとえば、SpecialScopesが 'string'から' [byte] 'に変更された場合、これはまだコンパイルされますが未定義の動作をします。意見は、私のことに気づくだけで違います。 – twotwotwo

1

あなたが本当に速い何かをしたい場合は、これはゴーでより高速な方法です:

func MergeScopes(scopes ...SpecialScopes) SpecialScopes { 
    var buffer bytes.Buffer 
    for ix, s := range scopes { 
     buffer.WriteString(string(s)) 
     if ix < len(scopes)-1 { 
      buffer.WriteString(", ")  
     } 
    } 

    return SpecialScopes(buffer.String()) 
} 

全例:https://play.golang.org/p/McWjh1yxHf

シンプルなように見えないのは分かっています。ジョイン()ですが、読みやすいです。

関連する問題