Home > Net >  Troubles with Golang append() and for loop
Troubles with Golang append() and for loop

Time:09-07

I am trying to use a buffer to receive data from conn. I have a for loop around reader.Read and will break the loop when the reader comes back with an err stating EOF. However, it seems everything outside of the loop is no longer defined.

The second issue I am running into is I cannot append two slices. I try and use dataFile = append(dataFile, buff) but it says that I cannot use []byte. To my understanding you are able to append two slices like that. Where am I going wrong?

Here is the code:


import (
  "fmt"
    "net"
    "log"
    "bufio"
    "os"
  "io"
)

func readData(conn net.Conn){
  fmt.Println("Reading data...\n")

  // Create a new reader from conn
  reader := bufio.NewReader(conn)

  // Make a slice to hold all data being transmitted
  var dataFile []byte

  // Create a buffer to store information as it comes across conn
  buff := make([]byte, 4096)

  for {
  bytesReturned, err := reader.Read(buff)
  dataFile = append(dataFile, buff)
  if err != nil {
    if err != io.EOF{
      log.Fatalln(err)
    }
    break //Break the loop when err returns EOF
  }
}
  
  err = os.WriteFile("data.txt", dataFile, 0666)

  if err != nil {
    log.Fatal(err)
  }
    

  fmt.Println("Read", bytesReturned,"bytes.")
}



// Start of main --------------------------------
func main(){

 //Listen on local port 80
 listener, err := net.Listen("tcp", ":5555")
 if err != nil {
   log.Fatalln("Unable to bind port")
 }

 fmt.Println("Port 5555 binded...\n")

 //handle multiple connections
 for {
   conn, err := listener.Accept()
   if err != nil {
     log.Fatalln("Unable to accept connection...")
   }
   go readData(conn)
 }
}

Here is a picture of the errors being received https://i.stack.imgur.com/7gJP9.png

CodePudding user response:

This line redefines bytesReturned, shadowing the definition in the outer scope:

  bytesReturned, err := reader.Read(buff)

Use:

var err error
bytesReturned, err = reader.Read(buff)

instead.

For appending, use append(dataFile, buff...)

Finally, err is not defined, because the only err used is in the for-loop, and since it is a different block, that err is not recognized outside. Use:

  err := os.WriteFile("data.txt", dataFile, 0666)

Instead.

Most of the program can be replaced with a call to io.Copy.

CodePudding user response:

Append the bytes read, not the buffer itself.

    bytesReturned, err := reader.Read(buff)
    dataFile = append(dataFile, buff[:bytesReturned]...)

Note the use of the slice expression to get a slice of the bytes read and the ... to specify the contents of the slice as the arguments to append.

Use a short variable declaration to declare err and assign the result of os.WriteFile to err.

err := os.WriteFile("data.txt", dataFile, 0666)
if err != nil {
  log.Fatal(err)
}

Use the length of the buffer to report the number of bytes read:

fmt.Println("Read", len(datafile),"bytes.")

Simplify the code by using io.ReadAll:

func readData(conn net.Conn) {
    fmt.Println("Reading data...\n")
    dataFile, err := io.ReadAll(conn)
    if err != io.EOF {
        log.Fatalln(err)
    }
    err = os.WriteFile("data.txt", dataFile, 0666)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Read", len(dataFile), "bytes.")
}
  •  Tags:  
  • go
  • Related