Simple way to write string and/or varible to file

I have been working through the tutorials found at https://gobyexample.com/writing-files; however, I am a little over my head.

Do I need to create a buffer for the item to be written to before writing to file? I have found so many ways to create a file and write to it that I am not sure what is really taken placing and going on.

I would be appreciative if someone can someone offer a simple Python -to- Golang examples that I can work through and discuss?

Thank you
RR

How would you write to a file without content (a buffer)?

I not sure to be honest. I am new to a buffer concept since in TCL and Perl you can write the variable/scalar directly to the file handler.

However, I hoped to find something similar in Go that I can use to write a variable directly to a file handler without having to worry about the buffer and the number of bytes stored in the buffer.

Also, I want to say - if you walk me through the buffer concept and concepts… I would be glad to learn how the buffer works and move forward with using a better approach to problems in coding.

RR

Actually, you can do the same in Go like you do in Perl. To do that, you need to open the file to get a handler for the file first, like so (it’s actually almost the same example in go by example site):

f, err := os.OpenFile(file, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
  panic(err) // i'm simplifying it here. you can do whatever you want.
}
defer f.Close()

Then, you can just write a string to the file like so:

f.WriteString("hello world")
f.WriteString("what's up?")

You can even write a formatted message to the file handler like so:

fmt.Fprintf(f, "my age is %d\n", 95)

Side Note: Please also read the article in this link.

1 Like

Let’s go through the gobyexample’s example:

  • ioutil.WriteFile is used when you want to write to a file once.

    • It creates or truncates the file, you can’t append).
  • os.Create is like os.OpenFile

    • It creates a file or truncates it if it exists and gives you a file handler
    • It calls OpenFile behind the scenes like so:
      OpenFile(filename, O_RDWR|O_CREATE|O_TRUNC, 0666)
  • f.Write is used when you want to write to the file using a byte slice.

  • f.WriteString is used when you want to write to the file using a string value

  • bufio.NewWriter is used when you want to write to a file successively in an efficient manner.

    • It’s because, it buffers your Write calls (it buffers them in memory), then at some points, it actually writes the accumulated buffer to the file. So, it doesn’t write each time you write, it writes in batches.
2 Likes

Hi Inancgumus,
Thank you for this example - this puts Go code concepts writing strings to a file into perspective for me; however, would you mind showing a simple writing with a buffer concept, so I can start thinking in better programming concepts and skills?

I still feel as if I am missing something with concepts, which I would normally not think of or concepts that are hidden in the background. I am working through the book Go in Action by William Kennedy from Manning publishing but it is slow going, yet I am just itching to get immersed more into Go.

Thank you
RR

Buffering is only needed when you’re writing a lot of data. What do you mean by the buffer concept? So I can help you.

To be honest I am not sure where to start. Do you have a source or links that will provide insight into using a Buffer? Also, when do you know when you should use a buffer?

Thank you
RR

I’ve found a link but it’s not only specific to Go, because buffering is a general computer-science/programming concept: https://www.quora.com/In-C-what-does-buffering-I-O-or-buffered-I-O-mean/answer/Robert-Love-1

This tells you what I told you before (see my explanation on bufio above). Buffers are mostly used for efficiency reasons.

1 Like
package main

import (
  "fmt"
  "os/exec"
  //"io"
)

func main() {
  c,_ := exec.Command("ping","-n","1","8.8.8.8").CombinedOutput()
  //fmt.Printf("%s",c)
  
  f, _ := os.Create("./output.txt")
  defer f.Close()
  
  ln, _ := f.WriteString(c)
  fmt.Printf("%s",ln)
}

Not sure why I am receiving
:13:11: undefined: os

In addition, I read your link, and I also started looking for some C documentation so i can learn about buffers.

Thank you
RR

This

import "os/exec"

does not also import os. You must add

import "os"

You can do the same like so:

In this example, I’m redirecting the Standard Out of the command to my file handle: f.

package main

import (
    "log"
    "os"
    "os/exec"
)

func main() {
	f, _ := os.Create("./output.txt")
	defer f.Close()

	c := exec.Command("ping", "-c", "1", "-n", "8.8.8.8")
	c.Stdout = f

	if err := c.Run(); err != nil {
		log.Fatal(err)
	}
}

For example, this is one of the places when you want to use buffering — if the command is producing a lot of output. You can do so easily like so:

package main

import (
    "bufio"
    "log"
    "os"
    "os/exec"
)

func main() {
  f, _ := os.Create("./output.txt")
  defer f.Close()

  buffered := bufio.NewWriter(f)

  c := exec.Command("ping", "-c", "1", "-n", "8.8.8.8")
  c.Stdout = buffered

  if err := c.Run(); err != nil {
	  log.Fatal(err)
  }

  if err := buffered.Flush(); err != nil {
	  log.Fatal(err)
  }
}

Thank you both for your code review. In addition, @inancgumus thank you for showing the ‘buffer’ example, which keeps me thinking in buffer concepts, but also it was very helpful getting the two different versions.

RR

Your solutions worked, but I wanted to continue to toy with this.

So I was experimenting with the code and started to try some different things, so I can learn and understand what is taking place here. Starting slow, and trying to understand the TYPE of objects that are getting returned. Due to the latter, I used the following code

fmt.Printf("%T\n",g)

I noticed I received the following: “[]uint8”, which I was not expecting. Still I found the following code, from another online forum:

:= string([]byte(c[:]))

From my research - “c” was getting returned as a byte array, not sure if ‘array’ is the right word; however, I realized that I needed to convert the []uint8 into string, which the above code did.

My code currently is the following:

package main

import (
  "fmt"
  "os/exec"
  //"io"
  "os"
)

func main() {
  //var c string
  
  c, _ := exec.Command("ping","-n","1","8.8.8.8").CombinedOutput()
  fmt.Printf("%T\n", c)
  g := string([]byte(c[:]))
  fmt.Printf("%T\n",g)
  
  //fmt.Printf("%s",c)
  
  //g := string(c)
  
  f, _ := os.Create("./output.txt")
  defer f.Close()
  
  ln, _ := f.WriteString(g)
  fmt.Printf("%s",ln)
}

It seems to work; however, I receive the following at the command prompt:

%!s(int=280)
I am not sure where this is coming or how his is getting generated. What would cause this output?

ln contains how many bytes written into the file, it’s an integer, but you’re trying to print it as a string.

Change the last line to (%d is for integers):

fmt.Printf("%d\n", ln)

You better take my complete course to learn Go methodologically :slight_smile:

@inancgumus,
I am little confused - I thought I converted the output of ‘c’ to a string and saved the new type to ‘g’ with the following line:

g := string([]byte(c[:]))

I didn’t understand what you’re trying to explain but this is unnecessary:

g := string([]byte(c[:]))

It’s because c is a byte slice ([]byte). So, doing the following is enough:

g := string(c)

But you don’t have to do that as well. f has a Write method which expects []byte, so you can directly call it like so:

c, _ := exec.Command("ping", "-n", "1", "8.8.8.8").CombinedOutput()

f, _ := os.Create("./output.txt")
defer f.Close()

ln, _ := f.Write(c)
fmt.Printf("%d", ln)

Then again, I recommend you to use the code that I sent you in one of my previous messages.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.