0

I want to create a dummy string of a given length to do a performance test. For example I want to first test with 1 KB of string and then may be 10 KB of string etc. I don't care which character (or rune?) it gets filled with. I understand that a string in Go is backed by byte array. So, I want the final string to be backed by a byte array of size equivalent of 1 KB (if I give 1024 as the argument).

For example, I tried the brute force code below:

...
    oneKBPayload := createPayload(1024, 'A')
...
//I don't mind even if the char argument is removed and 'A' is used for example 
func createPayload(len int, char rune) string {
    payload := make([]byte, len)
    for i := 0; i < len; i++ {
        payload = append(payload, byte(char))
    }
    return string(payload[:])
}

and it produced a result of (for 10 length)

"\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000AAAAAAAAAA"

I realize that it has something to do with the encoding. But how to fix this so that I create any string which is backed by a byte array of the given length so that when I write it over the network, I generate the intended payload.

icza
  • 389,944
  • 63
  • 907
  • 827
Amudhan
  • 696
  • 8
  • 18

1 Answers1

6

Your createPayload() creates a byte slice with the given length, which is filled with zeros by default (zero value). Then you append len number of runes to this slice, so the result will be double the length you intend to create (given the rune is less than 127), and that's why you see zeros then followed by the 'A' rune when printed.

If you change it to:

payload := make([]byte, 0, len)

Then the result will be what you want.

But easier would be to simply use strings.Repeat() which repeats a given string value n times. Repeat a one-rune (or more specifically a one-byte) string value n times, and you get what you want:

s := strings.Repeat("A", 10)
fmt.Println(len(s), s)

This will output (try it on the Go Playground):

10 AAAAAAAAAA

If you don't care about the content of the string only about its length, then simply convert a byte slice like this:

s := string(make([]byte, 1024))
fmt.Println(len(s))

Or alternatively like this:

s2 := string([]byte{1023: 0})
fmt.Println(len(s2))

Both prints 1024. Try them on the Go Playground.

If you do care about the content and you already have a byte slice allocated, this is how you can efficiently fill it: Is there analog of memset in go?

icza
  • 389,944
  • 63
  • 907
  • 827
  • Thank you! I tried strings.C (in GoLand) and couldn't find any Create kind of method. Didn't occur to me to look for Repeat method (strings.R would have suggested that). I will accept the answer in 5 mins (SOF restriction). – Amudhan Jan 08 '19 at 12:52