1

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:

here is the result

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?

jub0bs
  • 60,866
  • 25
  • 183
  • 186

2 Answers2

3

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)
}
rocka2q
  • 2,473
  • 4
  • 11
  • thanks a lot. Now I know that golang won't ignore the constant blank like C. And I shouldn't ignore the return value of function read which can help me specify the buffer size. – Carter Wang Feb 14 '22 at 12:54
-1

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.

hao
  • 639
  • 5
  • 11
  • You mean I should firstly get the size, declare a buffer with that size and then get the body. Right? I figure out this is a nice way. But I've got another question in the picture above. Why golang prints so many blanks? Shouldn't it stop printing when meeting the first blank? – Carter Wang Jan 24 '22 at 07:10
  • @CarterWang Why should golang stop printing when meeting the first blank? Blank is not empty or sign of stop.it is meaningful. In your program, buf is a pointer to a pile of memory and you just print every element in the memory, that's it. – hao Jan 24 '22 at 07:24