Chuyển đổi chuỗi thành kiểu số nguyên trong Go?


236

Tôi đang cố gắng chuyển đổi một chuỗi được trả về từ flag.Arg(n)một int. Cách thành ngữ để làm điều này trong Go là gì?

Câu trả lời:


298

Ví dụ,

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() { ... }không có đối số và trả về không có giá trị. Sử dụng các osgói Exitchức năng ví dụos.Exit(2).
peterSO

2
Hoặc chỉ cần làm một ví dụ chết ngườipanic(err)
Peter Bengtsson

70

Chuyển đổi chuỗi đơn giản

Cách dễ nhất là sử dụng strconv.Atoi()chức năng.

Lưu ý rằng có nhiều cách khác. Ví dụ fmt.Sscan()strconv.ParseInt()cung cấp tính linh hoạt cao hơn khi bạn có thể chỉ định cơ sở và bitize chẳng hạn. Cũng như ghi chú trong tài liệu của strconv.Atoi():

Atoi tương đương với ParseInt (s, 10, 0), được chuyển đổi thành kiểu int.

Dưới đây là một ví dụ sử dụng các chức năng được đề cập (thử trên Sân chơi Go ):

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

Đầu ra (nếu được gọi với đối số "123"):

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

Phân tích chuỗi tùy chỉnh

Ngoài ra còn có một tiện ích fmt.Sscanf()mang lại sự linh hoạt hơn nữa như với chuỗi định dạng, bạn có thể chỉ định định dạng số (như chiều rộng, cơ sở, v.v.) cùng với các ký tự bổ sung bổ sung trong đầu vào string.

Điều này là tuyệt vời để phân tích chuỗi tùy chỉnh giữ một số. Ví dụ: nếu đầu vào của bạn được cung cấp ở dạng "id:00123"bạn có tiền tố "id:"và số được cố định 5 chữ số, được đệm bằng số không nếu ngắn hơn, thì điều này rất dễ phân tích như thế này:

s := "id:00123"

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

Đối số thứ hai để ParseIntxác định là gì?
kaushik94

1
@ kaushik94 Nhấp vào strconv.ParseInt()liên kết và bạn sẽ thấy ngay lập tức : ParseInt(s string, base int, bitSize int). Vì vậy, đó là cơ sở: "ParseInt diễn giải một chuỗi s trong cơ sở đã cho (2 đến 36)"
icza

Lưu ý rằng đối số bitSize thành strconv.PudeInt () sẽ không chuyển đổi chuỗi thành loại bạn chọn mà thay vào đó chỉ ở đó để giới hạn kết quả thành 'bitness' cụ thể. Xem thêm: stackoverflow.com/questions/55925894/ Cách
viv

@viv Vâng, đúng rồi. Nếu giá trị của loại intđược yêu cầu và strconv.ParseInt()được sử dụng, chuyển đổi loại thủ công là cần thiết (từ int64đến int).
icza

16

Dưới đây là ba cách để phân tích chuỗi thành số nguyên, từ thời gian chạy nhanh nhất đến chậm nhất:

  1. strconv.ParseInt(...) nhanh nhất
  2. strconv.Atoi(...) vẫn rất nhanh
  3. fmt.Sscanf(...) không quá nhanh nhưng linh hoạt nhất

Đây là một điểm chuẩn cho thấy thời gian sử dụng và ví dụ cho từng chức năng:

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

Bạn có thể chạy nó bằng cách lưu atoi_test.govà chạy 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

Thử cái này

import ("strconv")

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

0

Nếu bạn kiểm soát dữ liệu đầu vào, bạn có thể sử dụng phiên bản 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
    }   
}

tùy chọn nhanh nhất (viết séc của bạn nếu cần thiết). Kết quả :

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
Gì ? Có thật không ? Những người đã viết "đi" thực hiện rất dễ dàng. Đừng quay bánh xe của bạn :)
Balaji Boggaram Ramanarayan

Còn Atoi ("- 9999") thì sao?
Oleksiy Chechel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.