How can I convert string to integer in golang
Asked Answered
J

9

21

I want to convert string to integer in golang. But I don't know the format of string. For example, "10" -> 10, "65.0" -> 65, "xx" -> 0, "11xx" -> 11, "xx11"->0

I do some searching and find strconv.ParseInt(). But it can not handle "65.0". So I have to check string's format.

Is there a better way?

Judie answered 18/7, 2015 at 4:8 Comment(6)
"65.0" is a float, not an int.Euphorbia
See https://mcmap.net/q/56306/-formatfloat-convert-float-number-to-string-duplicate/6309Pomiferous
Why not parse as a float and convert to string? or try first an int, fall back to parsing a float, etc?Fuddle
This can not solve "11xx"->11.Judie
#31488194Genic
strconv.Atoi("10") to convert a string to integer. strconv.Itoa(10) to convert an integer to a string. See https://mcmap.net/q/55268/-how-can-i-convert-string-to-integer-in-golang.Heelandtoe
E
11

I believe function you are looking for is

strconv.ParseFloat()

see example here

But return type of this function is float64.

If you don't need fractional part of the number passed as the string following function would do the job:

func StrToInt(str string) (int, error) {
    nonFractionalPart := strings.Split(str, ".")
    return strconv.Atoi(nonFractionalPart[0])
}
Endrin answered 18/7, 2015 at 8:49 Comment(3)
This solution can not deal with "11xx" -> 11 and "xx11"->0Judie
That is correct. From the question it is not clear that you need to handle cases like "11xx" -> 11 and i don't think it is good practice to parse integer and leave other character.Endrin
Yes, I do not make my question clear. I will update it. Thanks!Judie
U
11

You can use these three functions to convert a string value to an integer or a float.

Note: the strconv builtin package must be imported to execute these functions.

  1. func Atoi(s string) (int, error)
  2. func ParseInt(s string, base int, bitSize int) (i int64, err error)
  3. func ParseFloat(s string, bitSize int) (float64, error)
package main

import (
    "fmt"
    "strconv"
)

func main() {
    i, _ := strconv.Atoi("-42")
    fmt.Println(i)

    j,_ := strconv.ParseInt("-42", 10, 8)
    fmt.Println(j)

    k,_ := strconv.ParseFloat("-42.8", 8)
    fmt.Println(k)
}
Urbana answered 9/2, 2021 at 12:53 Comment(0)
Q
5
package main

import "strconv"
import "fmt"

// The built-in package "strconv" provides the number parsing.

// For `ParseInt`, the `0` means infer the base from
// the string. `64` requires that the result fit in 64
// bits.


value, err := strconv.ParseInt("123", 0, 64)
if err != nil {
    panic(err)
}
fmt.Println(value)

For reference, Click Here

You can also pass a non-zero base (like 10) if you always want the same thing.

Quartzite answered 3/9, 2018 at 13:36 Comment(0)
B
2

I want to convert string to integer in golang.

As you've already mentioned, there is a strconv.ParseInt function that does exactly this!

But I don't know the format of string.

That sounds scary (and challenging), but after looking at your examples I can easily conclude you know the format and the problem can be stated like this:

How can I parse an initial portion of a string as an integer?

As strconv.ParseInt returns 0 on syntax error it's not a good fit; well, at least not a good fit directly. But it can parse your initial portion if you extract it. I'm sure you've already figured it out, but this is really the cleanest solution: extract your content from the string, parse it.

You can extract the leading integer in a few ways, one of them is by using regexp:

package main

import (
    "fmt"
    "regexp"
    "strconv"
)

// Extract what you need
var leadingInt = regexp.MustCompile(`^[-+]?\d+`)

func ParseLeadingInt(s string) (int64, error) {
    s = leadingInt.FindString(s)
    if s == "" { // add this if you don't want error on "xx" etc
        return 0, nil
    }
    return strconv.ParseInt(s, 10, 64)
}

func main() {
    for _, s := range []string{"10", "65.0", "xx", "11xx", "xx11"} {
        i, err := ParseLeadingInt(s)
        fmt.Printf("%s\t%d\t%v\n", s, i, err)
    }
}

http://play.golang.org/p/d7sS5_WpLj

I believe this code is simple and clearly demonstrates the intentions. You're also using standard ParseInt which works and gives you all the error checking you need.

If for any reason you can't afford extracting the leading integer (you need it blazing fast parsing terabytes of data and your boss is screaming at you they need it now now now and better yesterday so bend the time and deliver it :hiss:) than I suggest diving into the source code and amending the standard parser so it doesn't report syntax errors, but returns a parsed portion of the string.

Bursary answered 19/7, 2015 at 19:38 Comment(0)
H
2

To add to the excellent answer by @MayankPatel and by @DeepakG. A string can be set to various numeric types. Various numeric types can be set to a string. Likewise, "true" can be set to a bool and true can be set to a string.

package main

import (
    "fmt"
    "strconv"
)

func main() {
    //convert a string to another type
    f, _ := strconv.ParseFloat("70.99", 64)
    i, _ := strconv.Atoi(fmt.Sprintf("%.f", f))
    t, _ := strconv.ParseBool("true")
    c := []interface{}{[]byte("70.99"), f, i, rune(i), t}
    checkType(c) //[]uint8 [55 48 46 57 57], float64 70.99, int 71, int32 71, bool true

    //convert another type to a string
    c = []interface{}{fmt.Sprintf("%s", []byte("70.99")), fmt.Sprintf("%.f", f), strconv.Itoa(i), string(rune(i)), strconv.FormatBool(t)}
    checkType(c) //string 70.99, string 71, string 71, string G, string true
}

func checkType(s []interface{}) {
    for k, _ := range s {
        fmt.Printf("%T %v\n", s[k], s[k])
    }
}

A string type represents the set of string values. A string value is a (possibly empty) sequence of bytes. The number of bytes is called the length of the string and is never negative. Strings are immutable. See https://Golang.org/ref/spec#String_types.

Here are three ways to parse strings into integers, from fastest runtime to slowest: 1. strconv.ParseInt(...) fastest 2. strconv.Atoi(...) still very fast 3. fmt.Sscanf(...) not terribly fast but most flexible. See https://mcmap.net/q/56307/-convert-string-to-integer-type-in-go.

Avoid converting a string to []byte: b := []byte(s). It allocates a new memory space and copies the whole content into it. See https://mcmap.net/q/56308/-how-to-decode-json-with-type-convert-from-string-to-float64. See https://mcmap.net/q/56309/-how-to-convert-utf8-string-to-byte. Quotes edited.

Heelandtoe answered 5/7, 2020 at 12:37 Comment(1)
C
1

You can write a FieldsFunc to parse and get the number values alone separately.

Play it here

package main

import (
    "fmt"
    "strconv"
    "strings"
    "unicode"
)

func stripNonIntFloat(s string) string {
    f := func(c rune) bool {
        return !unicode.IsNumber(c) && (c != 46)
    }
    output := strings.FieldsFunc(s, f)
    if len(output) > 0 {
        return output[0]
    } else {
        return ""
    }
}

func main() {
    strList := []string{"10", "65.0", "xx", "11xx", "xx11"}
    for i := 0; i < len(strList); i++ {
        s := stripNonIntFloat(strList[i])
        v, err := strconv.ParseFloat(s, 10)
        if err != nil {
            fmt.Println(strList[i], 0)
        } else {
            fmt.Println(strList[i], v)
        }
    }
}

The output here is

10 10
65.0 65
xx 0
11xx 11
xx11 11

Note that your last condition of xx11 handles it as 11.

Chamberlain answered 19/7, 2015 at 16:55 Comment(0)
B
1

Extracting an int from the start of a string is one of the most common things I do. In C you can use atoi() or strtol(). It's ridiculous that Go does not have a std library function to do it. Anyway here is one I just rolled up:

// strToInt gets the integer from the start of the string.
// It returns the value and the offset of the first non-digit.
func StrToInt(s string) (v int, offset int) {
    offset = strings.IndexFunc(s, func(r rune) bool { return r < '0' || r > '9' })
    if offset == -1 { offset = len(s) }
    if offset == 0 { return }   // Avoid Atoi on empty string
    v, _ = strconv.Atoi(s[:offset])
    return
}

You'll need a slight fix if you want to handle -ve integers.

Bureaucrat answered 21/8, 2017 at 4:24 Comment(1)
As well a checking for a leading minus sign you might first want to skip leading whitespace, for completeness. I leave this as an exercise.Bureaucrat
J
0

My current solution is:

// Convert string to integer in best effort.                                                                                
 // TODO: handle overflow and add unittest                                                                                   
func StrToInt(str string) (int64, error) {                                                                                  
    if len(str) == 0 {                                                                                                      
        return 0, nil                                                                                                       
     }                                                                                                                       
     negative := false                                                                                                       
     i := 0                                                                                                                  
     if str[i] == '-' {                                                                                                      
         negative = true                                                                                                     
         i++                                                                                                                 
     } else if str[i] == '+' {                                                                                               
         i++                                                                                                                 
     }                                                                                                                       
     r := int64(0)                                                                                                           
     for ; i < len(str); i++ {                                                                                             
         if unicode.IsDigit(rune(str[i])) {                                                                                  
             r = r*10 + int64(str[i]-'0')                                                                                    
         } else {
             break
          }                                                                                                                   
     }                                                                                                                       
     if negative {                                                                                                           
         r = -r                                                                                                              
     }                                                                                                                       
     // TODO: if i < len(str), we should return error                                                                        
     return r, nil                                                                                                           
 }    
Judie answered 18/7, 2015 at 11:0 Comment(2)
You're looping over str by byte but comparing as runes. I'd just use for _, r := range str[i:] to loop over the string by rune (or don't bother with unicode and just test against ASCII 0 and 9 literals).Crusade
IMO, if you want an API that will stop parsing early and ignore trailing characters you should have the API return either the number of bytes consumed/parsed or the remaining unparsed portion of the input (in addition to the existing return values of course).Crusade
M
0
import (
  "strconv"
  "strings"
)

func StrToInt(str string) int {
  // Delete any non-numeric character from the string
  str = strings.TrimFunc(str, func(r rune) bool {
      return r < '0' || r > '9'
  })

  // Convert the cleaned-up string to an integer
  n, _ := strconv.Atoi(str)
  return n
}
Megaspore answered 8/3, 2023 at 19:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.