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


回答:


298

例えば、

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)
}

14
func main() { ... }引数を取らず、値を返しません。osパッケージExit関数を使用します。例os.Exit(2).
peterSO 2010年

2
あるいは、致命的な例を実行してくださいpanic(err)
Peter Bengtsson 2014年

70

単純な文字列の変換

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

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

AtoiはParseInt(s、10、0)と同じで、int型に変換されます。

上記の関数を使用した例を次に示します(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
}

ParseInt指定する2番目の引数は何ですか?
kaushik94 2016年

1
@ kaushik94 strconv.ParseInt()リンクをクリックすると、すぐに表示されますParseInt(s string, base int, bitSize int)。したがって、これがベースです。「ParseIntは指定されたベース(
2〜36

strconv.ParseInt()のbitSize引数は、文字列をユーザーが選択したタイプに変換せず、結果を特定の「ビット数」に制限するためだけに存在することに注意してください。参照:stackoverflow.com/questions/55925894/...
VIV

@vivはい、そうです。タイプの値があればint必要とされ、strconv.ParseInt()使用されて、手動型変換は、(から必要とされるint64までint)。
icza

16

以下は、文字列を整数に解析する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


0

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

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

1
何 ?本当に ?「go」を書いた人はとても簡単になりました。ホイールを回転させないでください:)
Balaji Boggaram Ramanarayan '30

あとい( "-9999")は?
Oleksiy Chechel
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.