Go - convert string which represent binary number into int - go

I wrote a stupid solution for this, any better recipe?
As you can see lots of useless conversions there.
package main
import (
"fmt"
"strconv"
"math"
)
func conv(str string) int {
l := len(str)
result := 0.0
for i,n := range str {
number,_ := strconv.Atof64(string(n))
result += math.Exp2(float64(l-i-1))*number
}
return int(result)
}
func main() {
fmt.Println(conv("1001"))
}

You want the strconv.ParseInt function, which converts from an arbitrary base, into a given bit size.
package main
import (
"fmt"
"strconv"
)
func main() {
if i, err := strconv.ParseInt("1001", 2, 64); err != nil {
fmt.Println(err)
} else {
fmt.Println(i)
}
}
Playground

For example, on Go 1,
package main
import (
"fmt"
"strconv"
)
func main() {
i, err := strconv.ParseInt("1101", 2, 64)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(i)
}
Output:
13

Related

Insert slice into url link as text

I am trying to make a bot which sends mails. I got the following code. I am wondering, if it's possible to place the mails slice into this field seperated by a , ?
&bcc=
If my test.txt contains
test1#mail.com
test2#mail.com
I'd like the part of the link to contain &bcc=test1#mail.com,test2#mail.com
Is this doable with Go?
package main
import (
"bufio"
"fmt"
"log"
"os"
"os/exec"
)
func main() {
file, err := os.Open("test.txt")
if err != nil {
log.Fatal(err)
}
var mails []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
mails = append(mails, scanner.Text())
}
fmt.Println(mails)
exec.Command("xdg-open", "https://mail.google.com/mail/u/0/?fs=1&tf=cm&to=contact#test.com,&bcc=test1#mail.com,test2#mail.com&su=Hello+World!&body=This+Is+Just+An+Example").Run()
}
You can use "fmt.Sprintf()".It solves your problem.
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
file, err := os.Open("test.txt")
if err != nil {
log.Fatal(err)
}
var mails []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
mails = append(mails, scanner.Text())
}
sendMails := ""
for _, m := range mails {
sendMails += fmt.Sprintf("%s", m)
}
command := fmt.Sprintf("https://mail.google.com/mail/u/0/?fs=1&tf=cm&to=contact#test.com,&bcc=%s&su=Hello+World!&body=This+Is+Just+An+Example", sendMails)
fmt.Println(mails)
exec.Command("xdg-open", command).Run()
}

Different result when run io.Copy(os.Stdout, &r) consecutively in Golang

I am playing around Golang. About io.Copy
I put 2 consecutive io.Copy in the code, but i expect it output twice result(testtesttest). But the 2nd one is nil. Can anyone help explain why? tks
package main
import (
"io"
"os"
"strings"
"fmt"
)
type testReader struct {
w io.Reader
str string
}
func (tt *testReader) Read (b []byte) (n int, err error) {
io.Copy(os.Stdout, tt.w)
n, err = tt.w.Read(b)
if tt.w !=nil {
return 0,io.EOF
}
return
}
func main() {
s := strings.NewReader("testtesttest!!!")
r := testReader{s,"ttthhh"}
fmt.Println(&r)
io.Copy(os.Stdout, &r)
// s.Seek(0,0) // solution from Poy's answer
io.Copy(os.Stdout, &r)
}
I'm going to prune down the given example to (as there is a bit of noise):
package main
import (
"io"
"os"
"strings"
)
func main() {
s := strings.NewReader("testtesttest")
io.Copy(os.Stdout, s) // Will print "testtesttest"
io.Copy(os.Stdout, s) // Won't print anything
}
The reason the second copy won't output anything is the io.Reader (s) has already been read. Reading from a io.Reader is not idempotent (you can't call it twice to get the same results). It also doesn't have a way to "reset" it or anything.
As #JRLambert pointed out you have s.Seek() and s.Reset() to allow you to start reading again.
Quick addition to all the correct answers (#poy and #JRLambert) provided so far... Use io.TeeReader or io.MultiWriter for times when you would want to use io.Copy more than once. Below are some examples of using each.
Using io.TeeReader
package main
import (
"bytes"
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
)
func main() {
sourceFile, _ := os.Open("source/ebook.pdf")
var buf bytes.Buffer
tee := io.TeeReader(sourceFile, &buf)
process := func(sourceReader io.Reader) {
targetFile, _ := os.Create("target/ebook.pdf")
defer targetFile.Close()
if _, err := io.Copy(targetFile, sourceReader); err != nil {
fmt.Println(err)
}
}
process(tee)
fmt.Println(checksum(&buf))
}
func checksum(buf *bytes.Buffer) string {
h := md5.New()
b, _ := ioutil.ReadAll(buf)
if _, err := h.Write(b); err != nil {
fmt.Println(err)
}
return hex.EncodeToString(h.Sum(nil)[:16])
}
Using io.MultiWriter
package main
import (
"bytes"
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
)
func main() {
sourceFile, _ := os.Open("source/ebook.pdf")
process := func(sourceReader io.Reader) {
targetFile, _ := os.Create("target/ebook.pdf")
defer targetFile.Close()
var buf1, buf2 bytes.Buffer
w := io.MultiWriter(targetFile, &buf1, &buf2)
if _, err := io.Copy(w, sourceReader); err != nil {
fmt.Println(err)
}
fmt.Println(checksum(&buf1))
fmt.Println(checksum(&buf2))
}
process(sourceFile)
}
func checksum(buf *bytes.Buffer) string {
h := md5.New()
b, _ := ioutil.ReadAll(buf)
if _, err := h.Write(b); err != nil {
fmt.Println(err)
}
return hex.EncodeToString(h.Sum(nil)[:16])
}

How to run filepath.Walkfunc as a goroutine

I'm trying to parse a large image dataset. I'm using filepath.Walk ]and processing each file I find there. I'd like the filepath.
package main
import (
"fmt"
"image/color"
"image/png"
"math/rand"
"os"
)
var (
Black = color.Gray{0}
)
func getRandFloatNumber(min, max float32) float32 {
return (rand.Float32()*2 - min) * max
}
func openImage(path string, info os.FileInfo, err error) error {
infile, _ := os.Open(path)
defer infile.Close()
img, err := png.Decode(infile)
if err != nil {
return nil
}
array := make([]float32, 128*128)
for y := 0; y < 128; y++ {
for x := 0; x < 128; x++ {
c := color.GrayModel.Convert(img.At(x, y)).(color.Gray)
if c == Black {
array[x*y] = getRandFloatNumber(0.7, 0.95)
} else {
array[x*y] = getRandFloatNumber(0.1, 0.25)
}
}
}
fmt.Println(info.Name())
return nil
}
How to run openImage as a gorutine?
Or how to optimize this code?
You can't get filepath.Walk to call your function in a goroutine, but you can simply start a goroutine in your WalkFunc.
package main
import (
"os"
"path/filepath"
)
func main() {
filepath.Walk("/my/dir", func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
// Check more criteria if necessary. Also consider limiting the number
// of concurrent goroutines.
go openImage(path, info)
return nil
})
}
func openImage(path string, info os.FileInfo) {
}

In Go, can JSON marshaling of a well-defined type ever fail?

Given the following code:
package main
import (
"encoding/json"
"fmt"
"log"
)
type Employee struct {
Id int "json:id"
}
func main() {
b, err := json.Marshal(&Employee{Id: 2})
if err != nil {
log.Fatal("Couldn't marshal the Employee")
}
fmt.Println(string(b))
}
Can checking for the error be reliably ignored using the _ placeholder since the Employee struct is well defined. Theoretically it should never fail, so begs the question is it a good practice to ignore this type of error and save a little on this type of boilerplate error checking?
Ignoring would look like so:
package main
import (
"encoding/json"
"fmt"
)
type Employee struct {
Id int "json:id"
}
func main() {
b, _ := json.Marshal(&Employee{Id: 2})
fmt.Println(string(b))
}
Error handling and Go:
Proper error handling is an essential requirement of good software.
Normally your code won't fail. but if user Adds this MarshalJSON method reciver to your type, it fails:
func (t *Employee) MarshalJSON() ([]byte, error) {
if t.Id == 2 {
return nil, fmt.Errorf("Forbiden Id = %d", t.Id)
}
data := []byte(fmt.Sprintf(`{"Id":%d}`, t.Id))
return data, nil
}
This code Compiles, but fails on purpose just for Id == 2 (The Go Playground):
package main
import (
"encoding/json"
"fmt"
"log"
)
type Employee struct {
Id int "json:id"
}
func main() {
b, err := json.Marshal(&Employee{Id: 2})
if err != nil {
log.Fatal("Couldn't marshal the Employee", err)
}
fmt.Println(string(b))
}
func (t *Employee) MarshalJSON() ([]byte, error) {
if t.Id == 2 {
return nil, fmt.Errorf("Forbiden Id = %d", t.Id)
}
data := []byte(fmt.Sprintf(`{"Id":%d}`, t.Id))
return data, nil
}
Also this code Compiles, but fails (The Go Playground):
package main
import (
"encoding/json"
"fmt"
"log"
)
type Employee struct {
Id int "json:id"
}
func main() {
b, err := json.Marshal(&Employee{Id: 2})
if err != nil {
log.Fatal("Couldn't marshal the Employee")
}
fmt.Println(string(b))
}
func (t Employee) MarshalJSON() ([]byte, error) {
data := []byte(fmt.Sprint(t))
return data, nil
}
You can always write your own "wrapper" packages to compose behavior that might otherwise be boilerplate. For example, if you have a logging system set up, you might build a small package that looks like:
package json
import (
"encoding/json"
"log"
)
func TryMarshal(v interface{}) []byte {
b, err := json.Marshal(v)
if err != nil {
log.Println(err)
return nil
}
return b
}

Is it possible to do a conversion after assignment?

I'm wondering if there is any trick to avoid the xv identifier/allocation. Basically something like x, err := T1(strconv.Atoi("1"))
package main
import "fmt"
import "strconv"
type T1 int
func main() {
xv, err := strconv.Atoi("1")
if err != nil {
panic(err)
}
x := T1(xv)
fmt.Println(x)
}
For example, only x escapes to heap,
package main
import (
"fmt"
"strconv"
)
type T1 int
func atoi(a string) int {
i, err := strconv.Atoi(a)
if err != nil {
panic(err)
}
return i
}
func main() {
x := T1(atoi("1"))
fmt.Println(x)
}
Output:
1
No, I believe there is no such trick.
When I want to avoid declarations of unnecessary variables in the scope, and for one-off operations, I sometimes use this kind of anonymous function calls:
package main
import "fmt"
import "strconv"
type T1 int
func main() {
x, err := func() (T1, error) {
x, err := strconv.Atoi("1")
return T1(x), err
}()
fmt.Println(err, x)
}
On the other hand, if you need to perform a similar cast on many occasions, and not necessarily always as a result of the same call (like Atoi), you could create a simple function, which would do the conversion and pass through the error:
package main
import "fmt"
import "strconv"
type T1 int
func resToT1(n int, err error) (T1, error) {
return T1(n), err
}
func main() {
x, err := resToT1(strconv.Atoi("1"))
fmt.Println(err, x)
}

Resources