Convert string to int in GO - go

I am trying to convert a number into a slice of its digit in Go. My code is like this
stn := strconv.Itoa(2342)
starr := make([]int,0)
for i3,_ := range stn {
temp,_ := strconv.Atoi(stn[i3])
starr = append(starr,temp )
}
fmt.Println(starr)
The error is: "cannot use stn[i3] (type byte) as type string in argument to strconv.Atoi". I am used to Python so I try to follow the idea from Python but it does not seem to work. Reall appreciate any help

Answering the question behind the question, here's how you might convert an int into a slice of digits in go instead of using string conversions.
func digitSlice(input int) []int {
output := []int{}
for input > 0 {
output = append([]int{input % 10}, output...)
input = input / 10
}
return output
}
https://play.golang.org/p/tCLISl7Djah

Related

How do I parse a currency value as *big.Int in Go?

I want to parse a string like "12.49" into a *big.Int in Go. The resulting *big.Int should represent the amount of cents in the given value, in this case 1249. Here are some more examples of inputs and their expected outputs:
"3": 300
"3.1": 310
".19": 19
I already tried working with *big.Float and its Int function, but realized, that *big.Float does not provide arbitrary precision.
Right now I'm using this algorithm, but it seems fragile (Go Playground link):
func eurToCents(in string) *big.Int {
missingZerosUntilCents := 2
i := strings.Index(in, ".")
if i > -1 {
missingZerosUntilCents -= len(in) - i - 1
if missingZerosUntilCents < 0 {
panic("too many decimal places")
}
}
in = strings.Replace(in, ".", "", 1)
in += strings.Repeat("0", missingZerosUntilCents)
out, ok := big.NewInt(0).SetString(in, 10)
if !ok {
panic(fmt.Sprintf("could not parse '%s' as an interger", in))
}
return out
}
Is there a standard library function or other common way to parse currencies in Go? An external library is not an option.
PS: I'm parsing Nano cryptocurrency values, which have 30 decimal places and a maximum value of 133,248,297.0. That's why I'm asking for *big.Int and not uint64.
Update: Seems like this solution is still buggy, because an inaccurate result is reported after multiplication: https://play.golang.org/p/RS-DC6SeRwz
After revisiting the solution with *big.Float, I realized, that it does work perfectly fine. I think I forgot to use SetPrec on rawPerNano previously. I'm going to provide an example for the Nano cryptocurrency, because it requires many decimal places.
This works as expected (Go Playground link):
func nanoToRaw(in string) *big.Int {
f, _ := big.NewFloat(0).SetPrec(128).SetString(in)
rawPerNano, _ := big.NewFloat(0).SetPrec(128).SetString("1000000000000000000000000000000")
f.Mul(f, rawPerNano)
i, _ := f.Int(big.NewInt(0))
return i
}
Thanks #hymns-for-disco for nudging me in the right direction!

What exactly is this "cast" doing in Golang?

Can someone point me in the right direction of this Go's syntax :
(*int)(nil)
If I have a a value of a given type and I want to convert it to, lets say, float64 I can do this :
var num int = 65
fnum := float64(num)
If I have an interface and I want to "cast it" to some type I can do this :
func main() {
concretevalue := dosomething("hello!")
fmt.Printf("%T : %v", concretevalue, concretevalue)
}
func dosomething( v interface{} ) string {
return v.(string)
}
Where does the (*int)(nil) fit? How can I get information about this specific syntax?
It is a type-conversion, same as float64(num), however, because the converted type is a pointer, you need extra parentheses, because otherwise *int(nil) would mean converting nil to int, and then dereferencing it.

Writing a struct's fields and values of different types to a file in Go

I'm writing a simple program that takes in input from a form, populates an instance of a struct with the received data and the writes this received data to a file.
I'm a bit stuck at the moment with figuring out the best way to iterate over the populated struct and write its contents to the file.
The struct in question contains 3 different types of fields (ints, strings, []strings).
I can iterate over them but I am unable to get their actual type.
Inspecting my posted code below with print statements reveals that each of their types is coming back as structs rather than the aforementioned string, int etc.
The desired output format is be plain text.
For example:
field_1="value_1"
field_2=10
field_3=["a", "b", "c"]
Anyone have any ideas? Perhaps I'm going about this the wrong way entirely?
func (c *Config) writeConfigToFile(file *os.File) {
listVal := reflect.ValueOf(c)
element := listVal.Elem()
for i := 0; i < element.NumField(); i++ {
field := element.Field(i)
myType := reflect.TypeOf(field)
if myType.Kind() == reflect.Int {
file.Write(field.Bytes())
} else {
file.WriteString(field.String())
}
}
}
Instead of using the Bytes method on reflect.Value which does not work as you initially intended, you can use either the strconv package or the fmt to format you fields.
Here's an example using fmt:
var s string
switch fi.Kind() {
case reflect.String:
s = fmt.Sprintf("%q", fi.String())
case reflect.Int:
s = fmt.Sprintf("%d", fi.Int())
case reflect.Slice:
if fi.Type().Elem().Kind() != reflect.String {
continue
}
s = "["
for j := 0; j < fi.Len(); j++ {
s = fmt.Sprintf("%s%q, ", s, fi.Index(i).String())
}
s = strings.TrimRight(s, ", ") + "]"
default:
continue
}
sf := rv.Type().Field(i)
if _, err := fmt.Fprintf(file, "%s=%s\n", sf.Name, s); err!= nil {
panic(err)
}
Playground: https://play.golang.org/p/KQF3CicVzA
Why not use the built-in gob package to store your struct values?
I use it to store different structures, one per line, in files. During decoding, you can test the type conversion or provide a hint in a wrapper - whichever is faster for your given use case.
You'd treat each line as a buffer when Encoding and Decoding when reading back the line. You can even gzip/zlib/compress, encrypt/decrypt, etc the stream in real-time.
No point in re-inventing the wheel when you have a polished and armorall'd wheel already at your disposal.

Slice unicode/ascii strings in golang?

I need to slice a string in Go. Possible values can contain Latin chars and/or Arabic/Chinese chars. In the following example, the slice annotation [:1] for the Arabic string alphabet is returning a non-expected value/character.
package main
import "fmt"
func main() {
a := "a"
fmt.Println(a[:1]) // works
b := "ذ"
fmt.Println(b[:1]) // does not work
fmt.Println(b[:2]) // works
fmt.Println(len(a) == len(b)) // false
}
http://play.golang.org/p/R-JxaxbfNL
First of all, you should really read about strings, bytes and runes in Go.
And here is how you can achieve what you want: Go playground (I was not able to properly paste arabic symbols, but if Chinese works, arabic should work too).
s := "abcdefghijklmnop"
fmt.Println(s[2:9])
s = "维基百科:关于中文维基百科"
fmt.Println(string([]rune(s)[2:9]))
The output is:
cdefghi
百科:关于中文
You can use the utf8string package:
package main
import "golang.org/x/exp/utf8string"
func main() {
a := utf8string.NewString("🎈🎄🎀🎢👓")
// example 1
r := a.At(1)
// example 2
s := a.Slice(1, 3)
// example 3
n := a.RuneCount()
// print
println(r == '🎄', s == "🎄🎀", n == 5)
}
https://pkg.go.dev/golang.org/x/exp/utf8string

Looking for an elegant way to parse an Integer [duplicate]

This question already has answers here:
Convert string to integer type in Go?
(5 answers)
Closed 8 months ago.
Right now I am doing the following in order to parse an integer from a string and then convert it to int type:
tmpValue, _ := strconv.ParseInt(str, 10, 64) //returns int64
finalValue = int(tmpValue)
It is quite verbose, and definitely not pretty, since I haven't found a way to do the conversion in the ParseInt call. Is there a nicer way to do that?
It seems that the function strconv.Atoi does what you want, except that it works regardless of the bit size of int (your code seems to assume it's 64 bits wide).
If you have to write that once in your program than I see no problem. If you need at several places you can write a simple specialization wrapper, for example:
func parseInt(s string) (int, error) {
i, err := strconv.ParseInt(str, 10, 32) // or 64 on 64bit tip
return int(i), err
}
The standard library doesn't aim to supply (bloated) APIs for every possible numeric type and/or their combinations.
Don't forget to check for errors. For example,
package main
import (
"fmt"
"strconv"
)
func main() {
s := "123"
i, err := strconv.Atoi(s)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(i)
}
Output:
123

Resources