Golang中使用append()和for循环时遇到的问题

huangapple go评论86阅读模式
英文:

Troubles with Golang append() and for loop

问题

我正在尝试使用缓冲区从conn接收数据。我在reader.Read周围有一个for循环,并且当reader返回一个标明EOF的err时,我将跳出循环。然而,似乎循环外的所有内容都不再定义。

我遇到的第二个问题是我无法追加两个切片。我尝试使用dataFile = append(dataFile, buff),但它说我不能使用[]byte。据我了解,你可以像那样追加两个切片。我错在哪里?

以下是代码:


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

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

  // 从conn创建一个新的reader
  reader := bufio.NewReader(conn)

  // 创建一个切片来保存所有传输的数据
  var dataFile []byte

  // 创建一个缓冲区来存储从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 // 当err返回EOF时跳出循环
  }
}
  
  err = os.WriteFile("data.txt", dataFile, 0666)

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

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



// 主函数开始 --------------------------------
func main(){

 // 监听本地端口80
 listener, err := net.Listen("tcp", ":5555")
 if err != nil {
   log.Fatalln("Unable to bind port")
 }

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

 // 处理多个连接
 for {
   conn, err := listener.Accept()
   if err != nil {
     log.Fatalln("Unable to accept connection...")
   }
   go readData(conn)
 }
}

这是收到的错误的图片
https://i.stack.imgur.com/7gJP9.png

英文:

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

答案1

得分: 1

这一行重新定义了bytesReturned,遮蔽了外部作用域中的定义:

  bytesReturned, err := reader.Read(buff)

使用:

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

代替。

对于追加操作,使用append(dataFile, buff...)

最后,err没有被定义,因为唯一使用的err在for循环中,并且由于它是一个不同的块,所以在外部不被识别。使用:

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

代替。

大部分程序可以用io.Copy函数来替代。

英文:

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.

答案2

得分: 0

追加读取的字节,而不是缓冲区本身。

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

注意使用slice表达式获取读取的字节的切片,并使用...将切片的内容作为append的参数。

使用短变量声明声明err并将os.WriteFile的结果赋值给err

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

使用缓冲区的长度报告读取的字节数:

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

通过使用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.")
}
英文:

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.")
}

huangapple
  • 本文由 发表于 2022年9月7日 05:53:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/73628104.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定