How to scan a big.Int from standard input in Go - go

Is there a way to scan a big.Int directly from the standard input in Go? Right now I'm doing this:
package main
import (
"fmt"
"math/big"
)
func main() {
w := new(big.Int)
var s string
fmt.Scan(&s)
fmt.Sscan(s, w)
fmt.Println(w)
}
I also could have used .SetString. But, is there a way to Scan the big.Int directly from the standard input without scanning a string or an integer first?

For example,
package main
import (
"fmt"
"math/big"
)
func main() {
w := new(big.Int)
n, err := fmt.Scan(w)
fmt.Println(n, err)
fmt.Println(w.String())
}
Input (stdin):
295147905179352825857
Output (stdout):
1 <nil>
295147905179352825857

As far as I know - no, there's no other way. In fact, what you've got is the default example they have for scanning big.Int in the documentation.
package main
import (
"fmt"
"log"
"math/big"
)
func main() {
// The Scan function is rarely used directly;
// the fmt package recognizes it as an implementation of fmt.Scanner.
i := new(big.Int)
_, err := fmt.Sscan("18446744073709551617", i)
if err != nil {
log.Println("error scanning value:", err)
} else {
fmt.Println(i)
}
}
You can see the relevant section here - http://golang.org/pkg/math/big/#Int.Scan

Related

Cannot use (type []byte) as type string in argument to strconv.ParseFloat issue

pi#raspberrypi:~/Desktop/go $ go run shell1.go
As result i am getting:
pi#raspberrypi:~/Desktop/go $ go run shell1.go
# command-line-arguments
./shell1.go:29: undefined: n
./shell1.go:29: cannot use b (type []byte) as type string in argument to strconv.ParseFloat
./shell1.go:32: undefined: n
Go file (shell1.go) code is:
package main
import (
// "net/http"
// "github.com/julienschmidt/httprouter"
"fmt"
"log"
"os/exec"
"strconv"
"time"
//"bytes"
//"encoding/binary"
)
import _ "github.com/go-sql-driver/mysql"
import _ "database/sql"
func main() {
for {
time.Sleep(10 * time.Millisecond)
cmd := exec.Command("gpio.bash")
b, err := cmd.Output()
if err != nil {
log.Fatal(err)
}
n, _ = strconv.ParseFloat(b, 10)
fmt.Println(string(b))
break
}
fmt.Println("Button pressed!!! ", n)
}
Content of (gpio.bash) file is just one command to read gpio
#!/bin/bash
gpio read 29
You are working with a command here, which can of course execute just about anything.
The function is purposely generic, as the true return type varies depending on what you executed. Thus, when you call the output method, you are given a slice of bytes (very generic!). Here is its signature:
func (c *Cmd) Output() ([]byte, error)
If you know that the bytes will always be a string, then you simply have to do a type conversion to a string:
n, _ := strconv.ParseFloat(string(b), 10)

Extract part of string in Golang?

I'm learning Golang so I can rewrite some of my shell scripts.
I have URL's that look like this:
https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value
I want to extract the following part:
https://example-1.example.com/a/c482dfad3573acff324c/list.txt
In a shell script I would do something like this:
echo "$myString" | grep -o 'http://.*.txt'
What is the best way to do the same thing in Golang, only by using the standard library?
There are a few options:
// match regexp as in question
pat := regexp.MustCompile(`https?://.*\.txt`)
s := pat.FindString(myString)
// everything before the query
s := strings.Split(myString, "?")[0] string
// same as previous, but avoids []string allocation
s := myString
if i := strings.IndexByte(s, '?'); i >= 0 {
s = s[:i]
}
// parse and clear query string
u, err := url.Parse(myString)
u.RawQuery = ""
s := u.String()
The last option is the best because it will handle all possible corner cases.
try it on the playground
you may use strings.IndexRune, strings.IndexByte, strings.Split, strings.SplitAfter, strings.FieldsFunc, url.Parse, regexp or your function.
first most simple way:
you may use i := strings.IndexRune(s, '?') or i := strings.IndexByte(s, '?') then s[:i] like this (with commented output):
package main
import "fmt"
import "strings"
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
i := strings.IndexByte(s, '?')
if i != -1 {
fmt.Println(s[:i]) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
}
or you may use url.Parse(s) (I'd use this):
package main
import "fmt"
import "net/url"
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
url, err := url.Parse(s)
if err == nil {
url.RawQuery = ""
fmt.Println(url.String()) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
}
or you may use regexp.MustCompile(".*\\.txt"):
package main
import "fmt"
import "regexp"
var rgx = regexp.MustCompile(`.*\.txt`)
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
fmt.Println(rgx.FindString(s)) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
or you may use splits := strings.FieldsFunc(s, func(r rune) bool { return r == '?' }) then splits[0]:
package main
import "fmt"
import "strings"
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
splits := strings.FieldsFunc(s, func(r rune) bool { return r == '?' })
fmt.Println(splits[0]) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
you may use splits := strings.Split(s, "?") then splits[0]:
package main
import "fmt"
import "strings"
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
splits := strings.Split(s, "?")
fmt.Println(splits[0]) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
you may use splits := strings.SplitAfter(s, ".txt") then splits[0]:
package main
import "fmt"
import "strings"
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
splits := strings.SplitAfter(s, ".txt")
fmt.Println(splits[0]) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
or you may use your function (most independent way):
package main
import "fmt"
func left(s string) string {
for i, r := range s {
if r == '?' {
return s[:i]
}
}
return ""
}
func main() {
s := `https://example-1.example.com/a/c482dfad3573acff324c/list.txt?parm1=value,parm2=value,parm3=https://example.com/a?parm1=value,parm2=value`
fmt.Println(left(s)) // https://example-1.example.com/a/c482dfad3573acff324c/list.txt
}
If you are prosessing only URLs, you can use Go's net/url library https://golang.org/pkg/net/url/ to parse the URL, truncate the Query and Fragment parts (Query would be parm1=value,parm2=value etc.), and extract the remaining portion scheme://host/path, as in the following example (https://play.golang.org/p/Ao0jU22NyA):
package main
import (
"fmt"
"net/url"
)
func main() {
u, _ := url.Parse("https://example-1.example.com/a/b/c/list.txt?parm1=value,parm2=https%3A%2F%2Fexample.com%2Fa%3Fparm1%3Dvalue%2Cparm2%3Dvalue#somefragment")
u.RawQuery, u.Fragment = "", ""
fmt.Printf("%s\n", u)
}
Output:
https://example-1.example.com/a/b/c/list.txt
I used regexp package extract string from string .
In this example I wanted to extract between and <\PERSON> , did this by re expression and and replaced and <\PERSON> by re1 expression.
for loop used for if there there are multiple match and re1 format used for replace.
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile(`<PERSON>(.*?)</PERSON>`)
string_l := "java -mx500m -cp stanford-ner.jar edu.stanford.nlp.ie.crf.CRFClassifier -loadClassifier classifiers/english.all.3class.distsim.crf.ser.gz -textFile PatrickYe.txt -outputFormat inlineXML 2> /dev/null I complained to <ORGANIZATION>Microsoft</ORGANIZATION> about <PERSON>Bill Gates</PERSON>.They told me to see the mayor of <PERSON>New York</PERSON>.,"
x := re.FindAllString(string_l, -1)
fmt.Println(x)
for v,st:= range x{
re1 := regexp.MustCompile(`<(.?)PERSON>`)
y1 := re1.ReplaceAllLiteralString(st,"")
fmt.Println(v,st," : sdf : ",y1)
}
}
Play with Go

Remove multiple items from a slice

I am trying to remove multiple items from a slice by using the Delete examples from here: http://code.google.com/p/go-wiki/wiki/SliceTricks
Here is the code I have:
package main
import "fmt"
import "net"
func main() {
a := []string{"72.14.191.202", "69.164.200.202", "72.14.180.202", "2600:3c00::22", "2600:3c00::32", "2600:3c00::12"}
fmt.Println(a)
for index, element := range a {
if net.ParseIP(element).To4() == nil {
//a = append(a[:index], a[index+1:]...)
a = a[:index+copy(a[index:], a[index+1:])]
}
}
fmt.Println(a)
}
While the code works fine if I have only one IPv6 address in the slice, it fails if there are more than one IPv6 address. It fails with the error "panic: runtime error: slice bounds out of range". What should I do to fix this code so it's able to delete all IPv6 addresses?
Your problem is that you are modifying the slice that you are iterating over. Below is your code a bit modified:
package main
import (
"fmt"
"net"
)
func main() {
a := []string{"72.14.191.202", "69.164.200.202", "72.14.180.202", "2600:3c00::22", "2600:3c00::32", "2600:3c00::12"}
fmt.Println(a)
for i := 0; i < len(a); i++ {
if net.ParseIP(a[i]).To4() == nil {
a = append(a[:i], a[i+1:]...)
//a = a[:i+copy(a[i:], a[i+1:])]
i-- // Since we just deleted a[i], we must redo that index
}
}
fmt.Println(a)
}
Playground
Just to raise the point : it is always tricky to alter the structure on which you are iterating.
A common way to avoid this is to build the end result in a new variable :
package main
import (
"fmt"
"net"
)
func main() {
a := []string{"72.14.191.202", "69.164.200.202", "72.14.180.202", "2600:3c00::22", "2600:3c00::32", "2600:3c00::12"}
fmt.Println(a)
var b []string
for _, ip := range a {
if net.ParseIP(ip).To4() != nil {
b = append(b, ip)
}
}
fmt.Println(b)
}
http://play.golang.org/p/7CLMPw_FQi

Decoding bytes array: index out of range

Running the following little program to decode a string:
package main
import (
"fmt"
"encoding/hex"
)
func main()
{
var answer []byte
b, e := hex.Decode(answer, []byte("98eh1298e1h182he"))
fmt.Println(b)
fmt.Println(e)
}
Results in panic: runtime error: index out of range, though that is not a very helpful error message. What am I doing wrong?
The same is true for encoding:
package main
import (
"fmt"
"encoding/hex"
)
func main()
{
var answer []byte
e := hex.Encode(answer, []byte("98eh1298e1h182he"))
fmt.Println(answer)
fmt.Println(e)
}
hex.Encode is going to write into the array answer which isn't allocated yet. This worked for me, though you might find a more elegant way to do this:
package main
import (
"fmt"
"encoding/hex"
)
func main() {
var src []byte = []byte("98ef1298e1f182fe")
answer := make([]byte, hex.DecodedLen(len(src)))
b, e := hex.Decode(answer, src)
fmt.Println(b)
fmt.Println(e)
fmt.Println(answer)
}
Running it:
$ go build s.go && ./s
8
<nil>
[152 239 18 152 225 241 130 254]

Get terminal size in Go

How to get tty size with Golang? I am trying do this with executing stty size command, but I can't craft code right.
package main
import (
"os/exec"
"fmt"
"log"
)
func main() {
out, err := exec.Command("stty", "size").Output()
fmt.Printf("out: %#v\n", out)
fmt.Printf("err: %#v\n", err)
if err != nil {
log.Fatal(err)
}
}
Output:
out: []byte{}
err: &exec.ExitError{ProcessState:(*os.ProcessState)(0xc200066520)}
2013/05/16 02:35:57 exit status 1
exit status 1
I think this is because Go spawns a process not related to the current tty, with which it is working. How can I relate the command to current terminal in order to get its size?
I just wanted to add a new answer since I ran into this problem recently. There is a terminal package which lives inside the official ssh package https://godoc.org/golang.org/x/crypto/ssh/terminal.
This package provides a method to easily get the size of a terminal.
width, height, err := terminal.GetSize(0)
0 would be the file descriptor of the terminal you want the size of. To get the fd or you current terminal you can always do int(os.Stdin.Fd())
Under the covers it uses a syscall to get the terminal size for the given fd.
I was stuck on a similar problem. Here is what I ended up with.
It doesn't use a subprocess, so might be desirable in some situations.
import (
"syscall"
"unsafe"
)
type winsize struct {
Row uint16
Col uint16
Xpixel uint16
Ypixel uint16
}
func getWidth() uint {
ws := &winsize{}
retCode, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
uintptr(syscall.Stdin),
uintptr(syscall.TIOCGWINSZ),
uintptr(unsafe.Pointer(ws)))
if int(retCode) == -1 {
panic(errno)
}
return uint(ws.Col)
}
It works if you give the child process access to the parent's stdin:
package main
import (
"os/exec"
"fmt"
"log"
"os"
)
func main() {
cmd := exec.Command("stty", "size")
cmd.Stdin = os.Stdin
out, err := cmd.Output()
fmt.Printf("out: %#v\n", string(out))
fmt.Printf("err: %#v\n", err)
if err != nil {
log.Fatal(err)
}
}
Yields:
out: "36 118\n"
err: <nil>
You can use golang.org/x/term package (https://pkg.go.dev/golang.org/x/term)
Example
package main
import "golang.org/x/term"
func main() {
if term.IsTerminal(0) {
println("in a term")
} else {
println("not in a term")
}
width, height, err := term.GetSize(0)
if err != nil {
return
}
println("width:", width, "height:", height)
}
Output
in a term
width: 228 height: 27
Since no one else here has yet to present a cross-platform solution that will work on both Windows and Unix, I went ahead and put together a library that supports both.
https://github.com/nathan-fiscaletti/consolesize-go
package main
import (
"fmt"
"github.com/nathan-fiscaletti/consolesize-go"
)
func main() {
cols, rows := consolesize.GetConsoleSize()
fmt.Printf("Rows: %v, Cols: %v\n", rows, cols)
}
If anyone's interested I made a package to make this easier.
https://github.com/wayneashleyberry/terminal-dimensions
package main
import (
"fmt"
terminal "github.com/wayneashleyberry/terminal-dimensions"
)
func main() {
x, _ := terminal.Width()
y, _ := terminal.Height()
fmt.Printf("Terminal is %d wide and %d high", x, y)
}
I have one implementation that uses tcell module, under the hood it will still use approach that based on calling native dlls, but if you're searching for terminal dimensions there is a great chance that you would need that package anyway:
package main
import (
"fmt"
"github.com/gdamore/tcell"
)
func main() {
screen, _ := tcell.NewScreen()
screen.Init()
w, h := screen.Size()
fmt.Println(w, h)
}

Resources