Issue with parsing Go Command().Output() - go

I am using a third party tool in Go with the help of exec.Command and that program will print out a large integer value which obviously is in string format. I having trouble converting that string to int (or more specifically uint64).
Details:
(You can ignore what program it is etc. but after running it will return me a large integer)
cmd := exec.Command(app, arg0, arg1, arg3)
stdout, err := cmd.Output()
if err != nil {
fmt.Println(err.Error())
return
}
temp := string(stdout)
After I ran above, I am trying to parse it as below
myanswer, err = strconv.Atoi(temp) //I know this is not for uint64 but I am first trying for int but I actually need uint64 conversion
if err != nil {
fmt.Println(err)
return
}
Problem here is that the stdout is appending \r\n to its output which AtoI is not able to parse and gives the error
strconv.Atoi: parsing "8101832828\r\n": invalid syntax
Can someone pls help me on how to convert this string output to a uint64 and also int format pls?

The output contains special characters. First, you need to strip any these characters (e.g. \n or \r).
You can use strings.TrimSpace.
Then to parse a string as an int64, you would use:
if i, err := strconv.ParseInt(s, 10, 64); err == nil {
fmt.Printf("i=%d, type: %T\n", i, i)
}

Related

Golang: statically finding all strings in code

I would like to parse a package and output all of the strings in the code. The specific use case is to collect sql strings and run them through a sql parser, but that's a separate issue.
Is the best way to do this to just parse this line by line? Or is it possible to regex this or something? I imagine that some cases might be nontrivial, such as multiline strings:
str := "This is
the full
string"
// want > This is the full string
Use the go/scanner package to scan for strings in Go source code:
src, err := os.ReadFile(fname)
if err != nil {
/// handle error
}
// Create *token.File to scan.
fset := token.NewFileSet()
file := fset.AddFile(fname, fset.Base(), len(src))
var s scanner.Scanner
s.Init(file, src, nil, 0)
for {
pos, tok, lit := s.Scan()
if tok == token.EOF {
break
}
if tok == token.STRING {
s, _ := strconv.Unquote(lit)
fmt.Printf("%s: %s\n", fset.Position(pos), s)
}
}
https://go.dev/play/p/849QsbqVhho

Multiple unicode like '\u7cfb' with normal string mixed, how to convert to normal text

a:="\u5206\u7ec4\u6570\u4e0d\u80fd\u5927\u4e8e20\u4e2a"
fmt.Println(a) // output: 分组数不能大于20个
this is a segment of http reponse, I wan to write it to log, in the log it should be "分组数不能大于20个" not "\u5206\u7ec4\u6570\u4e0d\u80fd\u5927\u4e8e20\u4e2a"
pay attention to "\u4e8e20"
"\u4e8e" is chinese character "于",
"20" is just the literal number.
how to convert variable a to the output like fmt.Println(a)?
not just print it out
I found some snippt but encount error with "\u4e8e20", output "分组数不能大于⁎⁎"
func u2s(form string) (to string, err error) {
bs, err := hex.DecodeString(strings.Replace(form, `\u`, ``, -1))
if err != nil {
return
}
for i, bl, br, r := 0, len(bs), bytes.NewReader(bs), uint16(0); i < bl; i += 2 {
binary.Read(br, binary.BigEndian, &r)
to += string(r)
}
return
}
the http response is
{"code":"100001","msg":"\u5206\u7ec4\u6570\u4e0d\u80fd\u5927\u4e8e20\u4e2a","data":{}}
the solution is json.Unmarshal then json.Marshal, the "msg" field then human readable
and thank #Volker #Flimzy #kostix, your comment is very helpful

Does Golang have something like python's ast.literal_eval() for converting a string representation of a map into an actual map object?

I need to convert the string representation of a map object into an actual map object in Go. Python has this functionality via ast.literal_eval() and looking for something similar in Go.
I've checked out Go's ast lib https://golang.org/pkg/go/ast but I'm not finding similar functionality. Also a third party lib https://github.com/apaxa-go/eval that "appears" to support this via their example code in the readme (though not specific to maps):
src:="int8(1*(1+2))"
expr,err:=ParseString(src,"")
if err!=nil{
return err
}
r,err:=expr.EvalToInterface(nil)
if err!=nil{
return err
}
fmt.Printf("%v %T", r, r) // "3 int8"
But when attempting with a map:
myMap := "map[blah:1 stuff:2 list:3]"
expr, err := eval.ParseString(myMap, "")
if err != nil{
log.Fatal("%v", err)
}
log.Printf("%v %T", expr, expr)
result, err := expr.EvalToInterface(nil)
if err != nil{
log.Fatal("%v", err)
}
log.Printf("%v %T", result, result)
I get the following error message:
2019/10/27 18:38:27.242352 main.go:33: %vexpression:1:9: expected ']', found ':'
where line 33 is the expression:
expr, err := eval.ParseString(myMap, "")
I'm pretty new to Go so I might be approaching this from the wrong direction. Any help would be appreciated. The end goal is to take this string representation of a map and convert it to JSON.
The map representation in myMap is wrong. You should write it like this
map[string]int{"foo": 1, "bar": 2}

How to create a custom formatter with go 1.13 error?

With go 1.13, we can now wrap our error this way, fmt.Errorf("... %w ...", ..., err, ...) (https://golang.org/pkg/errors).
While this is great, there seems to be no way to create a custom formatter. Let say I want to have different spaces depending on the depth of the error, I'll get all of the errors in the tree if I just get the string representation of the error, err.Error().
Please see below for an example.
I've tried using fmt.Sprintf with %s and %v verbs, get the string representation from Error(), and fmt.Sprint.
// sprintError prints err in top-down order
func sprintError(err error) string {
var stack []string
level := 0
spacesPerLevel := 2
for err != nil {
space := strings.Repeat(" ", level*spacesPerLevel)
msg := fmt.Sprintf("%s%s", space, err)
stack = append(stack, msg)
err = errors.Unwrap(err)
level++
}
msg := strings.Join(stack, "\n")
return msg
}
Example:
err := fmt.Errorf("level 1")
err = fmt.Errorf("level 2: %w", err)
fmt.Print(sprintError(err))
Output:
level 2: level 1
level 1
Expected:
level 2:
level 1
[T]here seems to be no way to create a custom formatter
Exactly. That part of the original proposal did not make it into Go 1.13.
So you cannot do what you would like to do, at least not in an easy way.
You could try and strip of the unwrapped error string from the original
but this relies on string manipulation.

Check the number of dots present in string using golang

I have cmd prompt,In which stdin accept only string, but once i receive the string need to convert to float. when someone mistakenly enter "0..1" instead of 0.1, I need check it and show error info.
msg := "enter the rate eg:{0.1}"
rate, err := RatePrompt(msg)
if err != nil {
fmt.Println("something went while entering rate, please re-enter")
}
func RatePrompt(cmrmsg string) (price string, err error) {
fmt.Println(" ")
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
price := scanner.Text()
return price, nil
}
//check for string contains multiple dot
rate, err := RatePrompt(msg)
if err != nil {
fmt.Println("something went while entering
rate, please re-enter")else{
///check for string contains multiple dot
}
}
checking for multiple dot in string value, if multiple dot present throw error
If you are just checking for number use this instead of dot check
i, err := strconv.ParseFloat(elem, 64)
if err != nil {
numbers = append(numbers, i)
}

Resources