Konversi string ke tipe integer di Go?


236

Saya mencoba mengonversi string yang dikembalikan dari flag.Arg(n)ke int. Apa cara idiomatis untuk melakukan ini di Go?

Jawaban:


298

Sebagai contoh,

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() { ... }tidak mengambil argumen dan tidak mengembalikan nilai. Gunakan fungsi ospaket Exitmis.os.Exit(2).
peterSO

2
Atau hanya melakukan Eg fatalpanic(err)
Peter Bengtsson

70

Mengubah string sederhana

Cara termudah adalah menggunakan strconv.Atoi()fungsinya.

Perhatikan bahwa ada banyak cara lain. Misalnya fmt.Sscan()dan strconv.ParseInt()yang memberikan fleksibilitas lebih besar karena Anda dapat menentukan basis dan bitsize misalnya. Juga seperti yang tercantum dalam dokumentasi strconv.Atoi():

Atoi setara dengan ParseInt (s, 10, 0), dikonversi menjadi tipe int.

Berikut ini contoh menggunakan fungsi yang disebutkan (coba di 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)
}

Output (jika dipanggil dengan argumen "123"):

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

Parsing string Kustom

Ada juga yang berguna fmt.Sscanf()yang memberikan fleksibilitas lebih besar karena dengan string format Anda dapat menentukan format angka (seperti lebar, basis dll) bersama dengan karakter tambahan tambahan dalam input string.

Ini bagus untuk parsing string kustom yang memegang nomor. Misalnya, jika input Anda diberikan dalam bentuk di "id:00123"mana Anda memiliki awalan "id:"dan jumlahnya ditetapkan 5 digit, diisi dengan nol jika lebih pendek, ini sangat mudah diurai seperti ini:

s := "id:00123"

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

Apa yang ParseIntditentukan argumen kedua ?
kaushik94

1
@ kaushik94 Klik pada strconv.ParseInt()link di dan Anda akan melihat langsung: ParseInt(s string, base int, bitSize int). Jadi itulah dasarnya: "ParseInt menginterpretasikan sebuah string dalam basis yang diberikan (2 hingga 36)"
icza

Perhatikan bahwa argumen bitSize ke strconv.ParseInt () tidak akan mengonversi string ke tipe pilihan Anda, tetapi hanya ada di sana untuk membatasi hasilnya ke 'bitness' tertentu. Lihat juga: stackoverflow.com/questions/55925894/…
viv

@viv Ya, itu benar. Jika nilai tipe intdiperlukan dan strconv.ParseInt()digunakan, konversi tipe manual diperlukan (dari int64menjadi int).
icza

16

Berikut adalah tiga cara untuk mengurai string menjadi bilangan bulat, dari runtime tercepat ke yang paling lambat:

  1. strconv.ParseInt(...) tercepat
  2. strconv.Atoi(...) masih sangat cepat
  3. fmt.Sscanf(...) tidak terlalu cepat tetapi paling fleksibel

Berikut ini adalah tolok ukur yang menunjukkan waktu penggunaan dan contoh untuk setiap fungsi:

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

Anda dapat menjalankannya dengan menyimpan sebagai atoi_test.godan menjalankan 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

2

Coba ini

import ("strconv")

value : = "123"
number,err := strconv.ParseUint(value, 10, 32)

0

Jika Anda mengontrol data input, Anda dapat menggunakan versi mini

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

opsi tercepat (tulis cek Anda jika perlu). Hasil:

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
Apa ? Betulkah ? Orang yang menulis "pergi" menjadi sangat mudah. Jangan memutar roda Anda :)
Balaji Boggaram Ramanarayan

Bagaimana dengan Atoi ("- 9999")?
Oleksiy Chechel
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.