golang read line by line - go

I've started studying golang a bit and I'm absolutely unable to understand how I'm supposed to read line by line in the old-fashioned way:
while filehandler != EOF {
line_buffer = readline(filehandler)
}
I'm aware that I have to use bufio scanlines. This isn't what I am using as code, I'm merely trying to explain the idea.

use this:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
file, _ := os.Open("path/to_file")
fscanner := bufio.NewScanner(file)
for fscanner.Scan() {
fmt.Println(fscanner.Text())
}
}

Related

Is there a way to allow a user to delete a full word while reading a line in Go?

I am trying to create a shell in Go. I currently have this code that reads the os.Stdin and prints it out.
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
buf := bufio.NewReader(os.Stdin)
for {
fmt.Print("> ")
bytes, err := buf.ReadBytes('\n')
if err != nil {
panic(err)
}
fmt.Println(strings.TrimSuffix(string(bytes), "\n"))
}
}
However, while you are typing out your commands, I found that you can not use Command + Backspace to delete a full word like you can usually do in a shell. I found this issue to be pretty annoying and after looking at other similar questions on StackOverflow I saw that some people mentioned that the terminal needs to be in raw mode.
I have tried using termbox-go, but I was not able to get it working. If anyone could point me in the right direction it would be greatly appreciated.
Thanks.

How to run variable as shell script file

I need to run a variable as shell script file in golang. I tried like below code
package main
import (
"fmt"
"os/exec"
)
func main() {
var namespaceYaml string = `#!/bin/bash
docker verson`
out, err := exec.Command(namespaceYaml).Output()
fmt.Println(err, string(out))
}
But I cannot get any result. I cannot find where is the mistake.
Please anyone to fix this issue. Thanks in advance.
From official doc:
func Command(name string, arg ...string) *Cmd
Command returns the Cmd struct to execute the named program with the given arguments.
Try this:
package main
import (
"fmt"
"os/exec"
)
func main() {
out, err := exec.Command("docker", "version").Output()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Docker version is: %s\n", out)
}
Useful links for further details:
exec
examples
Note: make sure docker is installed on your machine.

what're Pipeline and TxPipeline redis functions in gloang

I want to perform an atomic transaction in redis using golang. How to do that ? What is the difference b/w Pileline and TxPieline and how to solve the problem using them.
I have visited the following link:
https://godoc.org/gopkg.in/redis.v5#example-Client-TxPipeline
But explanation is not elaborate.
Code from one of the examples from the library on how to use transaction.
package main
import (
"fmt"
"time"
"github.com/go-redis/redis"
)
var redisdb *redis.Client
func main() {
var incr *redis.IntCmd
_, err := redisdb.Pipelined(func(pipe redis.Pipeliner) error {
incr = pipe.Incr("pipelined_counter")
pipe.Expire("pipelined_counter", time.Hour)
return nil
})
fmt.Println(incr.Val(), err)
}

How to read multiple times from same io.Reader

I want to use request.Body(type io.ReadCloser) which is containing a image.
I dont want to use ioutil.ReadAll() as i want to write this body directly to the file as well as want to decode it, so i only want to use the reference to the content to pass to further function calls,
I tried creating multiple instances of reader for example shown below
package main
import (
"io/ioutil"
"log"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
a := &r
b := &r
log.Println(ioutil.ReadAll(*a))
log.Println(ioutil.ReadAll(*b))
}
but in second call it always results into nil.
Please help me how can i pass multiple separate reference for the same reader?
io.Reader is treated like a stream. Because of this you cannot read it twice. Imagine an incoming TCP connection - you cannot rewind what's coming in.
But you can use the io.TeeReader to duplicate the stream:
package main
import (
"bytes"
"io"
"io/ioutil"
"log"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
var buf bytes.Buffer
tee := io.TeeReader(r, &buf)
log.Println(ioutil.ReadAll(tee))
log.Println(ioutil.ReadAll(&buf))
}
Example on Go Playground
Edit: As #mrclx pointed out: You need to read from the TeeReader first, otherwise the buffer will be empty.
When you call ReadAll it's going to empty the buffer, so the second call will always return nothing. What you could do is save the result of ReadAll and reuse that in your functions. For example:
bytes, _ := ioutil.ReadAll(r);
log.Println(string(bytes))
When you read from ioutil.ReadAll(r) then, the content is gone. You can’t read from it a second time.
For an example:
var response *http.Response
//Read the content
rawBody, err := ioutil.ReadAll(response.Body)
if err != nil {
t.Error(err)
}
// Restore the io.ReadCloser to it's original state
response.Body = ioutil.NopCloser(bytes.NewBuffer(rawBody))
Technically, on one reader, you cannot read multiple times.
Even if you create different references but
when you read once it will be same object referred by all references.
so what you can do is read the content and store it in one variable.
Then use that variable as many times as you want.
This will print twice.
package main
import (
"io/ioutil"
"log"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
stringData, _ := ioutil.ReadAll(r)
log.Println(stringData)
log.Println(stringData)
}
Clone the Reader struct.
package main
import (
"io/ioutil"
"log"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
v := new(strings.Reader)
*v = *r
log.Println(ioutil.ReadAll(r))
log.Println(ioutil.ReadAll(v))
}

Golang for loop wont stop

So I am starting to learn the Go Programming Language and was hoping someone might be able to clarify why I'm getting the results I'm getting. I'm trying to have the program read input from the user and display it back until the user only enters the newline character.
package main
import (
"fmt"
"os"
"bufio"
"strings"
)
func main(){
inputBuff := bufio.NewReader(os.Stdin)
line,_ := inputBuff.ReadString('\n')
for (!strings.EqualFold(line,"\n")){
line,err := inputBuff.ReadString('\n')
if err!=nil {
fmt.Println(err)
}
fmt.Println(line)
fmt.Println(!strings.EqualFold(line,"\n"))
}
}
I am trying to read in full strings at a time so i thought the bufio would be better the using Scan. I added the last print to show that the method is returning false but the loop continues to execute. Any help would be greatly appreciated.
the line inside the loop is not the same line you initiated for the check. FTFY:
package main
import (
"fmt"
"os"
"bufio"
"strings"
)
func main(){
inputBuff := bufio.NewReader(os.Stdin)
line,_ := inputBuff.ReadString('\n')
var err error
for (!strings.EqualFold(line,"\n")){
line,err = inputBuff.ReadString('\n')
if err!=nil {
fmt.Println(err)
}
fmt.Println(line)
fmt.Println(!strings.EqualFold(line,"\n"))
}
You used the := assignment operator inside the loop, as in line, err := .....
This makes Go create a new symbol inside the the for loop with the name line. But the for's check is outside the inner scope of the loop code block. So it refers to the old line that was initiated outside the loop.
Changing the operator inside the loop to = doesn't create a new variable, but also doesn't init err, so I defined it beforehand too. err can be declared inside the loop but that's redundant.

Resources