Decoding bytes array: index out of range - go

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]

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)

How to scan a big.Int from standard input in 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

Golang AES encryption

I am new to Go and I am trying out the crypto package.
My code looks like:
package main
import "fmt"
import . "crypto/aes"
func main() {
block, _ := NewCipher([]byte("randomkey"))
var dst = []byte{}
var src = []byte("senstive")
block.Encrypt(dst, src)
fmt.Println(string(src))
}
I get the following error:
panic: runtime error: invalid memory address or nil pointer dereference.
What am I doing wrong?
My code can be found at the Go playground
here
I fixed it:
package main
import "fmt"
import "crypto/aes"
func main() {
bc, err := aes.NewCipher([]byte("key3456789012345"))
if (err != nil) {
fmt.Println(err);
}
fmt.Printf("The block size is %d\n", bc.BlockSize())
var dst = make([]byte, 16)
var src = []byte("sensitive1234567")
bc.Encrypt(dst, src)
fmt.Println(dst)
}
In general, you should be checking error codes and carefully reading documentation of every function you call. Also, this is a block cypher so it requires blocks of bytes that are a specific size.

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

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