当使用fmt.Printf()时,会显示很多空格。

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

when using fmt.Printf() many blanks are displayed

问题

我正在尝试使用Go语言完成一个回显服务器。服务器代码如下:

// 使用TCP回显时间
func main() {
    // 监听本地的TCP端口8000
    listener, err := net.Listen("tcp", "localhost:8000")
    if err != nil {
        fmt.Fprintf(os.Stderr, "监听错误,%s", err)
        return
    }
    for {
        // 接受连接
        connection, err := listener.Accept()
        if err != nil {
            fmt.Fprintf(os.Stderr, "监听错误,%s\n", err)
        } else {
            handle(connection)
        }
    }
}

// 处理TCP连接
// 每隔一秒返回当前时间
func handle(connection net.Conn) {
    defer connection.Close()
    for {
        // 返回写入的字节数和错误
        if _, err := fmt.Fprintf(connection, time.Now().Format("15:04:05\n")); err != nil {
            // 写入错误,可能是客户端关闭了连接
            fmt.Fprintf(os.Stderr, "%s 关闭连接\n", connection.RemoteAddr())
            break
        }
        // 等待一秒
        time.Sleep(1 * time.Second)
    }
}

客户端代码如下:

package main

const (
    proto = "tcp"
    addr  = "localhost:8000"
)

func main() {
    // 客户端连接到TCP端口localhost:8000
    connection, err := net.Dial(proto, addr)
    if err != nil {
        fmt.Fprintf(os.Stderr, "连接到 %s 错误,%s", addr, err)
    } else {
        buf := make([]byte, 1024)
        for {
            if _, err := connection.Read(buf); err != nil {
                fmt.Fprintf(os.Stderr, "从 %s 读取错误,%s\n", addr, err)
                break
            } else {
                fmt.Printf("数据:%s 结束\n", buf)
            }
        }
    }
}

当我运行我的代码时,得到了如下结果:

当使用fmt.Printf()时,会显示很多空格。

我不知道为什么会显示这么多空白字符。我猜可能是内置函数make导致的,但为什么Go语言默认会在字符串末尾显示这么多空白字符,而其他高级语言不会呢?你能解释并修复这个问题吗?

英文:

I'm trying to complete an echo server using golang.
server like this:

// use tcp to echo time
func main() {
	// listen tcp localhost:8000
	listener, err := net.Listen("tcp", "localhost:8000")
	if err != nil {
		fmt.Fprintf(os.Stderr, "listen error, %s", err)
		return
	}
	for {
		// accept
		connection, err := listener.Accept()
		if err != nil {
			fmt.Fprintf(os.Stderr, "listen error, %s\n", err)
		} else {
			handle(connection)
		}
	}
}

// handle the tcp connection
// return the time in one second gap
func handle(connection net.Conn) {
	defer connection.Close()
	for {
		// return written bytes, err
		if _, err := fmt.Fprintf(connection, time.Now().Format("15:04:05\n")); err != nil {
			// write error, probably the client close the connection
			fmt.Fprintf(os.Stderr, "%s close connection\n", connection.RemoteAddr())
			break
		}
		// wait one second
		time.Sleep(1 * time.Second)
	}
}

client like this

package main

const (
	proto = "tcp"
	addr  = "localhost:8000"
)

func main() {
	// client connect to tcp localhost:8000
	connection, err := net.Dial(proto, addr)
	if err != nil {
		fmt.Fprintf(os.Stderr, "connect to %s error, %s", addr, err)
	} else {
		buf := make([]byte, 1024)
		for {
			if _, err := connection.Read(buf); err != nil {
				fmt.Fprintf(os.Stderr, "read from %s error, %s\n", addr, err)
				break
			} else {
				fmt.Printf("data:%s ending\n", buf)
			}
		}
	}

}

When I run my code I get the following result:

当使用fmt.Printf()时,会显示很多空格。

I have no idea why so many blanks are shown.
I guess it's probably caused by the built-in function make, but why golang by default, displays so many blanks at the end of a string, unlike other high-level languages?
Could explain this and fix it?

答案1

得分: 3

Read返回n,表示读取的字节数。不要忽略它。将其读入长度为cap(buf)的缓冲区:buf[:cap(buf)]。然后使用n来更新缓冲区的长度:buf = buf[:n]

buf := make([]byte, 0, 1024)
for {
	n, err := connection.Read(buf[:cap(buf)])
	buf = buf[:n]
	if err != nil {
		fmt.Fprintf(os.Stderr, "从%s读取错误,%s\n", addr, err)
		break
	}
	fmt.Printf("数据:%s 结束\n", buf)
}
英文:

Read returns n, the number of bytes read. Don't ignore it. Read into a buffer of length cap(buf): buf[:cap(buf)]. Then use n to update the buffer length: buf = buf[:n].

buf := make([]byte, 0, 1024)
for {
	n, err := connection.Read(buf[:cap(buf)])
	buf = buf[:n]
	if err != nil {
		fmt.Fprintf(os.Stderr, "read from %s error, %s\n", addr, err)
		break
	}
	fmt.Printf("data:%s ending\n", buf)
}

答案2

得分: -1

你是对的,内置的make函数会声明一个长度和容量都为1024的切片。更好的处理方法是使用一个协议,该协议可以首先读取消息体的大小,然后声明适合响应体的大小。

英文:

You are right, built-in make declare a slice with length and capacity equals to 1024.The better way to deal with such info is to use a protocol which can first read the size of the body, and declare the fit size of the reponse body.

huangapple
  • 本文由 发表于 2022年1月24日 12:54:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/70829174.html
匿名

发表评论

匿名网友

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

确定