ホームページ  >  記事  >  バックエンド開発  >  Go 文字列処理の一般的なヒント

Go 文字列処理の一般的なヒント

Guanhui
Guanhui転載
2020-06-12 18:35:542517ブラウズ

Go 文字列処理の一般的なヒント

1. 複数行の文字列

str := `This is a
multiline
string.`

注 - 文字列に入力したインデントは最終結果にも保持されます。

str := `This string
    will have
    tabs in it`

2. 効率的な文字列連結方法

Go では、" " を介して文字列を連結できますが、この方法は、多数の文字列連結が処理されるシナリオでは非常に非効率的になります。 bytes.Buffer を使用して文字列を連結すると、すべてが一度に 1 つの文字列に連結されるため、より効率的な方法になります。

package main
import (
    "bytes"
    "fmt"
)
func main() {
    var b bytes.Buffer
    for i := 0; i < 1000; i++ {
        b.WriteString(randString())
    }
    fmt.Println(b.String())
}
func randString() string {
    // 模拟返回一个随机字符串
    return "abc-123-"
}

事前にすべての文字列を準備しておけば、strings.Join を通じて実現することもできます。

package main
import (
    "fmt"
    "strings"
)
func main() {
    var strs []string
    for i := 0; i < 1000; i++ {
        strs = append(strs, randString())
    }
    fmt.Println(strings.Join(strs, ""))
}
func randString() string {
    // 模拟返回一个随机字符串
    return "abc-123-"
}

3. 整数 (または任意のデータ型) を文字列に変換する

ほとんどの言語では、結合するために任意のデータ型を文字列に簡単に変換したり、文字列挿入 (たとえば、ルビでは「ID=#{id}」となります)。残念ながら、整数を強制的に文字列に変換するなどの明白な操作を Go で実行しようとすると、期待した結果は得られません。

i := 123
s := string(i)

s の出力をどうしたいですか?あなたもほとんどの人と同じように「123」と推測したなら、これ以上の間違いはありません。代わりに、「E」のような文字が表示されます。これは私たちが望んでいることではありません!

代わりに、[strconv] (https://golang.org/pkg/strconv/) のようなパッケージ、または fmt.Sprintf のような関数を使用する必要があります。たとえば、strconv.Itoa を使用して整数を文字列に変換する例を次に示します。

package main
import (
    "fmt"
    "strconv"
)
func main() {
    i := 123
    t := strconv.Itoa(i)
    fmt.Println(t)
}

fmt.Sprintf 関数を使用して、ほぼすべてのデータ型を文字列に変換することもできますが、これは通常、作成している文字列に埋め込みデータが含まれている場合に使用するためのものであり、使用されることが予想される場合ではありません。単一の整数を文字列に変換するとき。

package main
import "fmt"
func main() {
    i := 123
    t := fmt.Sprintf("We are currently processing ticket number %d.", i)
    fmt.Println(t)
}

Sprintf は fmt.Printf とほぼ同じように動作しますが、結果の文字列を標準出力に出力する代わりに文字列として返す点が異なります。

Sprintf の使用制限

前述したように、fmt.Sprintf は通常、値が埋め込まれた文字列を作成するために使用されます。これにはいくつかの理由がありますが、最も顕著な理由は、fmt.Sprintf が型チェックを行わないため、実際にコードを実行する前にエラーが見つかる可能性が低いことです。

Sprintf は、strconv パッケージで通常使用するほとんどの関数よりも遅いですが、正直に言うと、速度の差は非常に小さいため、一般に考慮する価値はありません。

4. ランダムな文字列の作成

これは実際には「簡単なテクニック」ではありませんが、よく聞かれる質問です。

Go でランダムな文字列を作成するにはどうすればよいですか?

簡単そうに聞こえます。 Ruby や Python などの多くの言語には、ランダムな文字列生成を非常に簡単にするヘルパーが用意されているので、Go にもそのようなツールが必要ですよね。答えは間違っています。

Go は、ランダムな文字列を作成するためのツールのみを提供することを選択し、詳細は開発者に任せています。最初は少し難しいかもしれませんが、文字列の生成方法を完全に制御できるという利点があります。これは、文字セット、ランダム生成のシード方法、その他の詳細を指定できることを意味します。つまり、より詳細に制御できるようになりますが、追加のコードを記述する必要があります。

ここでは、 math/rand パッケージと文字セットとして英数字のセットを使用する簡単な例を示します。

package main
import (
    "fmt"
    "math/rand"
    "time"
)
func main() {
    fmt.Println(RandString(10))
}
var source = rand.NewSource(time.Now().UnixNano())
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
func RandString(length int) string {
    b := make([]byte, length)
    for i := range b {
        b[i] = charset[source.Int63()%int64(len(charset))]
    }
    return string(b)
}

Go トレーニング グラウンドでは常に同じ文字列が出力されます

Go トレーニング グラウンドでこのコードを複数回実行すると、常に同じ文字列 -aJFLa7XPH5 が出力されることに気づくかもしれません。

これは、Go 練習場では常に同じ時間を使用するため、 rand.NewSource メソッドを使用する場合に発生します。現在の時刻に渡される値は常に同じであるため、生成される文字列は常に同じになります。

特定のニーズにはこれよりも優れたソリューションがあるかもしれませんが、これは良い出発点です。コードを改善/変更する方法を探している場合は、crypto/rand パッケージを使用してランダム データを生成することを検討してください。これは一般に安全ですが、最終的にはより多くの作業が必要になる可能性があります。

最終的に何を使用するかに関係なく、この例は開始に役立つはずです。パスワードや認証システムなどの機密データが関与しないほとんどの実用的なユースケースでは十分に機能します。乱数ジェネレーターのシードを忘れずに行ってください。これは、 math/rand パッケージで rand.Seed 関数を使用するか、ソース コードを作成することで実行できます。上の例では、ソース コードを作成することにしました。

5. 文字列パッケージ、HasPrefix およびカスタム コード

文字列を処理するとき、文字列が特定の文字列で始まるか、特定の文字列で終わるかを知りたいことは非常に一般的な状況です。たとえば、API キーがすべて sk_ で始まる場合、API リクエストで提供されるすべての API キーがこのプレフィックスで始まることを確認する必要があります。そうしないと、データベース検索に多くの時間が無駄になります。

非常に一般的な使用例のように見えるこれらの関数については、通常、文字列パッケージに直接アクセスして、役立つ可能性のあるいくつかのことを確認するのが最善の方法です。この場合、関数 HasPrefix(str, prefix) と strings.HasSuffix(str, prefix) を使用するとよいでしょう。使用方法は以下で確認できます。

package main
import (
    "fmt"
    "strings"
)
func main() {
    fmt.Println(strings.HasPrefix("something", "some"))
    fmt.Println(strings.HasSuffix("something", "thing"))
}

虽然 strings 包中有大量有用的公共函数,但值得注意的是,并不总是值得去寻找一个能满足您需要的包。如果你有其他语言经验正在学习 Go 语言,一个常见的错误是开发者花太多时间寻找能够提供所需功能的包,而他们自己可轻易地编码实现这功能。

使用标准库肯定有好处(如它们经过了彻底的测试并有很好的文档记录)。尽管有这些好处,但如果你发现自己花了超过几分钟的时间来寻找一个函数,那么自己编写它通常也是有益的。在这种情况下,根据需求自定义(编码),将很快完成,你将完全了解正在发生的事情,不会被奇怪的边界情况(译者注如索引越界)措手不及。您也不必担心其他人维护代码。

6. 字符串可以被转换成 byte 切片 (反之亦然)

Go 语言可以将一个字符串转换成 byte 切片 ([]byte) ,也可以将 byte 切片转换成字符串。转换的过程跟其他任意类型转换的方式一样简单。这种转换方式通常用于为一个接收 byte 切片参数的函数传递一个字符串 以及 为一个接收字符串参数的函数传递 byte 切片的场景。

下面是一个转换的例子:

package main
import "fmt"
func main() {
    var s string = "this is a string"
    fmt.Println(s)
    var b []byte
    b = []byte(s)
    fmt.Println(b)
    for i := range b {
        fmt.Println(string(b[i]))
    }
    s = string(b)
    fmt.Println(s)
}

以上就是 Go 语言字符串使用过程中的一些小技巧,希望能帮到你。如果你需要更多 Go 相关的实践,可以查阅我发表的其他相关教程。

推荐教程:《Go教程

以上がGo 文字列処理の一般的なヒントの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlearnku.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。