web-dev-qa-db-ja.com

Goで文字列を整数型に変換しますか?

flag.Arg(n)から返された文字列をintに変換しようとしています。 Goでこれを行う慣用的な方法は何ですか?

202
Matt Joiner

例えば、

package main

import (
    "flag"
    "fmt"
    "os"
    "strconv"
)

func main() {
    flag.Parse()
    s := flag.Arg(0)
    // string to int
    i, err := strconv.Atoi(s)
    if err != nil {
        // handle error
        fmt.Println(err)
        os.Exit(2)
    }
    fmt.Println(s, i)
}
250
peterSO

単純な文字列の変換

最も簡単な方法は、 strconv.Atoi() 関数を使用することです。

他にも多くの方法があることに注意してください。たとえば、 fmt.Sscan() および strconv.ParseInt() は、たとえばベースとビットサイズを指定できるため、柔軟性が向上します。また、strconv.Atoi()のドキュメントに記載されているとおり:

AtoiはParseInt(s、10、0)の省略形です。

上記の関数を使用した例を次に示します( Go Playground で試してください):

flag.Parse()
s := flag.Arg(0)

if i, err := strconv.Atoi(s); err == nil {
    fmt.Printf("i=%d, type: %T\n", i, i)
}

if i, err := strconv.ParseInt(s, 10, 64); err == nil {
    fmt.Printf("i=%d, type: %T\n", i, i)
}

var i int
if _, err := fmt.Sscan(s, &i); err == nil {
    fmt.Printf("i=%d, type: %T\n", i, i)
}

出力(引数"123"で呼び出された場合):

i=123, type: int
i=123, type: int64
i=123, type: int

カスタム文字列の解析

また、便利な fmt.Sscanf() があります。これは、入力文字列stringに追加の追加文字とともに数値形式(幅、基数など)を指定できる形式文字列と同様に、さらに柔軟性を提供します。

これは、数値を保持するカスタム文字列の解析に最適です。たとえば、入力が"id:00123"の形式で提供され、プレフィックス"id:"があり、数字が5桁に固定され、短い場合はゼロが埋め込まれる場合、これは次のように非常に簡単に解析できます。

s := "id:00123"

var i int
if _, err := fmt.Sscanf(s, "id:%5d", &i); err == nil {
    fmt.Println(i) // Outputs 123
}
50
icza

文字列を整数に解析する3つの方法を以下に示します。実行速度が最も速いものから最も遅いものまでです。

  1. strconv.ParseInt(...) 最速
  2. strconv.Atoi(...) まだ非常に高速
  3. fmt.Sscanf(...) それほど高速ではありませんが、最も柔軟です

以下に、各機能の使用方法とタイミングの例を示すベンチマークを示します。

package main

import "fmt"
import "strconv"
import "testing"

var num = 123456
var numstr = "123456"

func BenchmarkStrconvParseInt(b *testing.B) {
  num64 := int64(num)
  for i := 0; i < b.N; i++ {
    x, err := strconv.ParseInt(numstr, 10, 64)
    if x != num64 || err != nil {
      b.Error(err)
    }
  }
}

func BenchmarkAtoi(b *testing.B) {
  for i := 0; i < b.N; i++ {
    x, err := strconv.Atoi(numstr)
    if x != num || err != nil {
      b.Error(err)
    }
  }
}

func BenchmarkFmtSscan(b *testing.B) {
  for i := 0; i < b.N; i++ {
    var x int
    n, err := fmt.Sscanf(numstr, "%d", &x)
    if n != 1 || x != num || err != nil {
      b.Error(err)
    }
  }
}

atoi_test.goとして保存し、go test -bench=. atoi_test.goを実行することで実行できます。

goos: darwin
goarch: AMD64
BenchmarkStrconvParseInt-8      100000000           17.1 ns/op
BenchmarkAtoi-8                 100000000           19.4 ns/op
BenchmarkFmtSscan-8               2000000          693   ns/op
PASS
ok      command-line-arguments  5.797s
15
maerics

これを試して

import ("strconv")

value : = "123"
number,err := strconv.ParseUint(value, 10, 32)
0
MD.Mahedi hasan

入力データを制御する場合、ミニバージョンを使用できます

package main

import (
    "testing"
    "strconv"
)

func Atoi (s string) int {
    var (
        n uint64
        i int
        v byte
    )   
    for ; i < len(s); i++ {
        d := s[i]
        if '0' <= d && d <= '9' {
            v = d - '0'
        } else if 'a' <= d && d <= 'z' {
            v = d - 'a' + 10
        } else if 'A' <= d && d <= 'Z' {
            v = d - 'A' + 10
        } else {
            n = 0; break        
        }
        n *= uint64(10) 
        n += uint64(v)
    }
    return int(n)
}

func BenchmarkAtoi(b *testing.B) {
    for i := 0; i < b.N; i++ {
        in := Atoi("9999")
        _ = in
    }   
}

func BenchmarkStrconvAtoi(b *testing.B) {
    for i := 0; i < b.N; i++ {
        in, _ := strconv.Atoi("9999")
        _ = in
    }   
}

最速のオプション(必要に応じてチェックを書いてください)。結果:

Path>go test -bench=. atoi_test.go
goos: windows
goarch: AMD64
BenchmarkAtoi-2                 100000000               14.6 ns/op
BenchmarkStrconvAtoi-2          30000000                51.2 ns/op
PASS
ok      path     3.293s
0
Jenyokcoder