Alternate letters to UpperCase
I think both your solution and your testing are fine.

A couple of test cases I would add (but your solution also passes them):


a string starting with BOM, e.g. {"\xef\xbb\xbfhi", "\xef\xbb\xbfHi"}
a string which is not a valid UTF-8 string, e.g. {"h\xffi", "H\xef\xbf\xbdi"}
a string with multiple invalid UTF-8 bytes, e.g. {"h\xff\xffi", "H\xef\xbf\xbd\xef\xbf\xbdi"}


Explaining the invalid UTF-8 strings: Since you are converting your input string to runes, invalid UTF-8 bytes are reported as a value of 0xfffd (the Unicode replacement character), which when encoded as UTF-8 (happens when you convert []rune back to string) results in a sequence of []byte{0xef, 0xbf, 0xbd}; this is what the invalid 0xff byte is compared to in the test case.

Performance wise I would use a string => []rune conversion as you not only need the runes, but you also want to convert them back to a string. Using append() is slower, and it has to assign a slice value (a descriptor) at each rune.

Also note that if we convert the string to []rune, we only need to assign (overwrite) new runes which are converted to their upper case:

This is how I would do it:

func AlternateCase(s string) string {
    rs, upper := []rune(s), false
    for i, r := range rs {
        if unicode.IsLetter(r) {
            if upper = !upper; upper {
                rs[i] = unicode.ToUpper(r)
            }
        }
    }
    return string(rs)
}